e1d867b686
This patch adds support for executing multiple concurrent requests on different devices on the same AHCI controller. The libdriver library has been extended to include a generic multithreading interface, and the AHCI driver has been extended to make use of this interface. The original version of this code has been written by Arne Welzel.
288 lines
13 KiB
C
288 lines
13 KiB
C
#ifndef _AHCI_H
|
|
#define _AHCI_H
|
|
|
|
#include <minix/drivers.h>
|
|
|
|
#define NR_PORTS 32 /* maximum number of ports */
|
|
#define NR_CMDS 1 /* maximum number of queued commands */
|
|
|
|
/* Time values that can be set with options. */
|
|
#define SPINUP_TIMEOUT 5000 /* initial spin-up time (ms) */
|
|
#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 30000 /* time to wait for I/O cmd (ms) */
|
|
#define FLUSH_TIMEOUT 60000 /* time to wait for flush 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) */
|
|
|
|
/* Generic FIS layout. */
|
|
#define ATA_FIS_TYPE 0 /* FIS Type */
|
|
#define ATA_FIS_TYPE_H2D 0x27 /* Register - Host to Device */
|
|
|
|
/* Register - Host to Device FIS layout. */
|
|
#define ATA_H2D_SIZE 20 /* byte size of H2D FIS */
|
|
#define ATA_H2D_FLAGS 1 /* C and PM Port */
|
|
#define ATA_H2D_FLAGS_C 0x80 /* update command register */
|
|
#define ATA_H2D_CMD 2 /* Command */
|
|
#define ATA_CMD_READ_DMA_EXT 0x25 /* READ DMA EXT */
|
|
#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_FLUSH_CACHE 0xE7 /* FLUSH CACHE */
|
|
#define ATA_CMD_IDENTIFY 0xEC /* IDENTIFY DEVICE */
|
|
#define ATA_CMD_SET_FEATURES 0xEF /* SET FEATURES */
|
|
#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_H2D_LBA_LOW 4 /* LBA Low */
|
|
#define ATA_H2D_LBA_MID 5 /* LBA Mid */
|
|
#define ATA_H2D_LBA_HIGH 6 /* LBA High */
|
|
#define ATA_H2D_DEV 7 /* Device */
|
|
#define ATA_DEV_LBA 0x40 /* use LBA addressing */
|
|
#define ATA_H2D_LBA_LOW_EXP 8 /* LBA Low (exp) */
|
|
#define ATA_H2D_LBA_MID_EXP 9 /* LBA Mid (exp) */
|
|
#define ATA_H2D_LBA_HIGH_EXP 10 /* LBA High (exp) */
|
|
#define ATA_H2D_FEAT_EXP 11 /* Features (exp) */
|
|
#define ATA_H2D_SEC 12 /* Sector Count */
|
|
#define ATA_H2D_SEC_EXP 13 /* Sector Count (exp) */
|
|
#define ATA_H2D_CTL 15 /* Control */
|
|
|
|
/* ATA constants. */
|
|
#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 ATA_ID_GCAP_ATA_MASK 0x8000 /* ATA device mask */
|
|
#define ATA_ID_GCAP_ATA 0x0000 /* ATA device */
|
|
#define ATA_ID_GCAP_TYPE_MASK 0x1F00 /* ATAPI device type */
|
|
#define ATA_ID_GCAP_TYPE_SHIFT 8 /* (one of ATAPI_TYPE_*) */
|
|
#define ATA_ID_GCAP_REMOVABLE 0x0080 /* Removable media device */
|
|
#define ATA_ID_GCAP_INCOMPLETE 0x0004 /* Incomplete response */
|
|
#define ATA_ID_CAP 49 /* Capabilities */
|
|
#define ATA_ID_CAP_DMA 0x0100 /* DMA supported (no DMADIR) */
|
|
#define ATA_ID_CAP_LBA 0x0200 /* LBA supported */
|
|
#define ATA_ID_DMADIR 62 /* DMADIR */
|
|
#define ATA_ID_DMADIR_DMADIR 0x8000 /* DMADIR required */
|
|
#define ATA_ID_DMADIR_DMA 0x0400 /* DMA supported (DMADIR) */
|
|
#define ATA_ID_SUP0 82 /* Features supported (1/3) */
|
|
#define ATA_ID_SUP0_WCACHE 0x0020 /* Write cache supported */
|
|
#define ATA_ID_SUP1 83 /* Features supported (2/3) */
|
|
#define ATA_ID_SUP1_VALID_MASK 0xC000 /* Word validity mask */
|
|
#define ATA_ID_SUP1_VALID 0x4000 /* Word contents are valid */
|
|
#define ATA_ID_SUP1_FLUSH 0x1000 /* FLUSH CACHE supported */
|
|
#define ATA_ID_SUP1_LBA48 0x0400 /* 48-bit LBA supported */
|
|
#define ATA_ID_ENA0 85 /* Features enabled (1/3) */
|
|
#define ATA_ID_ENA0_WCACHE 0x0020 /* Write cache enabled */
|
|
#define ATA_ID_ENA2 87 /* Features enabled (3/3) */
|
|
#define ATA_ID_ENA2_VALID_MASK 0xC000 /* Word validity mask */
|
|
#define ATA_ID_ENA2_VALID 0x4000 /* Word contents are valid */
|
|
#define ATA_ID_LBA0 100 /* Max. LBA48 address (LSW) */
|
|
#define ATA_ID_LBA1 101 /* Max. LBA48 address */
|
|
#define ATA_ID_LBA2 102 /* Max. LBA48 address */
|
|
#define ATA_ID_LBA3 103 /* Max. LBA48 address (MSW) */
|
|
#define ATA_ID_PLSS 106 /* Phys./logical sector size */
|
|
#define ATA_ID_PLSS_VALID_MASK 0xC000 /* Word validity mask */
|
|
#define ATA_ID_PLSS_VALID 0x4000 /* Word contents are valid */
|
|
#define ATA_ID_PLSS_LLS 0x1000 /* Long logical sectors */
|
|
#define ATA_ID_LSS0 118 /* Logical sector size (LSW) */
|
|
#define ATA_ID_LSS1 119 /* Logical sector size (MSW) */
|
|
|
|
#define ATA_SF_EN_WCACHE 0x02 /* Enable write cache */
|
|
#define ATA_SF_DI_WCACHE 0x82 /* Disable write cache */
|
|
|
|
/* ATAPI constants. */
|
|
#define ATAPI_PACKET_SIZE 16 /* ATAPI packet size */
|
|
|
|
#define ATAPI_TYPE_CDROM 5 /* CD-ROM device */
|
|
|
|
#define ATAPI_CMD_TEST_UNIT 0x00 /* Test Unit Ready */
|
|
#define ATAPI_CMD_REQUEST_SENSE 0x03 /* Request Sense */
|
|
#define ATAPI_REQUEST_SENSE_LEN 18 /* result length */
|
|
#define ATAPI_SENSE_UNIT_ATT 6 /* Unit Attention */
|
|
#define ATAPI_CMD_START_STOP 0x1B /* Start/Stop Unit */
|
|
#define ATAPI_START_STOP_EJECT 0x02 /* eject the medium */
|
|
#define ATAPI_START_STOP_LOAD 0x03 /* load the medium */
|
|
#define ATAPI_CMD_READ_CAPACITY 0x25 /* Read Capacity */
|
|
#define ATAPI_READ_CAPACITY_LEN 8 /* result length */
|
|
#define ATAPI_CMD_READ 0xA8 /* Read (12) */
|
|
#define ATAPI_CMD_WRITE 0xAA /* Write (12) */
|
|
|
|
/* Command List constants. */
|
|
#define AHCI_CL_ENTRY_SIZE 32 /* Command List header size */
|
|
#define AHCI_CL_ENTRY_DWORDS (AHCI_CL_ENTRY_SIZE / sizeof(u32_t))
|
|
|
|
#define AHCI_CL_PRDTL_SHIFT 16 /* PRD Table Length */
|
|
#define AHCI_CL_PREFETCHABLE (1L << 7) /* Prefetchable */
|
|
#define AHCI_CL_WRITE (1L << 6) /* Write */
|
|
#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.
|
|
*/
|
|
typedef struct {
|
|
u8_t cf_cmd; /* Command */
|
|
u8_t cf_feat; /* Features */
|
|
u32_t cf_lba; /* LBA (24-bit) */
|
|
u8_t cf_dev; /* Device */
|
|
u32_t cf_lba_exp; /* LBA (exp) (24-bit) */
|
|
u8_t cf_feat_exp; /* Features (exp) */
|
|
u8_t cf_sec; /* Sector Count */
|
|
u8_t cf_sec_exp; /* Sector Count (exp) */
|
|
u8_t cf_ctl; /* Control */
|
|
} cmd_fis_t;
|
|
|
|
/* Physical Region Descriptor (PRD). For internal use only;
|
|
* the contents of this structure are later converted to an actual PRD.
|
|
*/
|
|
typedef struct {
|
|
phys_bytes prd_phys;
|
|
vir_bytes prd_size;
|
|
} prd_t;
|
|
|
|
/* These are from at_wini, as this driver is a drop-in replacement for at_wini.
|
|
* Practically speaking this is already the upper limit with 256 minor device
|
|
* numbers per driver, even though it means we can only ever expose 8 devices
|
|
* out of potentially 32.
|
|
*/
|
|
#define MAX_DRIVES 8
|
|
#define NR_MINORS (MAX_DRIVES * DEV_PER_DRIVE)
|
|
#define SUB_PER_DRIVE (NR_PARTITIONS * NR_PARTITIONS)
|
|
#define NR_SUBDEVS (MAX_DRIVES * SUB_PER_DRIVE)
|
|
|
|
/* Port states. */
|
|
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_ID, /* waiting for device identification */
|
|
STATE_BAD_DEV, /* an unusable device has been detected */
|
|
STATE_GOOD_DEV /* a usable device has been detected */
|
|
};
|
|
|
|
/* Port flags. */
|
|
#define FLAG_ATAPI 0x00000001 /* is this an ATAPI device? */
|
|
#define FLAG_HAS_MEDIUM 0x00000002 /* is a medium present? */
|
|
#define FLAG_USE_DMADIR 0x00000004 /* use ATAPI DMADIR flag? */
|
|
#define FLAG_READONLY 0x00000008 /* is the device read-only? */
|
|
#define FLAG_BUSY 0x00000010 /* is an operation ongoing? */
|
|
#define FLAG_FAILURE 0x00000020 /* did the operation fail? */
|
|
#define FLAG_BARRIER 0x00000040 /* no access until unset */
|
|
#define FLAG_HAS_WCACHE 0x00000080 /* is a write cache present? */
|
|
#define FLAG_HAS_FLUSH 0x00000100 /* is FLUSH CACHE supported? */
|
|
#define FLAG_SUSPENDED 0x00000200 /* is the thread suspended? */
|
|
|
|
/* Mapping between devices and ports. */
|
|
#define NO_PORT -1 /* this device maps to no port */
|
|
#define NO_DEVICE -1 /* this port maps to no device */
|
|
|
|
/* Output verbosity levels. */
|
|
enum {
|
|
V_NONE, /* no output at all; keep silent */
|
|
V_ERR, /* important error information only (the default) */
|
|
V_INFO, /* general information about the driver and devices */
|
|
V_DEV, /* device details, to help with detection problems */
|
|
V_REQ /* detailed information about requests */
|
|
};
|
|
|
|
#endif /* _AHCI_H */
|