AHCI driver: miscellaneous changes

- check the DF status flag after each command
- increase I/O timeout from 15 to 30 seconds
- share some code between ATA and ATAPI after all
- produce more accurate errors on DIOCEJECT
- rename AHCI_ID_SIZE to the more appropriate ATA_ID_SIZE
- rearrange ahci.h in a now more sensible way
This commit is contained in:
David van Moolenbroek 2010-08-12 14:08:23 +00:00
parent f8c56494c9
commit 5998a4b2af
2 changed files with 133 additions and 153 deletions

View file

@ -398,29 +398,6 @@ PRIVATE int atapi_check_medium(struct port_state *ps, int cmd)
return OK;
}
/*===========================================================================*
* atapi_identify *
*===========================================================================*/
PRIVATE void atapi_identify(struct port_state *ps)
{
/* Identify an ATAPI device.
*/
cmd_fis_t fis;
prd_t prd;
/* Set up a command, and a single PRD for the result. */
memset(&fis, 0, sizeof(fis));
fis.cf_cmd = ATA_CMD_IDENTIFY_PACKET;
prd.prd_phys = ps->tmp_phys;
prd.prd_size = AHCI_ID_SIZE;
/* Start the command, but do not wait for the result. */
port_set_cmd(ps, 0, &fis, NULL /*packet*/, &prd, 1, FALSE /*write*/);
port_issue(ps, 0, ahci_command_timeout);
}
/*===========================================================================*
* atapi_id_check *
*===========================================================================*/
@ -499,29 +476,6 @@ PRIVATE int atapi_transfer(struct port_state *ps, int cmd, u64_t start_lba,
return port_exec(ps, cmd, ahci_transfer_timeout);
}
/*===========================================================================*
* ata_identify *
*===========================================================================*/
PRIVATE void ata_identify(struct port_state *ps)
{
/* Identify an ATA device.
*/
cmd_fis_t fis;
prd_t prd;
/* Set up a command, and a single PRD for the result. */
memset(&fis, 0, sizeof(fis));
fis.cf_cmd = ATA_CMD_IDENTIFY;
prd.prd_phys = ps->tmp_phys;
prd.prd_size = AHCI_ID_SIZE;
/* Start the command, but do not wait for the result. */
port_set_cmd(ps, 0, &fis, NULL /*packet*/, &prd, 1, FALSE /*write*/);
port_issue(ps, 0, ahci_command_timeout);
}
/*===========================================================================*
* ata_id_check *
*===========================================================================*/
@ -609,6 +563,33 @@ PRIVATE int ata_transfer(struct port_state *ps, int cmd, u64_t start_lba,
return port_exec(ps, cmd, ahci_transfer_timeout);
}
/*===========================================================================*
* gen_identify *
*===========================================================================*/
PRIVATE void gen_identify(struct port_state *ps, int cmd)
{
/* Identify an ATA or ATAPI device.
*/
cmd_fis_t fis;
prd_t prd;
/* Set up a command, and a single PRD for the result. */
memset(&fis, 0, sizeof(fis));
if (ps->flags & FLAG_ATAPI)
fis.cf_cmd = ATA_CMD_IDENTIFY_PACKET;
else
fis.cf_cmd = ATA_CMD_IDENTIFY;
prd.prd_phys = ps->tmp_phys;
prd.prd_size = ATA_ID_SIZE;
/* Start the command, but do not wait for the result. */
port_set_cmd(ps, cmd, &fis, NULL /*packet*/, &prd, 1, FALSE /*write*/);
port_issue(ps, cmd, ahci_command_timeout);
}
/*===========================================================================*
* ct_set_fis *
*===========================================================================*/
@ -1140,10 +1121,7 @@ PRIVATE void port_sig_check(struct port_state *ps)
ps->state = STATE_WAIT_ID;
ps->reg[AHCI_PORT_IE] = AHCI_PORT_IE_MASK;
if (ps->flags & FLAG_ATAPI)
atapi_identify(ps);
else
ata_identify(ps);
gen_identify(ps, 0);
}
/*===========================================================================*
@ -1348,13 +1326,15 @@ PRIVATE void port_intr(struct port_state *ps)
}
else if ((ps->flags & FLAG_BUSY) && (smask & AHCI_PORT_IS_MASK) &&
(!(ps->reg[AHCI_PORT_TFD] & AHCI_PORT_TFD_STS_BSY) ||
(ps->reg[AHCI_PORT_TFD] & AHCI_PORT_TFD_STS_ERR))) {
(ps->reg[AHCI_PORT_TFD] & (AHCI_PORT_TFD_STS_ERR |
AHCI_PORT_TFD_STS_DF)))) {
assert(!(ps->flags & FLAG_FAILURE));
/* Command completed or failed. */
ps->flags &= ~FLAG_BUSY;
if (ps->reg[AHCI_PORT_TFD] & AHCI_PORT_TFD_STS_ERR)
if (ps->reg[AHCI_PORT_TFD] & (AHCI_PORT_TFD_STS_ERR |
AHCI_PORT_TFD_STS_DF))
ps->flags |= FLAG_FAILURE;
/* Some error cases require a port restart. */
@ -2293,21 +2273,20 @@ PRIVATE int ahci_other(struct driver *UNUSED(dp), message *m)
if (m->m_type != DEV_IOCTL_S)
return EINVAL;
if (ahci_prepare(m->DEVICE) == NULL)
return ENXIO;
switch (m->REQUEST) {
case DIOCEJECT:
if (ahci_prepare(m->DEVICE) == NULL)
return ENXIO;
if (current_port->state != STATE_GOOD_DEV)
return EIO;
if (current_port->state != STATE_GOOD_DEV ||
!(current_port->flags & FLAG_ATAPI))
if (!(current_port->flags & FLAG_ATAPI))
return EINVAL;
return atapi_load_eject(current_port, 0, FALSE /*load*/);
case DIOCOPENCT:
if (ahci_prepare(m->DEVICE) == NULL)
return ENXIO;
return sys_safecopyto(m->IO_ENDPT, (cp_grant_id_t) m->IO_GRANT,
0, (vir_bytes) &current_port->open_count,
sizeof(current_port->open_count), D);

View file

@ -11,105 +11,13 @@
#define SIG_TIMEOUT 250 /* time between signature checks (ms) */
#define NR_SIG_CHECKS 60 /* maximum number of times to check */
#define COMMAND_TIMEOUT 5000 /* time to wait for non-I/O cmd (ms) */
#define TRANSFER_TIMEOUT 15000 /* time to wait for I/O cmd (ms) */
#define TRANSFER_TIMEOUT 30000 /* time to wait for I/O cmd (ms) */
/* Time values that are defined by the standards. */
#define SPINUP_DELAY 1 /* time to assert spin-up flag (ms) */
#define RESET_DELAY 1000 /* maximum HBA reset time (ms) */
#define PORTREG_DELAY 500 /* maximum port register update (ms) */
/* Host Bus Adapter (HBA) constants. */
#define AHCI_HBA_CAP 0 /* Host Capabilities */
#define AHCI_HBA_CAP_SNCQ (1L << 30) /* Native Cmd Queuing */
#define AHCI_HBA_CAP_SCLO (1L << 24) /* Cmd List Override */
#define AHCI_HBA_CAP_NCS_SHIFT 8 /* Nr of Cmd Slots */
#define AHCI_HBA_CAP_NCS_MASK 0x1FL
#define AHCI_HBA_CAP_NP_SHIFT 0 /* Nr of Ports */
#define AHCI_HBA_CAP_NP_MASK 0x1FL
#define AHCI_HBA_GHC 1 /* Global Host Control */
#define AHCI_HBA_GHC_AE (1L << 31) /* AHCI Enable */
#define AHCI_HBA_GHC_IE (1L << 1) /* Interrupt Enable */
#define AHCI_HBA_GHC_HR (1L << 0) /* HBA Reset */
#define AHCI_HBA_IS 2 /* Interrupt Status */
#define AHCI_HBA_PI 3 /* Ports Implemented */
#define AHCI_HBA_VS 4 /* Version */
#define AHCI_HBA_CAP2 9 /* Host Capabilities Extended */
/* Port constants. */
#define AHCI_PORT_CLB 0 /* Command List Base */
#define AHCI_PORT_CLBU 1 /* Command List Base, Upper 32 bits */
#define AHCI_PORT_FB 2 /* FIS Base */
#define AHCI_PORT_FBU 3 /* FIS Base, Upper 32 bits */
#define AHCI_PORT_IS 4 /* Interrupt Status */
#define AHCI_PORT_IS_TFES (1L << 30) /* Task File Error */
#define AHCI_PORT_IS_HBFS (1L << 29) /* Host Bus Fatal */
#define AHCI_PORT_IS_HBDS (1L << 28) /* Host Bus Data */
#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_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)
#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
#define AHCI_PORT_IE_PCE AHCI_PORT_IS_PCS
#define AHCI_PORT_IE_NONE 0L
#define AHCI_PORT_CMD 6 /* Command and Status */
#define AHCI_PORT_CMD_CR (1L << 15) /* Cmd List Running */
#define AHCI_PORT_CMD_FR (1L << 14) /* FIS Recv Running */
#define AHCI_PORT_CMD_FRE (1L << 4) /* FIS Recv Enabled */
#define AHCI_PORT_CMD_SUD (1L << 1) /* Spin-Up Device */
#define AHCI_PORT_CMD_ST (1L << 0) /* Start */
#define AHCI_PORT_TFD 8 /* Task File Data */
#define AHCI_PORT_TFD_STS_BSY (1L << 7) /* Busy */
#define AHCI_PORT_TFD_STS_DRQ (1L << 3) /* Data Xfer Req'd */
#define AHCI_PORT_TFD_STS_ERR (1L << 0) /* Error */
#define AHCI_PORT_TFD_STS_INIT 0x7F /* Initial state */
#define AHCI_PORT_SIG 9 /* Signature */
#define ATA_SIG_ATA 0x00000101L /* ATA interface */
#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_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_N (1L << 16) /* PhyRdy Change */
#define AHCI_PORT_CI 14 /* Command Issue */
/* Number of Physical Region Descriptors (PRDs). Must be at least NR_IOREQS+2,
* and at most 1024. There is currently no reason to use more than the minimum.
*/
#define NR_PRDS (NR_IOREQS + 2)
/* Various size constants. */
#define AHCI_MEM_BASE_SIZE 0x100 /* memory-mapped base region size */
#define AHCI_MEM_PORT_SIZE 0x80 /* memory-mapped port region size */
#define AHCI_ID_SIZE (256 * sizeof(u16_t)) /* IDENTIFY result size */
#define AHCI_FIS_SIZE 256 /* size of FIS receive buffer */
#define AHCI_CL_SIZE 1024 /* size of command list buffer */
#define AHCI_TMP_SIZE AHCI_ID_SIZE /* size of temporary storage buffer */
#define AHCI_TMP_ALIGN 2 /* required alignment for temp buf */
#define AHCI_CT_SIZE (128 + NR_PRDS * sizeof(u32_t) * 4)
/* size of command table buffer */
#define AHCI_CT_ALIGN 128 /* required alignment for CT buffer */
#define MAX_PRD_BYTES (1L << 22) /* maximum number of bytes per PRD */
#define MAX_TRANSFER MAX_PRD_BYTES /* maximum size of a single transfer */
/* Command Table offsets. */
#define AHCI_CT_PACKET_OFF 0x40 /* CT offset to ATAPI packet */
#define AHCI_CT_PRDT_OFF 0x80 /* CT offset to PRD table */
/* Generic FIS layout. */
#define ATA_FIS_TYPE 0 /* FIS Type */
#define ATA_FIS_TYPE_H2D 0x27 /* Register - Host to Device */
@ -123,7 +31,7 @@
#define ATA_CMD_WRITE_DMA_EXT 0x35 /* WRITE DMA EXT */
#define ATA_CMD_PACKET 0xA0 /* PACKET */
#define ATA_CMD_IDENTIFY_PACKET 0xA1 /* IDENTIFY PACKET DEVICE */
#define ATA_CMD_IDENTIFY 0xEC /* IDENTIFY DEVICE */
#define ATA_CMD_IDENTIFY 0xEC /* IDENTIFY DEVICE */
#define ATA_H2D_FEAT 3 /* Features */
#define ATA_FEAT_PACKET_DMA 0x01 /* use DMA */
#define ATA_FEAT_PACKET_DMADIR 0x03 /* DMA is inbound */
@ -144,6 +52,8 @@
#define ATA_SECTOR_SIZE 512 /* default sector size */
#define ATA_MAX_SECTORS 0x10000 /* max sectors per transfer */
#define ATA_ID_SIZE (256 * sizeof(u16_t)) /* IDENTIFY result size */
#define ATA_ID_GCAP 0 /* General capabililties */
#define ATA_ID_GCAP_ATAPI_MASK 0xC000 /* ATAPI device mask */
#define ATA_ID_GCAP_ATAPI 0x8000 /* ATAPI device */
@ -201,6 +111,97 @@
#define AHCI_CL_ATAPI (1L << 5) /* ATAPI */
#define AHCI_CL_CFL_SHIFT 0 /* Command FIS Length */
/* Command Table offsets. */
#define AHCI_CT_PACKET_OFF 0x40 /* CT offset to ATAPI packet */
#define AHCI_CT_PRDT_OFF 0x80 /* CT offset to PRD table */
/* Host Bus Adapter (HBA) constants. */
#define AHCI_HBA_CAP 0 /* Host Capabilities */
#define AHCI_HBA_CAP_SNCQ (1L << 30) /* Native Cmd Queuing */
#define AHCI_HBA_CAP_SCLO (1L << 24) /* Cmd List Override */
#define AHCI_HBA_CAP_NCS_SHIFT 8 /* Nr of Cmd Slots */
#define AHCI_HBA_CAP_NCS_MASK 0x1FL
#define AHCI_HBA_CAP_NP_SHIFT 0 /* Nr of Ports */
#define AHCI_HBA_CAP_NP_MASK 0x1FL
#define AHCI_HBA_GHC 1 /* Global Host Control */
#define AHCI_HBA_GHC_AE (1L << 31) /* AHCI Enable */
#define AHCI_HBA_GHC_IE (1L << 1) /* Interrupt Enable */
#define AHCI_HBA_GHC_HR (1L << 0) /* HBA Reset */
#define AHCI_HBA_IS 2 /* Interrupt Status */
#define AHCI_HBA_PI 3 /* Ports Implemented */
#define AHCI_HBA_VS 4 /* Version */
#define AHCI_HBA_CAP2 9 /* Host Capabilities Extended */
/* Port constants. */
#define AHCI_PORT_CLB 0 /* Command List Base */
#define AHCI_PORT_CLBU 1 /* Command List Base, Upper 32 bits */
#define AHCI_PORT_FB 2 /* FIS Base */
#define AHCI_PORT_FBU 3 /* FIS Base, Upper 32 bits */
#define AHCI_PORT_IS 4 /* Interrupt Status */
#define AHCI_PORT_IS_TFES (1L << 30) /* Task File Error */
#define AHCI_PORT_IS_HBFS (1L << 29) /* Host Bus Fatal */
#define AHCI_PORT_IS_HBDS (1L << 28) /* Host Bus Data */
#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_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)
#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
#define AHCI_PORT_IE_PCE AHCI_PORT_IS_PCS
#define AHCI_PORT_IE_NONE 0L
#define AHCI_PORT_CMD 6 /* Command and Status */
#define AHCI_PORT_CMD_CR (1L << 15) /* Cmd List Running */
#define AHCI_PORT_CMD_FR (1L << 14) /* FIS Recv Running */
#define AHCI_PORT_CMD_FRE (1L << 4) /* FIS Recv Enabled */
#define AHCI_PORT_CMD_SUD (1L << 1) /* Spin-Up Device */
#define AHCI_PORT_CMD_ST (1L << 0) /* Start */
#define AHCI_PORT_TFD 8 /* Task File Data */
#define AHCI_PORT_TFD_STS_BSY (1L << 7) /* Busy */
#define AHCI_PORT_TFD_STS_DF (1L << 5) /* Device Fault */
#define AHCI_PORT_TFD_STS_DRQ (1L << 3) /* Data Xfer Req'd */
#define AHCI_PORT_TFD_STS_ERR (1L << 0) /* Error */
#define AHCI_PORT_TFD_STS_INIT 0x7F /* Initial state */
#define AHCI_PORT_SIG 9 /* Signature */
#define ATA_SIG_ATA 0x00000101L /* ATA interface */
#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_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_N (1L << 16) /* PhyRdy Change */
#define AHCI_PORT_CI 14 /* Command Issue */
/* Number of Physical Region Descriptors (PRDs). Must be at least NR_IOREQS+2,
* and at most 1024. There is currently no reason to use more than the minimum.
*/
#define NR_PRDS (NR_IOREQS + 2)
/* Various size constants. */
#define AHCI_MEM_BASE_SIZE 0x100 /* memory-mapped base region size */
#define AHCI_MEM_PORT_SIZE 0x80 /* memory-mapped port region size */
#define AHCI_FIS_SIZE 256 /* size of FIS receive buffer */
#define AHCI_CL_SIZE 1024 /* size of command list buffer */
#define AHCI_TMP_SIZE ATA_ID_SIZE /* size of temporary storage buffer */
#define AHCI_TMP_ALIGN 2 /* required alignment for temp buf */
#define AHCI_CT_SIZE (128 + NR_PRDS * sizeof(u32_t) * 4)
/* size of command table buffer */
#define AHCI_CT_ALIGN 128 /* required alignment for CT buffer */
#define MAX_PRD_BYTES (1L << 22) /* maximum number of bytes per PRD */
#define MAX_TRANSFER MAX_PRD_BYTES /* maximum size of a single transfer */
/* Command Frame Information Structure (FIS). For internal use only;
* the contents of this structure are later converted to an actual FIS.
*/