/** @file Header file for AHCI mode of ATA host controller. Copyright (c) 2010 - 2020, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #ifndef __ATA_HC_AHCI_MODE_H__ #define __ATA_HC_AHCI_MODE_H__ #define EFI_AHCI_BAR_INDEX 0x05 #define EFI_AHCI_CAPABILITY_OFFSET 0x0000 #define EFI_AHCI_CAP_SAM BIT18 #define EFI_AHCI_CAP_SSS BIT27 #define EFI_AHCI_CAP_S64A BIT31 #define EFI_AHCI_GHC_OFFSET 0x0004 #define EFI_AHCI_GHC_RESET BIT0 #define EFI_AHCI_GHC_IE BIT1 #define EFI_AHCI_GHC_ENABLE BIT31 #define EFI_AHCI_IS_OFFSET 0x0008 #define EFI_AHCI_PI_OFFSET 0x000C #define EFI_AHCI_MAX_PORTS 32 #define AHCI_CAPABILITY2_OFFSET 0x0024 #define AHCI_CAP2_SDS BIT3 #define AHCI_CAP2_SADM BIT4 typedef struct { UINT32 Lower32; UINT32 Upper32; } DATA_32; typedef union { DATA_32 Uint32; UINT64 Uint64; } DATA_64; // // Refer SATA1.0a spec section 5.2, the Phy detection time should be less than 10ms. // Add a bit of margin for robustness. // #define EFI_AHCI_BUS_PHY_DETECT_TIMEOUT 15 // // Refer SATA1.0a spec, the FIS enable time should be less than 500ms. // #define EFI_AHCI_PORT_CMD_FR_CLEAR_TIMEOUT EFI_TIMER_PERIOD_MILLISECONDS(500) // // Refer SATA1.0a spec, the bus reset time should be less than 1s. // #define EFI_AHCI_BUS_RESET_TIMEOUT EFI_TIMER_PERIOD_SECONDS(1) #define EFI_AHCI_ATAPI_DEVICE_SIG 0xEB140000 #define EFI_AHCI_ATA_DEVICE_SIG 0x00000000 #define EFI_AHCI_PORT_MULTIPLIER_SIG 0x96690000 #define EFI_AHCI_ATAPI_SIG_MASK 0xFFFF0000 // // Each PRDT entry can point to a memory block up to 4M byte // #define EFI_AHCI_MAX_DATA_PER_PRDT 0x400000 #define EFI_AHCI_FIS_REGISTER_H2D 0x27 // Register FIS - Host to Device #define EFI_AHCI_FIS_REGISTER_H2D_LENGTH 20 #define EFI_AHCI_FIS_REGISTER_D2H 0x34 // Register FIS - Device to Host #define EFI_AHCI_FIS_REGISTER_D2H_LENGTH 20 #define EFI_AHCI_FIS_DMA_ACTIVATE 0x39 // DMA Activate FIS - Device to Host #define EFI_AHCI_FIS_DMA_ACTIVATE_LENGTH 4 #define EFI_AHCI_FIS_DMA_SETUP 0x41 // DMA Setup FIS - Bi-directional #define EFI_AHCI_FIS_DMA_SETUP_LENGTH 28 #define EFI_AHCI_FIS_DATA 0x46 // Data FIS - Bi-directional #define EFI_AHCI_FIS_BIST 0x58 // BIST Activate FIS - Bi-directional #define EFI_AHCI_FIS_BIST_LENGTH 12 #define EFI_AHCI_FIS_PIO_SETUP 0x5F // PIO Setup FIS - Device to Host #define EFI_AHCI_FIS_PIO_SETUP_LENGTH 20 #define EFI_AHCI_FIS_SET_DEVICE 0xA1 // Set Device Bits FIS - Device to Host #define EFI_AHCI_FIS_SET_DEVICE_LENGTH 8 #define EFI_AHCI_D2H_FIS_OFFSET 0x40 #define EFI_AHCI_DMA_FIS_OFFSET 0x00 #define EFI_AHCI_PIO_FIS_OFFSET 0x20 #define EFI_AHCI_SDB_FIS_OFFSET 0x58 #define EFI_AHCI_FIS_TYPE_MASK 0xFF #define EFI_AHCI_U_FIS_OFFSET 0x60 // // Port register // #define EFI_AHCI_PORT_START 0x0100 #define EFI_AHCI_PORT_REG_WIDTH 0x0080 #define EFI_AHCI_PORT_CLB 0x0000 #define EFI_AHCI_PORT_CLBU 0x0004 #define EFI_AHCI_PORT_FB 0x0008 #define EFI_AHCI_PORT_FBU 0x000C #define EFI_AHCI_PORT_IS 0x0010 #define EFI_AHCI_PORT_IS_DHRS BIT0 #define EFI_AHCI_PORT_IS_PSS BIT1 #define EFI_AHCI_PORT_IS_DSS BIT2 #define EFI_AHCI_PORT_IS_SDBS BIT3 #define EFI_AHCI_PORT_IS_UFS BIT4 #define EFI_AHCI_PORT_IS_DPS BIT5 #define EFI_AHCI_PORT_IS_PCS BIT6 #define EFI_AHCI_PORT_IS_DIS BIT7 #define EFI_AHCI_PORT_IS_PRCS BIT22 #define EFI_AHCI_PORT_IS_IPMS BIT23 #define EFI_AHCI_PORT_IS_OFS BIT24 #define EFI_AHCI_PORT_IS_INFS BIT26 #define EFI_AHCI_PORT_IS_IFS BIT27 #define EFI_AHCI_PORT_IS_HBDS BIT28 #define EFI_AHCI_PORT_IS_HBFS BIT29 #define EFI_AHCI_PORT_IS_TFES BIT30 #define EFI_AHCI_PORT_IS_CPDS BIT31 #define EFI_AHCI_PORT_IS_CLEAR 0xFFFFFFFF #define EFI_AHCI_PORT_IS_FIS_CLEAR 0x0000000F #define EFI_AHCI_PORT_IS_ERROR_MASK (EFI_AHCI_PORT_IS_INFS | EFI_AHCI_PORT_IS_IFS | EFI_AHCI_PORT_IS_HBDS | EFI_AHCI_PORT_IS_HBFS | EFI_AHCI_PORT_IS_TFES) #define EFI_AHCI_PORT_IS_FATAL_ERROR_MASK (EFI_AHCI_PORT_IS_IFS | EFI_AHCI_PORT_IS_HBDS | EFI_AHCI_PORT_IS_HBFS | EFI_AHCI_PORT_IS_TFES) #define EFI_AHCI_PORT_IE 0x0014 #define EFI_AHCI_PORT_CMD 0x0018 #define EFI_AHCI_PORT_CMD_ST_MASK 0xFFFFFFFE #define EFI_AHCI_PORT_CMD_ST BIT0 #define EFI_AHCI_PORT_CMD_SUD BIT1 #define EFI_AHCI_PORT_CMD_POD BIT2 #define EFI_AHCI_PORT_CMD_CLO BIT3 #define EFI_AHCI_PORT_CMD_FRE BIT4 #define EFI_AHCI_PORT_CMD_CCS_MASK (BIT8 | BIT9 | BIT10 | BIT11 | BIT12) #define EFI_AHCI_PORT_CMD_CCS_SHIFT 8 #define EFI_AHCI_PORT_CMD_FR BIT14 #define EFI_AHCI_PORT_CMD_CR BIT15 #define EFI_AHCI_PORT_CMD_MASK ~(EFI_AHCI_PORT_CMD_ST | EFI_AHCI_PORT_CMD_FRE | EFI_AHCI_PORT_CMD_COL) #define EFI_AHCI_PORT_CMD_PMA BIT17 #define EFI_AHCI_PORT_CMD_HPCP BIT18 #define EFI_AHCI_PORT_CMD_MPSP BIT19 #define EFI_AHCI_PORT_CMD_CPD BIT20 #define EFI_AHCI_PORT_CMD_ESP BIT21 #define EFI_AHCI_PORT_CMD_ATAPI BIT24 #define EFI_AHCI_PORT_CMD_DLAE BIT25 #define EFI_AHCI_PORT_CMD_ALPE BIT26 #define EFI_AHCI_PORT_CMD_ASP BIT27 #define EFI_AHCI_PORT_CMD_ICC_MASK (BIT28 | BIT29 | BIT30 | BIT31) #define EFI_AHCI_PORT_CMD_ACTIVE (1 << 28 ) #define EFI_AHCI_PORT_TFD 0x0020 #define EFI_AHCI_PORT_TFD_MASK (BIT7 | BIT3 | BIT0) #define EFI_AHCI_PORT_TFD_BSY BIT7 #define EFI_AHCI_PORT_TFD_DRQ BIT3 #define EFI_AHCI_PORT_TFD_ERR BIT0 #define EFI_AHCI_PORT_TFD_ERR_MASK 0x00FF00 // ERROR field is specified by ATA/ATAPI Command Set specification #define EFI_AHCI_PORT_TFD_ERR_INT_CRC BIT15 #define EFI_AHCI_PORT_SIG 0x0024 #define EFI_AHCI_PORT_SSTS 0x0028 #define EFI_AHCI_PORT_SSTS_DET_MASK 0x000F #define EFI_AHCI_PORT_SSTS_DET 0x0001 #define EFI_AHCI_PORT_SSTS_DET_PCE 0x0003 #define EFI_AHCI_PORT_SSTS_SPD_MASK 0x00F0 #define EFI_AHCI_PORT_SCTL 0x002C #define EFI_AHCI_PORT_SCTL_DET_MASK 0x000F #define EFI_AHCI_PORT_SCTL_MASK (~EFI_AHCI_PORT_SCTL_DET_MASK) #define EFI_AHCI_PORT_SCTL_DET_INIT 0x0001 #define EFI_AHCI_PORT_SCTL_DET_PHYCOMM 0x0003 #define EFI_AHCI_PORT_SCTL_SPD_MASK 0x00F0 #define EFI_AHCI_PORT_SCTL_IPM_MASK 0x0F00 #define EFI_AHCI_PORT_SCTL_IPM_INIT 0x0300 #define EFI_AHCI_PORT_SCTL_IPM_PSD 0x0100 #define EFI_AHCI_PORT_SCTL_IPM_SSD 0x0200 #define EFI_AHCI_PORT_SERR 0x0030 #define EFI_AHCI_PORT_SERR_RDIE BIT0 #define EFI_AHCI_PORT_SERR_RCE BIT1 #define EFI_AHCI_PORT_SERR_TDIE BIT8 #define EFI_AHCI_PORT_SERR_PCDIE BIT9 #define EFI_AHCI_PORT_SERR_PE BIT10 #define EFI_AHCI_PORT_SERR_IE BIT11 #define EFI_AHCI_PORT_SERR_PRC BIT16 #define EFI_AHCI_PORT_SERR_PIE BIT17 #define EFI_AHCI_PORT_SERR_CW BIT18 #define EFI_AHCI_PORT_SERR_BDE BIT19 #define EFI_AHCI_PORT_SERR_DE BIT20 #define EFI_AHCI_PORT_SERR_CRCE BIT21 #define EFI_AHCI_PORT_SERR_HE BIT22 #define EFI_AHCI_PORT_SERR_LSE BIT23 #define EFI_AHCI_PORT_SERR_TSTE BIT24 #define EFI_AHCI_PORT_SERR_UFT BIT25 #define EFI_AHCI_PORT_SERR_EX BIT26 #define EFI_AHCI_PORT_ERR_CLEAR 0xFFFFFFFF #define EFI_AHCI_PORT_SACT 0x0034 #define EFI_AHCI_PORT_CI 0x0038 #define EFI_AHCI_PORT_SNTF 0x003C #define AHCI_PORT_DEVSLP 0x0044 #define AHCI_PORT_DEVSLP_ADSE BIT0 #define AHCI_PORT_DEVSLP_DSP BIT1 #define AHCI_PORT_DEVSLP_DETO_MASK 0x000003FC #define AHCI_PORT_DEVSLP_MDAT_MASK 0x00007C00 #define AHCI_PORT_DEVSLP_DITO_MASK 0x01FF8000 #define AHCI_PORT_DEVSLP_DM_MASK 0x1E000000 #define AHCI_COMMAND_RETRIES (PcdGet32 (PcdAhciCommandRetryCount)) #pragma pack(1) // // Command List structure includes total 32 entries. // The entry data structure is listed at the following. // typedef struct { UINT32 AhciCmdCfl : 5; // Command FIS Length UINT32 AhciCmdA : 1; // ATAPI UINT32 AhciCmdW : 1; // Write UINT32 AhciCmdP : 1; // Prefetchable UINT32 AhciCmdR : 1; // Reset UINT32 AhciCmdB : 1; // BIST UINT32 AhciCmdC : 1; // Clear Busy upon R_OK UINT32 AhciCmdRsvd : 1; UINT32 AhciCmdPmp : 4; // Port Multiplier Port UINT32 AhciCmdPrdtl : 16; // Physical Region Descriptor Table Length UINT32 AhciCmdPrdbc; // Physical Region Descriptor Byte Count UINT32 AhciCmdCtba; // Command Table Descriptor Base Address UINT32 AhciCmdCtbau; // Command Table Descriptor Base Address Upper 32-BITs UINT32 AhciCmdRsvd1[4]; } EFI_AHCI_COMMAND_LIST; // // This is a software constructed FIS. // For data transfer operations, this is the H2D Register FIS format as // specified in the Serial ATA Revision 2.6 specification. // typedef struct { UINT8 AhciCFisType; UINT8 AhciCFisPmNum : 4; UINT8 AhciCFisRsvd : 1; UINT8 AhciCFisRsvd1 : 1; UINT8 AhciCFisRsvd2 : 1; UINT8 AhciCFisCmdInd : 1; UINT8 AhciCFisCmd; UINT8 AhciCFisFeature; UINT8 AhciCFisSecNum; UINT8 AhciCFisClyLow; UINT8 AhciCFisClyHigh; UINT8 AhciCFisDevHead; UINT8 AhciCFisSecNumExp; UINT8 AhciCFisClyLowExp; UINT8 AhciCFisClyHighExp; UINT8 AhciCFisFeatureExp; UINT8 AhciCFisSecCount; UINT8 AhciCFisSecCountExp; UINT8 AhciCFisRsvd3; UINT8 AhciCFisControl; UINT8 AhciCFisRsvd4[4]; UINT8 AhciCFisRsvd5[44]; } EFI_AHCI_COMMAND_FIS; typedef enum { SataFisD2H = 0, SataFisPioSetup, SataFisDmaSetup } SATA_FIS_TYPE; // // ACMD: ATAPI command (12 or 16 bytes) // typedef struct { UINT8 AtapiCmd[0x10]; } EFI_AHCI_ATAPI_COMMAND; // // Physical Region Descriptor Table includes up to 65535 entries // The entry data structure is listed at the following. // the actual entry number comes from the PRDTL field in the command // list entry for this command slot. // typedef struct { UINT32 AhciPrdtDba; // Data Base Address UINT32 AhciPrdtDbau; // Data Base Address Upper 32-BITs UINT32 AhciPrdtRsvd; UINT32 AhciPrdtDbc : 22; // Data Byte Count UINT32 AhciPrdtRsvd1 : 9; UINT32 AhciPrdtIoc : 1; // Interrupt on Completion } EFI_AHCI_COMMAND_PRDT; // // Command table data structure which is pointed to by the entry in the command list // typedef struct { EFI_AHCI_COMMAND_FIS CommandFis; // A software constructed FIS. EFI_AHCI_ATAPI_COMMAND AtapiCmd; // 12 or 16 bytes ATAPI cmd. UINT8 Reserved[0x30]; EFI_AHCI_COMMAND_PRDT PrdtTable[65535]; // The scatter/gather list for data transfer } EFI_AHCI_COMMAND_TABLE; // // Received FIS structure // typedef struct { UINT8 AhciDmaSetupFis[0x1C]; // Dma Setup Fis: offset 0x00 UINT8 AhciDmaSetupFisRsvd[0x04]; UINT8 AhciPioSetupFis[0x14]; // Pio Setup Fis: offset 0x20 UINT8 AhciPioSetupFisRsvd[0x0C]; UINT8 AhciD2HRegisterFis[0x14]; // D2H Register Fis: offset 0x40 UINT8 AhciD2HRegisterFisRsvd[0x04]; UINT64 AhciSetDeviceBitsFis; // Set Device Bits Fix: offset 0x58 UINT8 AhciUnknownFis[0x40]; // Unknown Fis: offset 0x60 UINT8 AhciUnknownFisRsvd[0x60]; } EFI_AHCI_RECEIVED_FIS; typedef struct { UINT8 Madt : 5; UINT8 Reserved_5 : 3; UINT8 Deto; UINT16 Reserved_16; UINT32 Reserved_32 : 31; UINT32 Supported : 1; } DEVSLP_TIMING_VARIABLES; #pragma pack() typedef struct { EFI_AHCI_RECEIVED_FIS *AhciRFis; EFI_AHCI_COMMAND_LIST *AhciCmdList; EFI_AHCI_COMMAND_TABLE *AhciCommandTable; EFI_AHCI_RECEIVED_FIS *AhciRFisPciAddr; EFI_AHCI_COMMAND_LIST *AhciCmdListPciAddr; EFI_AHCI_COMMAND_TABLE *AhciCommandTablePciAddr; UINT64 MaxCommandListSize; UINT64 MaxCommandTableSize; UINT64 MaxReceiveFisSize; VOID *MapRFis; VOID *MapCmdList; VOID *MapCommandTable; } EFI_AHCI_REGISTERS; /** This function is used to send out ATAPI commands conforms to the Packet Command with PIO Protocol. @param PciIo The PCI IO protocol instance. @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS. @param Port The number of port. @param PortMultiplier The number of port multiplier. @param Packet A pointer to EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET structure. @retval EFI_SUCCESS send out the ATAPI packet command successfully and device sends data successfully. @retval EFI_DEVICE_ERROR the device failed to send data. **/ EFI_STATUS EFIAPI AhciPacketCommandExecute ( IN EFI_PCI_IO_PROTOCOL *PciIo, IN EFI_AHCI_REGISTERS *AhciRegisters, IN UINT8 Port, IN UINT8 PortMultiplier, IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet ); /** Start command for give slot on specific port. @param PciIo The PCI IO protocol instance. @param Port The number of port. @param CommandSlot The number of CommandSlot. @param Timeout The timeout value of start, uses 100ns as a unit. @retval EFI_DEVICE_ERROR The command start unsuccessfully. @retval EFI_TIMEOUT The operation is time out. @retval EFI_SUCCESS The command start successfully. **/ EFI_STATUS EFIAPI AhciStartCommand ( IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT8 Port, IN UINT8 CommandSlot, IN UINT64 Timeout ); /** Stop command running for giving port @param PciIo The PCI IO protocol instance. @param Port The number of port. @param Timeout The timeout value of stop, uses 100ns as a unit. @retval EFI_DEVICE_ERROR The command stop unsuccessfully. @retval EFI_TIMEOUT The operation is time out. @retval EFI_SUCCESS The command stop successfully. **/ EFI_STATUS EFIAPI AhciStopCommand ( IN EFI_PCI_IO_PROTOCOL *PciIo, IN UINT8 Port, IN UINT64 Timeout ); #endif