From: David van Moolenbroek Date: Thu, 12 Aug 2010 14:08:23 +0000 (+0000) Subject: AHCI driver: miscellaneous changes X-Git-Tag: v3.1.8~77 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/zlib_tech.html?a=commitdiff_plain;h=5998a4b2af122fd2c9589f1f7519acac763b4c2a;p=minix.git 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 --- diff --git a/drivers/ahci/ahci.c b/drivers/ahci/ahci.c index 9aa626d01..605b7a3c3 100644 --- a/drivers/ahci/ahci.c +++ b/drivers/ahci/ahci.c @@ -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) ¤t_port->open_count, sizeof(current_port->open_count), D); diff --git a/drivers/ahci/ahci.h b/drivers/ahci/ahci.h index 5c8f2e766..ca4692d1d 100644 --- a/drivers/ahci/ahci.h +++ b/drivers/ahci/ahci.h @@ -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. */