diff options
author | msmith <msmith@FreeBSD.org> | 2002-03-07 09:55:41 +0000 |
---|---|---|
committer | msmith <msmith@FreeBSD.org> | 2002-03-07 09:55:41 +0000 |
commit | eea0ae24b995a9c7c9132c8ed91df3e2f640ef18 (patch) | |
tree | aacb41e66b3d51310841948ae91276de9e3db52f /sys | |
parent | 955b896bbcf515a09eb75d0fc1b6d859e8c39f8e (diff) | |
download | FreeBSD-src-eea0ae24b995a9c7c9132c8ed91df3e2f640ef18.zip FreeBSD-src-eea0ae24b995a9c7c9132c8ed91df3e2f640ef18.tar.gz |
Update for the 6.9 firmware family (6xxx controllers), as well as for
the upcoming 7.4 family (7xxx controllers).
- improved error reporting and handling
- more diagnostic output
- add extra command packet definitions
- merge sources again with -stable
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/twe/twe.c | 70 | ||||
-rw-r--r-- | sys/dev/twe/twe_freebsd.c | 30 | ||||
-rw-r--r-- | sys/dev/twe/twe_tables.h | 20 | ||||
-rw-r--r-- | sys/dev/twe/twereg.h | 30 | ||||
-rw-r--r-- | sys/dev/twe/twevar.h | 2 |
5 files changed, 132 insertions, 20 deletions
diff --git a/sys/dev/twe/twe.c b/sys/dev/twe/twe.c index a8d7164..75c0808 100644 --- a/sys/dev/twe/twe.c +++ b/sys/dev/twe/twe.c @@ -115,6 +115,7 @@ int twe_setup(struct twe_softc *sc) { struct twe_request *tr; + u_int32_t status_reg; int i; debug_called(4); @@ -149,6 +150,12 @@ twe_setup(struct twe_softc *sc) } /* + * 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)) { @@ -566,6 +573,8 @@ twe_ioctl(struct twe_softc *sc, int cmd, void *addr) twe_reset(sc); break; + /* XXX implement ATA PASSTHROUGH */ + /* nothing we understand */ default: error = ENOTTY; @@ -919,12 +928,16 @@ twe_reset(struct twe_softc *sc) 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(); @@ -1178,10 +1191,11 @@ twe_soft_reset(struct twe_softc *sc) 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); @@ -1586,6 +1600,14 @@ twe_check_bits(struct twe_softc *sc, u_int32_t status_reg) 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); @@ -1616,7 +1638,7 @@ twe_format_aen(struct twe_softc *sc, u_int16_t aen) if (!bootverbose) return(NULL); /* FALLTHROUGH */ - case 'p': + case 'a': return(msg); case 'c': @@ -1627,6 +1649,12 @@ twe_format_aen(struct twe_softc *sc, u_int16_t aen) 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: @@ -1660,25 +1688,41 @@ twe_report_request(struct twe_request *tr) } 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); diff --git a/sys/dev/twe/twe_freebsd.c b/sys/dev/twe/twe_freebsd.c index 242950d..1fffe4e 100644 --- a/sys/dev/twe/twe_freebsd.c +++ b/sys/dev/twe/twe_freebsd.c @@ -90,7 +90,7 @@ static struct cdevsw twe_cdevsw = { * 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 @@ twe_open(dev_t dev, int flags, int fmt, struct thread *td) * 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 @@ twe_close(dev_t dev, int flags, int fmt, struct thread *td) * 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 @@ twe_attach_drive(struct twe_softc *sc, struct twe_drive *dr) } /******************************************************************************** + * 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 @@ static int disks_registered = 0; * 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 @@ twed_open(dev_t dev, int flags, int fmt, struct thread *td) * 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; diff --git a/sys/dev/twe/twe_tables.h b/sys/dev/twe/twe_tables.h index aa1ab02..116a8da 100644 --- a/sys/dev/twe/twe_tables.h +++ b/sys/dev/twe/twe_tables.h @@ -118,7 +118,7 @@ struct twe_code_lookup twe_table_aen[] = { {"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 @@ struct twe_code_lookup twe_table_aen[] = { {"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} }; diff --git a/sys/dev/twe/twereg.h b/sys/dev/twe/twereg.h index e7136df..12ce0d6 100644 --- a/sys/dev/twe/twereg.h +++ b/sys/dev/twe/twereg.h @@ -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 @@ typedef struct 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 @@ typedef union 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 @@ typedef struct u_int8_t parameter_size_bytes; u_int8_t data[0]; } TWE_Param __attribute__ ((packed)); + diff --git a/sys/dev/twe/twevar.h b/sys/dev/twe/twevar.h index 84d41dd..3c0d6b3 100644 --- a/sys/dev/twe/twevar.h +++ b/sys/dev/twe/twevar.h @@ -145,6 +145,8 @@ extern void twe_disable_interrupts(struct twe_softc *sc); /* disable controller 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 */ |