]> Zhao Yanbai Git Server - minix.git/commitdiff
AHCI driver: miscellaneous changes
authorDavid van Moolenbroek <david@minix3.org>
Thu, 12 Aug 2010 14:08:23 +0000 (14:08 +0000)
committerDavid van Moolenbroek <david@minix3.org>
Thu, 12 Aug 2010 14:08:23 +0000 (14:08 +0000)
- 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

drivers/ahci/ahci.c
drivers/ahci/ahci.h

index 9aa626d01e2d9950a1eecfe26715de3226e115b0..605b7a3c3570853a7a085a5dc652ba0ec5fc0331 100644 (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);
index 5c8f2e766f39b9e63f4b0c2832eeab0c23b09ab6..ca4692d1d8092c43e3cc611e418b7f21942dc5d6 100644 (file)
 #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 */
 #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 */
 #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 */
 #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.
  */