Index: twe.c =================================================================== RCS file: /host/ziplok/local0/cvs/src/sys/dev/twe/twe.c,v retrieving revision 1.9 diff -u -r1.9 twe.c --- twe.c 7 May 2001 21:46:44 -0000 1.9 +++ twe.c 18 Feb 2002 09:17:40 -0000 @@ -111,6 +111,7 @@ twe_setup(struct twe_softc *sc) { struct twe_request *tr; + u_int32_t status_reg; int i; debug_called(4); @@ -145,6 +146,12 @@ } /* + * Check status register for errors, clear them. + */ + status_reg = TWE_STATUS(sc); + twe_check_bits(sc, status_reg); + + /* * Wait for the controller to come ready. */ if (twe_wait_status(sc, TWE_STATUS_MICROCONTROLLER_READY, 60)) { @@ -562,6 +569,8 @@ twe_reset(sc); break; + /* XXX implement ATA PASSTHROUGH */ + /* nothing we understand */ default: error = ENOTTY; @@ -911,12 +920,16 @@ struct twe_request *tr; int i, s; - twe_printf(sc, "controller reset in progress...\n"); + /* + * Sleep for a short period to allow AENs to be signalled. + */ + tsleep(NULL, PRIBIO, "twereset", hz); /* * Disable interrupts from the controller, and mask any accidental entry * into our interrupt handler. */ + twe_printf(sc, "controller reset in progress...\n"); twe_disable_interrupts(sc); s = splbio(); @@ -1170,10 +1183,11 @@ TWE_SOFT_RESET(sc); - if (twe_wait_status(sc, TWE_STATUS_ATTENTION_INTERRUPT, 15)) { + if (twe_wait_status(sc, TWE_STATUS_ATTENTION_INTERRUPT, 30)) { twe_printf(sc, "no attention interrupt\n"); return(1); } + TWE_CONTROL(sc, TWE_CONTROL_CLEAR_ATTENTION_INTERRUPT); if (twe_drain_aen_queue(sc)) { twe_printf(sc, "can't drain AEN queue\n"); return(1); @@ -1578,6 +1592,14 @@ lastwarn[1] = time_second; } result = 1; + if (status_reg & TWE_STATUS_PCI_PARITY_ERROR) { + twe_printf(sc, "PCI parity error: Reseat card, move card or buggy device present."); + twe_clear_pci_parity_error(sc); + } + if (status_reg & TWE_STATUS_PCI_ABORT) { + twe_printf(sc, "PCI abort, clearing."); + twe_clear_pci_abort(sc); + } } return(result); @@ -1608,7 +1630,7 @@ if (!bootverbose) return(NULL); /* FALLTHROUGH */ - case 'p': + case 'a': return(msg); case 'c': @@ -1619,6 +1641,12 @@ msg, TWE_AEN_UNIT(aen)); } return(buf); + + case 'p': + sprintf(buf, "twe%d: port %d: %s", device_get_unit(sc->twe_dev), TWE_AEN_UNIT(aen), + msg); + return(buf); + case 'x': default: @@ -1652,25 +1680,41 @@ } else if (cmd->generic.status > TWE_STATUS_FATAL) { /* * Fatal errors that don't require controller reset. + * + * We know a few special flags values. */ - twe_printf(sc, "command returned fatal status - %s (flags = 0x%x)\n", - twe_describe_code(twe_table_status, cmd->generic.status), - cmd->generic.flags); - result = 1; + switch (cmd->generic.flags) { + case 0x1b: + device_printf(sc->twe_drive[cmd->generic.unit].td_disk, + "drive timeout"); + break; + case 0x51: + device_printf(sc->twe_drive[cmd->generic.unit].td_disk, + "unrecoverable drive error"); + break; + default: + device_printf(sc->twe_drive[cmd->generic.unit].td_disk, + "controller error - %s (flags = 0x%x)\n", + twe_describe_code(twe_table_status, cmd->generic.status), + cmd->generic.flags); + result = 1; + } } else if (cmd->generic.status > TWE_STATUS_WARNING) { /* * Warning level status. */ - twe_printf(sc, "command returned warning status - %s (flags = 0x%x)\n", - twe_describe_code(twe_table_status, cmd->generic.status), - cmd->generic.flags); + device_printf(sc->twe_drive[cmd->generic.unit].td_disk, + "warning - %s (flags = 0x%x)\n", + twe_describe_code(twe_table_status, cmd->generic.status), + cmd->generic.flags); } else if (cmd->generic.status > 0x40) { /* * Info level status. */ - twe_printf(sc, "command returned info status: %s (flags = 0x%x)\n", - twe_describe_code(twe_table_status, cmd->generic.status), - cmd->generic.flags); + device_printf(sc->twe_drive[cmd->generic.unit].td_disk, + "attention - %s (flags = 0x%x)\n", + twe_describe_code(twe_table_status, cmd->generic.status), + cmd->generic.flags); } return(result); Index: twe_freebsd.c =================================================================== RCS file: /host/ziplok/local0/cvs/src/sys/dev/twe/twe_freebsd.c,v retrieving revision 1.11 diff -u -r1.11 twe_freebsd.c --- twe_freebsd.c 13 Nov 2001 01:08:54 -0000 1.11 +++ twe_freebsd.c 18 Feb 2002 09:18:28 -0000 @@ -90,7 +90,7 @@ * Accept an open operation on the control device. */ static int -twe_open(dev_t dev, int flags, int fmt, struct thread *td) +twe_open(dev_t dev, int flags, int fmt, d_thread_t *td) { int unit = minor(dev); struct twe_softc *sc = devclass_get_softc(twe_devclass, unit); @@ -103,7 +103,7 @@ * Accept the last close on the control device. */ static int -twe_close(dev_t dev, int flags, int fmt, struct thread *td) +twe_close(dev_t dev, int flags, int fmt, d_thread_t *td) { int unit = minor(dev); struct twe_softc *sc = devclass_get_softc(twe_devclass, unit); @@ -116,7 +116,7 @@ * Handle controller-specific control operations. */ static int -twe_ioctl_wrapper(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td) +twe_ioctl_wrapper(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, d_thread_t *td) { struct twe_softc *sc = (struct twe_softc *)dev->si_drv1; @@ -513,6 +513,26 @@ } /******************************************************************************** + * Clear a PCI parity error. + */ +void +twe_clear_pci_parity_error(struct twe_softc *sc) +{ + TWE_CONTROL(sc, TWE_CONTROL_CLEAR_PARITY_ERROR); + pci_write_config(sc->twe_dev, PCIR_STATUS, TWE_PCI_CLEAR_PARITY_ERROR, 2); +} + +/******************************************************************************** + * Clear a PCI abort. + */ +void +twe_clear_pci_abort(struct twe_softc *sc) +{ + TWE_CONTROL(sc, TWE_CONTROL_CLEAR_PCI_ABORT); + pci_write_config(sc->twe_dev, PCIR_STATUS, TWE_PCI_CLEAR_PCI_ABORT, 2); +} + +/******************************************************************************** ******************************************************************************** Disk device ******************************************************************************** @@ -599,7 +619,7 @@ * for opens on subdevices (eg. slices, partitions). */ static int -twed_open(dev_t dev, int flags, int fmt, struct thread *td) +twed_open(dev_t dev, int flags, int fmt, d_thread_t *td) { struct twed_softc *sc = (struct twed_softc *)dev->si_drv1; struct disklabel *label; @@ -632,7 +652,7 @@ * Handle last close of the disk device. */ static int -twed_close(dev_t dev, int flags, int fmt, struct thread *td) +twed_close(dev_t dev, int flags, int fmt, d_thread_t *td) { struct twed_softc *sc = (struct twed_softc *)dev->si_drv1; Index: twe_tables.h =================================================================== RCS file: /host/ziplok/local0/cvs/src/sys/dev/twe/twe_tables.h,v retrieving revision 1.1 diff -u -r1.1 twe_tables.h --- twe_tables.h 25 Oct 2000 06:59:05 -0000 1.1 +++ twe_tables.h 18 Feb 2002 08:49:39 -0000 @@ -118,7 +118,7 @@ {"q queue empty", 0x00}, {"q soft reset", 0x01}, {"c degraded mirror", 0x02}, - {"p controller error", 0x03}, + {"a controller error", 0x03}, {"c rebuild fail", 0x04}, {"c rebuild done", 0x05}, {"c incomplete unit", 0x06}, @@ -127,7 +127,23 @@ {"c drive timeout", 0x09}, {"c drive error", 0x0a}, {"c rebuild started", 0x0b}, - {"p aen queue full", 0xff}, + {"c init started", 0x0c}, + {"c logical unit deleted", 0x0d}, + {"p SMART threshold exceeded", 0x0f}, + {"p ATA UDMA downgrade", 0x21}, + {"p ATA UDMA upgrade", 0x22}, + {"p sector repair occurred", 0x23}, + {"a SBUF integrity check failure", 0x24}, + {"p lost cached write", 0x25}, + {"p drive ECC error detected", 0x26}, + {"p DCB checksum error", 0x27}, + {"p DCB unsupported version", 0x28}, + {"c verify started", 0x29}, + {"c verify failed", 0x2a}, + {"c verify complete", 0x2b}, + {"p overwrote bad sector during rebuild", 0x2c}, + {"p encountered bad sector during rebuild", 0x2d}, + {"a aen queue full", 0xff}, {NULL, 0}, {"x unknown AEN", 0} }; Index: twereg.h =================================================================== RCS file: /host/ziplok/local0/cvs/src/sys/dev/twe/twereg.h,v retrieving revision 1.5 diff -u -r1.5 twereg.h --- twereg.h 7 May 2001 21:46:44 -0000 1.5 +++ twereg.h 18 Feb 2002 09:18:57 -0000 @@ -47,6 +47,8 @@ #define TWE_CONTROL_ENABLE_INTERRUPTS 0x00000080 #define TWE_CONTROL_DISABLE_INTERRUPTS 0x00000040 #define TWE_CONTROL_ISSUE_HOST_INTERRUPT 0x00000020 +#define TWE_CONTROL_CLEAR_PARITY_ERROR 0x00800000 +#define TWE_CONTROL_CLEAR_PCI_ABORT 0x00100000 #define TWE_SOFT_RESET(sc) TWE_CONTROL(sc, TWE_CONTROL_ISSUE_SOFT_RESET | \ TWE_CONTROL_CLEAR_HOST_INTERRUPT | \ @@ -100,6 +102,8 @@ #define TWE_VENDOR_ID 0x13C1 #define TWE_DEVICE_ID 0x1000 #define TWE_DEVICE_ID_ASIC 0x1001 +#define TWE_PCI_CLEAR_PARITY_ERROR 0xc100 +#define TWE_PCI_CLEAR_PCI_ABORT 0x2000 /* command packet opcodes */ #define TWE_OP_NOP 0x00 @@ -123,6 +127,8 @@ #define TWE_OP_SECTOR_INFO 0x1a #define TWE_OP_AEN_LISTEN 0x1c #define TWE_OP_CMD_PACKET 0x1d +#define TWE_OP_ATA_PASSTHROUGH 0x1e +#define TWE_OP_CMD_WITH_DATA 0x1f /* command status values */ #define TWE_STATUS_RESET 0xff /* controller requests reset */ @@ -138,6 +144,8 @@ #define TWE_SHUTDOWN_MESSAGE_CREDITS 0x001 #define TWE_INIT_COMMAND_PACKET_SIZE 0x3 #define TWE_MAX_SGL_LENGTH 62 +#define TWE_MAX_ATA_SGL_LENGTH 60 +#define TWE_MAX_PASSTHROUGH 4096 #define TWE_Q_LENGTH TWE_INIT_MESSAGE_CREDITS #define TWE_Q_START 0 #define TWE_MAX_RESET_TRIES 3 @@ -272,6 +280,26 @@ u_int8_t unit:4; u_int8_t host_id:4; u_int8_t status; + u_int16_t param; + u_int16_t features; + u_int16_t sector_count; + u_int16_t sector_num; + u_int16_t cylinder_lo; + u_int16_t cylinder_hi; + u_int8_t drive_head; + u_int8_t command; + TWE_SG_Entry sgl[TWE_MAX_ATA_SGL_LENGTH]; +} TWE_Command_ATA __attribute__ ((packed)); + +typedef struct +{ + u_int8_t opcode:5; + u_int8_t sgl_offset:3; + u_int8_t size; + u_int8_t request_id; + u_int8_t unit:4; + u_int8_t host_id:4; + u_int8_t status; u_int8_t flags; #define TWE_FLAGS_SUCCESS 0x00 #define TWE_FLAGS_INFORMATIONAL 0x01 @@ -290,6 +318,7 @@ TWE_Command_CHECKSTATUS checkstatus; TWE_Command_REBUILDUNIT rebuildunit; TWE_Command_SETATAFEATURE setatafeature; + TWE_Command_ATA ata; TWE_Command_Generic generic; u_int8_t pad[512]; } TWE_Command; @@ -460,3 +489,4 @@ u_int8_t parameter_size_bytes; u_int8_t data[0]; } TWE_Param __attribute__ ((packed)); + Index: twevar.h =================================================================== RCS file: /host/ziplok/local0/cvs/src/sys/dev/twe/twevar.h,v retrieving revision 1.4 diff -u -r1.4 twevar.h --- twevar.h 7 May 2001 21:46:44 -0000 1.4 +++ twevar.h 18 Feb 2002 08:43:02 -0000 @@ -145,6 +145,8 @@ extern void twe_attach_drive(struct twe_softc *sc, struct twe_drive *dr); /* attach drive when found in twe_init */ +extern void twe_clear_pci_parity_error(struct twe_softc *sc); +extern void twe_clear_pci_abort(struct twe_softc *sc); extern void twed_intr(twe_bio *bp); /* return bio from core */ extern struct twe_request *twe_allocate_request(struct twe_softc *sc); /* allocate request structure */ extern void twe_free_request(struct twe_request *tr); /* free request structure */