From: David van Moolenbroek Date: Wed, 13 Feb 2013 14:22:45 +0000 (+0000) Subject: ahci: device detection rewrite X-Git-Tag: v3.2.1~8 X-Git-Url: http://zhaoyanbai.com/repos/?a=commitdiff_plain;h=eb89b33d39afea54862aee9986783a7f20463c8b;p=minix.git ahci: device detection rewrite - do not start a port before the BSY and DRQ flags have been cleared; as such, poll on device status rather than signature availability. - change "ahci_sig_timeout" to "ahci_device_timeout" variable setting accordingly; this variable determines the polling duration before a newly attached device is given up on, and uses 30 seconds as default; - use port connect changes (PCS/X/DET->1h) to kick off polling for an attached device; detachment is still detected by means of PhyRdy status changes (PRCS/N/DET<->3h). --- diff --git a/drivers/ahci/ahci.c b/drivers/ahci/ahci.c index 4af5b1210..cf2b628e1 100644 --- a/drivers/ahci/ahci.c +++ b/drivers/ahci/ahci.c @@ -31,7 +31,7 @@ * | | | ^ | * v v | | | * +----------+ +----------+ +----------+ +----------+ | - * | NO_DEV | --> | WAIT_SIG | --> | WAIT_ID | --> | GOOD_DEV | | + * | NO_DEV | --> | WAIT_DEV | --> | WAIT_ID | --> | GOOD_DEV | | * +----------+ +----------+ +----------+ +----------+ | * ^ | | | | * +----------------+----------------+----------------+--------+ @@ -60,6 +60,14 @@ * closed and reopened. Removable media are not locked in the drive while * opened, because the driver author is uncomfortable with that concept. * + * Ports may leave the group of states where a device is connected (that is, + * WAIT_ID, GOOD_DEV, and BAD_DEV) in two ways: either due to a hot-unplug + * event, or due to a hard reset after a serious failure. For simplicity, we + * we perform a hard reset after a hot-unplug event as well, so that the link + * to the device is broken. Thus, in both cases, a transition to NO_DEV is + * made, after which the link to the device may or may not be reestablished. + * In both cases, ongoing requests are cancelled and the BARRIER flag is set. + * * The following table lists for each state, whether the port is started * (PxCMD.ST is set), whether a timer is running, what the PxIE mask is to be * set to, and what BDEV_OPEN calls on this port should return. @@ -67,16 +75,16 @@ * State Started Timer PxIE BDEV_OPEN * --------- --------- --------- --------- --------- * NO_PORT no no (none) ENXIO - * SPIN_UP no yes PRCE (wait) - * NO_DEV no no PRCE ENXIO - * WAIT_SIG yes yes PRCE (wait) - * WAIT_ID yes yes (all) (wait) + * SPIN_UP no yes PCE (wait) + * NO_DEV no no PCE ENXIO + * WAIT_DEV no yes PCE (wait) * BAD_DEV no no PRCE ENXIO - * GOOD_DEV yes per-command (all) OK + * WAIT_ID yes yes PRCE+ (wait) + * GOOD_DEV yes per-command PRCE+ OK * * In order to continue deferred BDEV_OPEN calls, the BUSY flag must be unset - * when changing from SPIN_UP to any state but WAIT_SIG, and when changing from - * WAIT_SIG to any state but WAIT_ID, and when changing from WAIT_ID to any + * when changing from SPIN_UP to any state but WAIT_DEV, and when changing from + * WAIT_DEV to any state but WAIT_ID, and when changing from WAIT_ID to any * other state. */ /* @@ -183,9 +191,9 @@ static int ahci_verbose; /* verbosity level (0..4) */ /* Timeout-related values. */ static clock_t ahci_spinup_timeout; -static clock_t ahci_sig_timeout; -static clock_t ahci_sig_delay; -static unsigned int ahci_sig_checks; +static clock_t ahci_device_timeout; +static clock_t ahci_device_delay; +static unsigned int ahci_device_checks; static clock_t ahci_command_timeout; static clock_t ahci_transfer_timeout; static clock_t ahci_flush_timeout; @@ -196,11 +204,11 @@ static struct { u32_t default_ms; /* default in milliseconds */ clock_t *ptr; /* clock ticks value pointer */ } ahci_timevar[] = { - { "ahci_init_timeout", SPINUP_TIMEOUT, &ahci_spinup_timeout }, - { "ahci_sig_timeout", SIG_TIMEOUT, &ahci_sig_timeout }, - { "ahci_cmd_timeout", COMMAND_TIMEOUT, &ahci_command_timeout }, - { "ahci_io_timeout", TRANSFER_TIMEOUT, &ahci_transfer_timeout }, - { "ahci_flush_timeout", FLUSH_TIMEOUT, &ahci_flush_timeout } + { "ahci_init_timeout", SPINUP_TIMEOUT, &ahci_spinup_timeout }, + { "ahci_device_timeout", DEVICE_TIMEOUT, &ahci_device_timeout }, + { "ahci_cmd_timeout", COMMAND_TIMEOUT, &ahci_command_timeout }, + { "ahci_io_timeout", TRANSFER_TIMEOUT, &ahci_transfer_timeout }, + { "ahci_flush_timeout", FLUSH_TIMEOUT, &ahci_flush_timeout } }; static int ahci_map[MAX_DRIVES]; /* device-to-port mapping */ @@ -1245,6 +1253,27 @@ static void port_start(struct port_state *ps) dprintf(V_INFO, ("%s: started\n", ahci_portname(ps))); } +/*===========================================================================* + * port_stop * + *===========================================================================*/ +static void port_stop(struct port_state *ps) +{ + /* Stop the given port, if not already stopped. + */ + u32_t cmd; + + cmd = port_read(ps, AHCI_PORT_CMD); + + if (cmd & (AHCI_PORT_CMD_CR | AHCI_PORT_CMD_ST)) { + port_write(ps, AHCI_PORT_CMD, cmd & ~AHCI_PORT_CMD_ST); + + SPIN_UNTIL(!(port_read(ps, AHCI_PORT_CMD) & AHCI_PORT_CMD_CR), + PORTREG_DELAY); + + dprintf(V_INFO, ("%s: stopped\n", ahci_portname(ps))); + } +} + /*===========================================================================* * port_restart * *===========================================================================*/ @@ -1252,21 +1281,12 @@ static void port_restart(struct port_state *ps) { /* Restart a port after a fatal error has occurred. */ - u32_t cmd; /* Fail all outstanding commands. */ port_fail_cmds(ps); /* Stop the port. */ - cmd = port_read(ps, AHCI_PORT_CMD); - port_write(ps, AHCI_PORT_CMD, cmd & ~AHCI_PORT_CMD_ST); - - SPIN_UNTIL(!(port_read(ps, AHCI_PORT_CMD) & AHCI_PORT_CMD_CR), - PORTREG_DELAY); - - /* Reset status registers. */ - port_write(ps, AHCI_PORT_SERR, ~0); - port_write(ps, AHCI_PORT_IS, ~0); + port_stop(ps); /* If the BSY and/or DRQ flags are set, reset the port. */ if (port_read(ps, AHCI_PORT_TFD) & @@ -1290,125 +1310,7 @@ static void port_restart(struct port_state *ps) } /* Start the port. */ - cmd = port_read(ps, AHCI_PORT_CMD); - port_write(ps, AHCI_PORT_CMD, cmd | AHCI_PORT_CMD_ST); - - dprintf(V_INFO, ("%s: restarted\n", ahci_portname(ps))); -} - -/*===========================================================================* - * port_stop * - *===========================================================================*/ -static void port_stop(struct port_state *ps) -{ - /* Stop the given port, if not already stopped. - */ - u32_t cmd; - - /* Disable interrupts. */ - port_write(ps, AHCI_PORT_IE, AHCI_PORT_IE_NONE); - - /* Stop the port. */ - cmd = port_read(ps, AHCI_PORT_CMD); - - if (cmd & (AHCI_PORT_CMD_CR | AHCI_PORT_CMD_ST)) { - cmd &= ~(AHCI_PORT_CMD_CR | AHCI_PORT_CMD_ST); - - port_write(ps, AHCI_PORT_CMD, cmd); - - SPIN_UNTIL(!(port_read(ps, AHCI_PORT_CMD) & AHCI_PORT_CMD_CR), - PORTREG_DELAY); - - dprintf(V_INFO, ("%s: stopped\n", ahci_portname(ps))); - } - - /* Reset status registers. */ - port_write(ps, AHCI_PORT_SERR, ~0); - port_write(ps, AHCI_PORT_IS, ~0); -} - -/*===========================================================================* - * port_sig_check * - *===========================================================================*/ -static void port_sig_check(struct port_state *ps) -{ - /* Check whether the device's signature has become available yet, and - * if so, start identifying the device. - */ - u32_t tfd, sig; - - tfd = port_read(ps, AHCI_PORT_TFD); - - /* Wait for the BSY flag to be (set and then) cleared first. Note that - * clearing it only happens when PxCMD.FRE is set, which is why we - * start the port before starting the signature wait cycle. - */ - if ((tfd & AHCI_PORT_TFD_STS_BSY) || tfd == AHCI_PORT_TFD_STS_INIT) { - /* Try for a while before giving up. It may take seconds. */ - if (ps->left > 0) { - ps->left--; - set_timer(&ps->cmd_info[0].timer, ahci_sig_delay, - port_timeout, BUILD_ARG(ps - port_state, 0)); - return; - } - - /* If no device is actually attached, disable the port. This - * value is also the initial value of the register, before the - * BSY flag gets set, so only check this condition on timeout. - */ - if (tfd == AHCI_PORT_TFD_STS_INIT) { - dprintf(V_DEV, ("%s: no device at this port\n", - ahci_portname(ps))); - - port_stop(ps); - - ps->state = STATE_BAD_DEV; - ps->flags &= ~FLAG_BUSY; - - return; - } - - port_restart(ps); - - dprintf(V_ERR, ("%s: timeout waiting for signature\n", - ahci_portname(ps))); - } - - /* Check the port's signature. We only support the normal ATA and ATAPI - * signatures. We ignore devices reporting anything else. - */ - sig = port_read(ps, AHCI_PORT_SIG); - - if (sig != ATA_SIG_ATA && sig != ATA_SIG_ATAPI) { - dprintf(V_ERR, ("%s: unsupported signature (%08x)\n", - ahci_portname(ps), sig)); - - port_stop(ps); - - ps->state = STATE_BAD_DEV; - ps->flags &= ~FLAG_BUSY; - - return; - } - - /* Clear all state flags except the busy flag, which may be relevant if - * a BDEV_OPEN call is waiting for the device to become ready; the - * barrier flag, which prevents access to the device until it is - * completely closed and (re)opened; and, the thread suspension flag. - */ - ps->flags &= (FLAG_BUSY | FLAG_BARRIER | FLAG_SUSPENDED); - - if (sig == ATA_SIG_ATAPI) - ps->flags |= FLAG_ATAPI; - - /* Attempt to identify the device. Do this using continuation, because - * we may already be called from port_wait() here, and could end up - * confusing the timer expiration procedure. - */ - ps->state = STATE_WAIT_ID; - port_write(ps, AHCI_PORT_IE, AHCI_PORT_IE_MASK); - - (void) gen_identify(ps, FALSE /*blocking*/); + port_start(ps); } /*===========================================================================* @@ -1444,8 +1346,8 @@ static void port_id_check(struct port_state *ps, int success) u16_t *buf; assert(ps->state == STATE_WAIT_ID); - assert(!(ps->flags & FLAG_BUSY)); /* unset by callers */ + ps->flags &= ~FLAG_BUSY; cancel_timer(&ps->cmd_info[0].timer); if (!success) @@ -1509,21 +1411,67 @@ static void port_connect(struct port_state *ps) /* A device has been found to be attached to this port. Start the port, * and do timed polling for its signature to become available. */ + u32_t status, sig; dprintf(V_INFO, ("%s: device connected\n", ahci_portname(ps))); - if (ps->state == STATE_SPIN_UP) - cancel_timer(&ps->cmd_info[0].timer); - port_start(ps); - ps->state = STATE_WAIT_SIG; - ps->left = ahci_sig_checks; + /* The next check covers a purely hypothetical race condition, where + * the device would disappear right before we try to start it. This is + * possible because we have to clear PxSERR, and with that, the DIAG.N + * bit. Double-check the port status, and if it is not as we expect, + * infer a disconnection. + */ + status = port_read(ps, AHCI_PORT_SSTS) & AHCI_PORT_SSTS_DET_MASK; + + if (status != AHCI_PORT_SSTS_DET_PHY) { + dprintf(V_ERR, ("%s: device vanished!\n", ahci_portname(ps))); + + port_stop(ps); + + ps->state = STATE_NO_DEV; + ps->flags &= ~FLAG_BUSY; + + return; + } + + /* Check the port's signature. We only support the normal ATA and ATAPI + * signatures. We ignore devices reporting anything else. + */ + sig = port_read(ps, AHCI_PORT_SIG); + + if (sig != ATA_SIG_ATA && sig != ATA_SIG_ATAPI) { + dprintf(V_ERR, ("%s: unsupported signature (%08x)\n", + ahci_portname(ps), sig)); + + port_stop(ps); + + ps->state = STATE_BAD_DEV; + port_write(ps, AHCI_PORT_IE, AHCI_PORT_IE_PRCE); + ps->flags &= ~FLAG_BUSY; + + return; + } + + /* Clear all state flags except the busy flag, which may be relevant if + * a BDEV_OPEN call is waiting for the device to become ready; the + * barrier flag, which prevents access to the device until it is + * completely closed and (re)opened; and, the thread suspension flag. + */ + ps->flags &= (FLAG_BUSY | FLAG_BARRIER | FLAG_SUSPENDED); + + if (sig == ATA_SIG_ATAPI) + ps->flags |= FLAG_ATAPI; - port_write(ps, AHCI_PORT_IE, AHCI_PORT_IE_PRCE); + /* Attempt to identify the device. Do this using continuation, because + * we may already be called from port_wait() here, and could end up + * confusing the timer expiration procedure. + */ + ps->state = STATE_WAIT_ID; + port_write(ps, AHCI_PORT_IE, AHCI_PORT_IE_MASK); - /* Do the first check immediately; who knows, we may get lucky. */ - port_sig_check(ps); + (void) gen_identify(ps, FALSE /*blocking*/); } /*===========================================================================* @@ -1531,16 +1479,13 @@ static void port_connect(struct port_state *ps) *===========================================================================*/ static void port_disconnect(struct port_state *ps) { - /* The device has detached from this port. Stop the port if necessary. + /* The device has detached from this port. It has already been stopped. */ dprintf(V_INFO, ("%s: device disconnected\n", ahci_portname(ps))); - if (ps->state != STATE_BAD_DEV) - port_stop(ps); - ps->state = STATE_NO_DEV; - port_write(ps, AHCI_PORT_IE, AHCI_PORT_IE_PRCE); + port_write(ps, AHCI_PORT_IE, AHCI_PORT_IE_PCE); ps->flags &= ~FLAG_BUSY; /* Fail any ongoing request. The caller may already have done this. */ @@ -1556,6 +1501,66 @@ static void port_disconnect(struct port_state *ps) blockdriver_mt_set_workers(ps->device, 1); } +/*===========================================================================* + * port_dev_check * + *===========================================================================*/ +static void port_dev_check(struct port_state *ps) +{ + /* Perform device detection by means of polling. + */ + u32_t status, tfd; + + assert(ps->state == STATE_WAIT_DEV); + + status = port_read(ps, AHCI_PORT_SSTS) & AHCI_PORT_SSTS_DET_MASK; + + dprintf(V_DEV, ("%s: polled status %u\n", ahci_portname(ps), status)); + + switch (status) { + case AHCI_PORT_SSTS_DET_PHY: + tfd = port_read(ps, AHCI_PORT_TFD); + + /* If a Phy connection has been established, and the BSY and + * DRQ flags are cleared, the device is ready. + */ + if (!(tfd & (AHCI_PORT_TFD_STS_BSY | AHCI_PORT_TFD_STS_DRQ))) { + port_connect(ps); + + return; + } + + /* fall-through */ + case AHCI_PORT_SSTS_DET_DET: + /* A device has been detected, but it is not ready yet. Try for + * a while before giving up. This may take seconds. + */ + if (ps->left > 0) { + ps->left--; + set_timer(&ps->cmd_info[0].timer, ahci_device_delay, + port_timeout, BUILD_ARG(ps - port_state, 0)); + return; + } + } + + dprintf(V_INFO, ("%s: device not ready\n", ahci_portname(ps))); + + /* We get here on timeout, and if the HBA reports that there is no + * device present at all. In all cases, we change to another state. + */ + if (status == AHCI_PORT_SSTS_DET_PHY) { + /* A device is present and initialized, but not ready. */ + ps->state = STATE_BAD_DEV; + port_write(ps, AHCI_PORT_IE, AHCI_PORT_IE_PRCE); + } else { + /* A device may or may not be present, but it does not appear + * to be ready in any case. Ignore it until the next device + * initialization event. + */ + ps->state = STATE_NO_DEV; + ps->flags &= ~FLAG_BUSY; + } +} + /*===========================================================================* * port_intr * *===========================================================================*/ @@ -1564,7 +1569,6 @@ static void port_intr(struct port_state *ps) /* Process an interrupt on this port. */ u32_t smask, emask; - int connected; if (ps->state == STATE_NO_PORT) { dprintf(V_ERR, ("%s: interrupt for invalid port!\n", @@ -1584,26 +1588,67 @@ static void port_intr(struct port_state *ps) /* Check if any commands have completed. */ port_check_cmds(ps); - if (emask & AHCI_PORT_IS_PRCS) { + if (emask & AHCI_PORT_IS_PCS) { + /* Clear the X diagnostics bit to clear this interrupt. */ + port_write(ps, AHCI_PORT_SERR, AHCI_PORT_SERR_DIAG_X); + + dprintf(V_DEV, ("%s: device attached\n", ahci_portname(ps))); + + switch (ps->state) { + case STATE_SPIN_UP: + case STATE_NO_DEV: + /* Reportedly, a device has shown up. Start polling its + * status until it has become ready. + */ + + if (ps->state == STATE_SPIN_UP) + cancel_timer(&ps->cmd_info[0].timer); + + ps->state = STATE_WAIT_DEV; + ps->left = ahci_device_checks; + + port_dev_check(ps); + + break; + + case STATE_WAIT_DEV: + /* Nothing else to do. */ + break; + + default: + /* Impossible. */ + assert(0); + } + } else if (emask & AHCI_PORT_IS_PRCS) { /* Clear the N diagnostics bit to clear this interrupt. */ port_write(ps, AHCI_PORT_SERR, AHCI_PORT_SERR_DIAG_N); - connected = (port_read(ps, AHCI_PORT_SSTS) & - AHCI_PORT_SSTS_DET_MASK) == AHCI_PORT_SSTS_DET_PHY; + dprintf(V_DEV, ("%s: device detached\n", ahci_portname(ps))); switch (ps->state) { - case STATE_BAD_DEV: - case STATE_GOOD_DEV: - case STATE_WAIT_SIG: case STATE_WAIT_ID: - port_disconnect(ps); + case STATE_GOOD_DEV: + /* The device is no longer ready. Stop the port, cancel + * ongoing requests, and disconnect the device. + */ + port_stop(ps); /* fall-through */ - default: - if (!connected) - break; + case STATE_BAD_DEV: + port_disconnect(ps); - port_connect(ps); + /* The device has become unusable to us at this point. + * Reset the port to make sure that once the device (or + * another device) becomes usable again, we will get a + * PCS interrupt as well. + */ + port_hardreset(ps); + + break; + + default: + /* Impossible. */ + assert(0); } } else if (smask & AHCI_PORT_IS_MASK) { /* We assume that any other interrupt indicates command @@ -1617,7 +1662,6 @@ static void port_intr(struct port_state *ps) /* If we were waiting for ID verification, check now. */ if (ps->state == STATE_WAIT_ID) { - ps->flags &= ~FLAG_BUSY; port_id_check(ps, !(port_read(ps, AHCI_PORT_TFD) & (AHCI_PORT_TFD_STS_ERR | AHCI_PORT_TFD_STS_DF))); @@ -1666,19 +1710,21 @@ static void port_timeout(struct timer *tp) * detection and only look for hot plug events from now on. */ if (ps->state == STATE_SPIN_UP) { - /* There is one exception: for braindead controllers that don't - * generate the right interrupts (cough, VirtualBox), we do an - * explicit check to see if a device is connected after all. - * Later hot-(un)plug events will not be detected in this case. + /* One exception: if the PCS interrupt bit is set here, then we + * are probably running on VirtualBox, which is currently not + * always raising interrupts when setting interrupt bits (!). */ - if ((port_read(ps, AHCI_PORT_SSTS) & - AHCI_PORT_SSTS_DET_MASK) == AHCI_PORT_SSTS_DET_PHY) { - dprintf(V_INFO, ("%s: no device connection event\n", + if (port_read(ps, AHCI_PORT_IS) & AHCI_PORT_IS_PCS) { + dprintf(V_INFO, ("%s: bad controller, no interrupt\n", ahci_portname(ps))); - port_connect(ps); - } - else { + ps->state = STATE_WAIT_DEV; + ps->left = ahci_device_checks; + + port_dev_check(ps); + + return; + } else { dprintf(V_INFO, ("%s: spin-up timeout\n", ahci_portname(ps))); @@ -1693,25 +1739,15 @@ static void port_timeout(struct timer *tp) return; } - /* If a device has been connected and we are waiting for its signature - * to become available, check now. + /* If we are waiting for a device to become connected and initialized, + * check now. */ - if (ps->state == STATE_WAIT_SIG) { - port_sig_check(ps); + if (ps->state == STATE_WAIT_DEV) { + port_dev_check(ps); return; } - /* The only case where the busy flag will be set after this is for a - * failed identify operation. During this operation, the port will be - * in the WAIT_ID state. In that case, we clear the BUSY flag, fail the - * command by setting its state, restart port and finish identify op. - */ - if (ps->flags & FLAG_BUSY) { - assert(ps->state == STATE_WAIT_ID); - ps->flags &= ~FLAG_BUSY; - } - dprintf(V_ERR, ("%s: timeout\n", ahci_portname(ps))); /* Restart the port, failing all current commands. */ @@ -1934,8 +1970,8 @@ static void port_init(struct port_state *ps) /* Allocate memory for the port. */ port_alloc(ps); - /* Just listen for device status change events for now. */ - port_write(ps, AHCI_PORT_IE, AHCI_PORT_IE_PRCE); + /* Just listen for device connection events for now. */ + port_write(ps, AHCI_PORT_IE, AHCI_PORT_IE_PCE); /* Enable device spin-up for HBAs that support staggered spin-up. * This is a no-op for HBAs that do not support it. @@ -2190,9 +2226,9 @@ static void ahci_get_params(void) *ahci_timevar[i].ptr = millis_to_hz(v); } - ahci_sig_delay = millis_to_hz(SIG_DELAY); - ahci_sig_checks = - (ahci_sig_timeout + ahci_sig_delay - 1) / ahci_sig_delay; + ahci_device_delay = millis_to_hz(DEVICE_DELAY); + ahci_device_checks = (ahci_device_timeout + ahci_device_delay - 1) / + ahci_device_delay; } /*===========================================================================* diff --git a/drivers/ahci/ahci.h b/drivers/ahci/ahci.h index 3a58e423b..b1ccd664d 100644 --- a/drivers/ahci/ahci.h +++ b/drivers/ahci/ahci.h @@ -8,7 +8,7 @@ /* Time values that can be set with options. */ #define SPINUP_TIMEOUT 5000 /* initial spin-up time (ms) */ -#define SIG_TIMEOUT 15000 /* time to wait for signature (ms) */ +#define DEVICE_TIMEOUT 30000 /* time to wait for device (ms) */ #define COMMAND_TIMEOUT 10000 /* time to wait for non-I/O cmd (ms) */ #define TRANSFER_TIMEOUT 30000 /* time to wait for I/O cmd (ms) */ #define FLUSH_TIMEOUT 60000 /* time to wait for flush cmd (ms) */ @@ -19,7 +19,7 @@ #define PORTREG_DELAY 500 /* maximum port register update (ms) */ /* Other hardcoded time values. */ -#define SIG_DELAY 250 /* time between signature checks (ms) */ +#define DEVICE_DELAY 100 /* time between device checks (ms) */ /* Generic FIS layout. */ #define ATA_FIS_TYPE 0 /* FIS Type */ @@ -174,15 +174,15 @@ #define AHCI_PORT_IS_IFS (1L << 27) /* Interface Fatal */ #define AHCI_PORT_IS_PRCS (1L << 22) /* PhyRdy Change */ #define AHCI_PORT_IS_PCS (1L << 6) /* Port Conn Change */ -#define AHCI_PORT_IS_SDBS (1L << 3) /* Set Device Bits FIS */ +#define AHCI_PORT_IS_SDBS (1L << 3) /* Set Dev Bits FIS */ #define AHCI_PORT_IS_PSS (1L << 1) /* PIO Setup FIS */ #define AHCI_PORT_IS_DHRS (1L << 0) /* D2H Register FIS */ #define AHCI_PORT_IS_RESTART \ (AHCI_PORT_IS_TFES | AHCI_PORT_IS_HBFS | AHCI_PORT_IS_HBDS | \ AHCI_PORT_IS_IFS) #define AHCI_PORT_IS_MASK \ - (AHCI_PORT_IS_RESTART | AHCI_PORT_IS_PRCS | AHCI_PORT_IS_PCS | \ - AHCI_PORT_IS_DHRS | AHCI_PORT_IS_PSS | AHCI_PORT_IS_SDBS) + (AHCI_PORT_IS_RESTART | AHCI_PORT_IS_PRCS | AHCI_PORT_IS_DHRS | \ + AHCI_PORT_IS_PSS | AHCI_PORT_IS_SDBS) #define AHCI_PORT_IE 5 /* Interrupt Enable */ #define AHCI_PORT_IE_MASK AHCI_PORT_IS_MASK #define AHCI_PORT_IE_PRCE AHCI_PORT_IS_PRCS @@ -205,11 +205,13 @@ #define ATA_SIG_ATAPI 0xEB140101L /* ATAPI interface */ #define AHCI_PORT_SSTS 10 /* Serial ATA Status */ #define AHCI_PORT_SSTS_DET_MASK 0x00000007L /* Detection Mask */ +#define AHCI_PORT_SSTS_DET_DET 0x00000001L /* Device Detected */ #define AHCI_PORT_SSTS_DET_PHY 0x00000003L /* PHY Comm Establ */ #define AHCI_PORT_SCTL 11 /* Serial ATA Control */ #define AHCI_PORT_SCTL_DET_INIT 0x00000001L /* Perform Init Seq */ #define AHCI_PORT_SCTL_DET_NONE 0x00000000L /* No Action Req'd */ #define AHCI_PORT_SERR 12 /* Serial ATA Error */ +#define AHCI_PORT_SERR_DIAG_X (1L << 26) /* Exchanged */ #define AHCI_PORT_SERR_DIAG_N (1L << 16) /* PhyRdy Change */ #define AHCI_PORT_SACT 13 /* Serial ATA Active */ #define AHCI_PORT_CI 14 /* Command Issue */ @@ -269,7 +271,7 @@ enum { STATE_NO_PORT, /* this port is not present */ STATE_SPIN_UP, /* waiting for device or timeout after reset */ STATE_NO_DEV, /* no device has been detected on this port */ - STATE_WAIT_SIG, /* waiting for device signature to appear */ + STATE_WAIT_DEV, /* waiting for functioning device to appear */ STATE_WAIT_ID, /* waiting for device identification */ STATE_BAD_DEV, /* an unusable device has been detected */ STATE_GOOD_DEV /* a usable device has been detected */