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/dev/twe/twe.c | |
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/dev/twe/twe.c')
-rw-r--r-- | sys/dev/twe/twe.c | 70 |
1 files changed, 57 insertions, 13 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); |