2016-06-03 15:54:21 +00:00
/*
* PROJECT : ReactOS Kernel
* LICENSE : GNU GPLv2 only as published by the Free Software Foundation
* PURPOSE : To Implement AHCI Miniport driver targeting storport NT 5.2
* PROGRAMMERS : Aman Priyadarshi ( aman . eureka @ gmail . com )
*/
2016-06-07 11:05:32 +00:00
2016-06-09 23:47:19 +00:00
# include <ntddk.h>
2016-06-20 11:49:22 +00:00
# include <ata.h>
2016-06-09 23:47:19 +00:00
# include <storport.h>
2016-06-02 14:13:06 +00:00
2017-10-13 19:52:38 +00:00
# define NDEBUG
# include <debug.h>
2016-06-09 23:47:19 +00:00
# define DEBUG 1
2017-10-13 19:52:38 +00:00
# if defined(_MSC_VER)
2016-07-04 20:20:25 +00:00
# pragma warning(disable:4214) // bit field types other than int
# pragma warning(disable:4201) // nameless struct/union
2017-10-13 19:52:38 +00:00
# endif
2016-06-09 23:47:19 +00:00
2016-07-04 20:20:25 +00:00
# define MAXIMUM_AHCI_PORT_COUNT 32
2016-06-22 16:08:45 +00:00
# define MAXIMUM_AHCI_PRDT_ENTRIES 32
2016-06-30 16:04:50 +00:00
# define MAXIMUM_AHCI_PORT_NCS 30
2016-06-16 17:02:55 +00:00
# define MAXIMUM_QUEUE_BUFFER_SIZE 255
2016-06-09 23:47:19 +00:00
# define MAXIMUM_TRANSFER_LENGTH (128*1024) // 128 KB
2016-06-07 11:05:32 +00:00
2016-07-23 22:53:15 +00:00
# define DEVICE_ATA_BLOCK_SIZE 512
2016-06-30 16:04:50 +00:00
// device type (DeviceParams)
# define AHCI_DEVICE_TYPE_ATA 1
# define AHCI_DEVICE_TYPE_ATAPI 2
# define AHCI_DEVICE_TYPE_NODEVICE 3
2016-06-07 11:05:32 +00:00
// section 3.1.2
2016-06-09 23:47:19 +00:00
# define AHCI_Global_HBA_CAP_S64A (1 << 31)
2016-06-20 11:49:22 +00:00
2016-07-19 16:50:59 +00:00
// FIS Types : http://wiki.osdev.org/AHCI
# define FIS_TYPE_REG_H2D 0x27 // Register FIS - host to device
# define FIS_TYPE_REG_D2H 0x34 // Register FIS - device to host
# define FIS_TYPE_DMA_ACT 0x39 // DMA activate FIS - device to host
# define FIS_TYPE_DMA_SETUP 0x41 // DMA setup FIS - bidirectional
# define FIS_TYPE_BIST 0x58 // BIST activate FIS - bidirectional
# define FIS_TYPE_PIO_SETUP 0x5F // PIO setup FIS - device to host
# define FIS_TYPE_DEV_BITS 0xA1 // Set device bits FIS - device to host
2016-06-27 12:58:04 +00:00
# define AHCI_ATA_CFIS_FisType 0
# define AHCI_ATA_CFIS_PMPort_C 1
# define AHCI_ATA_CFIS_CommandReg 2
# define AHCI_ATA_CFIS_FeaturesLow 3
# define AHCI_ATA_CFIS_LBA0 4
# define AHCI_ATA_CFIS_LBA1 5
# define AHCI_ATA_CFIS_LBA2 6
# define AHCI_ATA_CFIS_Device 7
# define AHCI_ATA_CFIS_LBA3 8
# define AHCI_ATA_CFIS_LBA4 9
# define AHCI_ATA_CFIS_LBA5 10
# define AHCI_ATA_CFIS_FeaturesHigh 11
# define AHCI_ATA_CFIS_SectorCountLow 12
# define AHCI_ATA_CFIS_SectorCountHigh 13
2016-06-20 11:49:22 +00:00
// ATA Functions
# define ATA_FUNCTION_ATA_COMMAND 0x100
# define ATA_FUNCTION_ATA_IDENTIFY 0x101
2016-07-23 22:53:15 +00:00
# define ATA_FUNCTION_ATA_READ 0x102
2016-06-20 11:49:22 +00:00
// ATAPI Functions
# define ATA_FUNCTION_ATAPI_COMMAND 0x200
// ATA Flags
# define ATA_FLAGS_DATA_IN (1 << 1)
# define ATA_FLAGS_DATA_OUT (1 << 2)
2016-07-23 22:53:15 +00:00
# define ATA_FLAGS_48BIT_COMMAND (1 << 3)
# define ATA_FLAGS_USE_DMA (1 << 4)
2016-06-20 11:49:22 +00:00
# define IsAtaCommand(AtaFunction) (AtaFunction & ATA_FUNCTION_ATA_COMMAND)
# define IsAtapiCommand(AtaFunction) (AtaFunction & ATA_FUNCTION_ATAPI_COMMAND)
# define IsDataTransferNeeded(SrbExtension) (SrbExtension->Flags & (ATA_FLAGS_DATA_IN | ATA_FLAGS_DATA_OUT))
# define IsAdapterCAPS64(CAP) (CAP & AHCI_Global_HBA_CAP_S64A)
2016-06-09 23:47:19 +00:00
// 3.1.1 NCS = CAP[12:08] -> Align
2016-07-23 22:53:15 +00:00
# define AHCI_Global_Port_CAP_NCS(x) (((x) & 0xF00) >> 8)
2016-06-09 23:47:19 +00:00
# define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
2017-10-13 19:52:38 +00:00
//#define AhciDebugPrint(format, ...) StorPortDebugPrint(0, format, __VA_ARGS__)
# define AhciDebugPrint(format, ...) DbgPrint("(%s:%d) " format, __RELFILE__, __LINE__, ##__VA_ARGS__)
2016-06-07 11:05:32 +00:00
2016-06-30 16:04:50 +00:00
typedef
VOID
( * PAHCI_COMPLETION_ROUTINE ) (
__in PVOID PortExtension ,
__in PVOID Srb
) ;
2016-06-07 11:05:32 +00:00
//////////////////////////////////////////////////////////////
// ---- Support Structures --- //
//////////////////////////////////////////////////////////////
2016-06-03 15:54:21 +00:00
2016-06-16 17:02:55 +00:00
// section 3.3.5
typedef union _AHCI_INTERRUPT_STATUS
{
struct
{
ULONG DHRS : 1 ; //Device to Host Register FIS Interrupt
ULONG PSS : 1 ; //PIO Setup FIS Interrupt
ULONG DSS : 1 ; //DMA Setup FIS Interrupt
ULONG SDBS : 1 ; //Set Device Bits Interrupt
ULONG UFS : 1 ; //Unknown FIS Interrupt
ULONG DPS : 1 ; //Descriptor Processed
ULONG PCS : 1 ; //Port Connect Change Status
ULONG DMPS : 1 ; //Device Mechanical Presence Status (DMPS)
ULONG Reserved : 14 ;
ULONG PRCS : 1 ; //PhyRdy Change Status
ULONG IPMS : 1 ; //Incorrect Port Multiplier Status
ULONG OFS : 1 ; //Overflow Status
ULONG Reserved2 : 1 ;
ULONG INFS : 1 ; //Interface Non-fatal Error Status
ULONG IFS : 1 ; //Interface Fatal Error Status
ULONG HBDS : 1 ; //Host Bus Data Error Status
ULONG HBFS : 1 ; //Host Bus Fatal Error Status
ULONG TFES : 1 ; //Task File Error Status
ULONG CPDS : 1 ; //Cold Port Detect Status
} ;
ULONG Status ;
} AHCI_INTERRUPT_STATUS ;
2016-06-03 15:54:21 +00:00
typedef struct _AHCI_FIS_DMA_SETUP
{
ULONG ULONG0_1 ; // FIS_TYPE_DMA_SETUP
// Port multiplier
// Reserved
// Data transfer direction, 1 - device to host
// Interrupt bit
// Auto-activate. Specifies if DMA Activate FIS is needed
UCHAR Reserved [ 2 ] ; // Reserved
ULONG DmaBufferLow ; // DMA Buffer Identifier. Used to Identify DMA buffer in host memory. SATA Spec says host specific and not in Spec. Trying AHCI spec might work.
ULONG DmaBufferHigh ;
2016-06-09 23:47:19 +00:00
ULONG Reserved2 ; // More reserved
ULONG DmaBufferOffset ; // Byte offset into buffer. First 2 bits must be 0
ULONG TranferCount ; // Number of bytes to transfer. Bit 0 must be 0
ULONG Reserved3 ; // Reserved
2016-06-03 15:54:21 +00:00
} AHCI_FIS_DMA_SETUP ;
typedef struct _AHCI_PIO_SETUP_FIS
{
2016-06-09 23:47:19 +00:00
UCHAR FisType ;
2016-06-03 15:54:21 +00:00
UCHAR Reserved1 : 5 ;
2016-06-09 23:47:19 +00:00
UCHAR D : 1 ;
2016-06-03 15:54:21 +00:00
UCHAR I : 1 ;
UCHAR Reserved2 : 1 ;
UCHAR Status ;
UCHAR Error ;
UCHAR SectorNumber ;
UCHAR CylLow ;
UCHAR CylHigh ;
UCHAR Dev_Head ;
UCHAR SectorNumb_Exp ;
UCHAR CylLow_Exp ;
UCHAR CylHigh_Exp ;
UCHAR Reserved3 ;
UCHAR SectorCount ;
UCHAR SectorCount_Exp ;
UCHAR Reserved4 ;
UCHAR E_Status ;
USHORT TransferCount ;
UCHAR Reserved5 [ 2 ] ;
2016-06-07 11:05:32 +00:00
} AHCI_PIO_SETUP_FIS ;
2016-06-03 15:54:21 +00:00
typedef struct _AHCI_D2H_REGISTER_FIS
{
2016-06-07 11:05:32 +00:00
UCHAR FisType ;
2016-06-03 15:54:21 +00:00
UCHAR Reserved1 : 6 ;
UCHAR I : 1 ;
UCHAR Reserved2 : 1 ;
UCHAR Status ;
UCHAR Error ;
UCHAR SectorNumber ;
UCHAR CylLow ;
UCHAR CylHigh ;
UCHAR Dev_Head ;
UCHAR SectorNum_Exp ;
UCHAR CylLow_Exp ;
UCHAR CylHigh_Exp ;
UCHAR Reserved ;
UCHAR SectorCount ;
UCHAR SectorCount_Exp ;
UCHAR Reserved3 [ 2 ] ;
UCHAR Reserved4 [ 4 ] ;
} AHCI_D2H_REGISTER_FIS ;
2016-06-07 11:05:32 +00:00
typedef struct _AHCI_SET_DEVICE_BITS_FIS
{
UCHAR FisType ;
2016-06-03 15:54:21 +00:00
UCHAR PMPort : 4 ;
UCHAR Reserved1 : 2 ;
UCHAR I : 1 ;
UCHAR N : 1 ;
UCHAR Status_Lo : 3 ;
UCHAR Reserved2 : 1 ;
UCHAR Status_Hi : 3 ;
UCHAR Reserved3 : 1 ;
UCHAR Error ;
UCHAR Reserved5 [ 4 ] ;
2016-06-07 11:05:32 +00:00
} AHCI_SET_DEVICE_BITS_FIS ;
2016-06-03 15:54:21 +00:00
2016-06-16 17:02:55 +00:00
typedef struct _AHCI_QUEUE
{
PVOID Buffer [ MAXIMUM_QUEUE_BUFFER_SIZE ] ; // because Storahci hold Srb queue of 255 size
ULONG Head ;
ULONG Tail ;
} AHCI_QUEUE , * PAHCI_QUEUE ;
2016-06-07 11:05:32 +00:00
//////////////////////////////////////////////////////////////
// --------------------------- //
//////////////////////////////////////////////////////////////
2016-06-20 11:49:22 +00:00
typedef union _AHCI_COMMAND_HEADER_DESCRIPTION
{
struct
{
2016-07-04 19:01:07 +00:00
ULONG CFL : 5 ; // Command FIS Length
ULONG A : 1 ; // IsATAPI
ULONG W : 1 ; // Write
ULONG P : 1 ; // Prefetchable
ULONG R : 1 ; // Reset
ULONG B : 1 ; // BIST
ULONG C : 1 ; //Clear Busy upon R_OK
2016-07-19 16:50:59 +00:00
ULONG RSV : 1 ;
2016-07-04 19:01:07 +00:00
ULONG PMP : 4 ; //Port Multiplier Port
ULONG PRDTL : 16 ; //Physical Region Descriptor Table Length
2016-06-20 11:49:22 +00:00
} ;
ULONG Status ;
} AHCI_COMMAND_HEADER_DESCRIPTION ;
2016-07-19 16:50:59 +00:00
typedef union _AHCI_GHC
{
struct
{
ULONG HR : 1 ;
ULONG IE : 1 ;
ULONG MRSM : 1 ;
ULONG RSV0 : 28 ;
ULONG AE : 1 ;
} ;
ULONG Status ;
} AHCI_GHC ;
2016-07-04 19:01:07 +00:00
// section 3.3.7
typedef union _AHCI_PORT_CMD
{
struct
{
ULONG ST : 1 ;
ULONG SUD : 1 ;
ULONG POD : 1 ;
ULONG CLO : 1 ;
ULONG FRE : 1 ;
ULONG RSV0 : 3 ;
ULONG CCS : 5 ;
ULONG MPSS : 1 ;
ULONG FR : 1 ;
ULONG CR : 1 ;
ULONG CPS : 1 ;
ULONG PMA : 1 ;
ULONG HPCP : 1 ;
ULONG MPSP : 1 ;
ULONG CPD : 1 ;
ULONG ESP : 1 ;
ULONG FBSCP : 1 ;
ULONG APSTE : 1 ;
ULONG ATAPI : 1 ;
ULONG DLAE : 1 ;
ULONG ALPE : 1 ;
ULONG ASP : 1 ;
ULONG ICC : 4 ;
} ;
ULONG Status ;
} AHCI_PORT_CMD ;
typedef union _AHCI_SERIAL_ATA_CONTROL
{
struct
{
ULONG DET : 4 ;
ULONG SPD : 4 ;
ULONG IPM : 4 ;
ULONG SPM : 4 ;
ULONG PMP : 4 ;
ULONG DW11_Reserved : 12 ;
} ;
ULONG Status ;
} AHCI_SERIAL_ATA_CONTROL ;
typedef union _AHCI_SERIAL_ATA_STATUS
{
struct
{
ULONG DET : 4 ;
ULONG SPD : 4 ;
ULONG IPM : 4 ;
ULONG RSV0 : 20 ;
} ;
ULONG Status ;
} AHCI_SERIAL_ATA_STATUS ;
2016-07-05 16:51:17 +00:00
typedef union _AHCI_TASK_FILE_DATA
{
struct
{
struct _STS
{
UCHAR ERR : 1 ;
UCHAR CS1 : 2 ;
UCHAR DRQ : 1 ;
UCHAR CS2 : 3 ;
UCHAR BSY : 1 ;
} STS ;
UCHAR ERR ;
USHORT RSV ;
} ;
ULONG Status ;
} AHCI_TASK_FILE_DATA ;
2016-06-22 16:08:45 +00:00
typedef struct _AHCI_PRDT
{
ULONG DBA ;
ULONG DBAU ;
ULONG RSV0 ;
ULONG DBC : 22 ;
ULONG RSV1 : 9 ;
ULONG I : 1 ;
} AHCI_PRDT , * PAHCI_PRDT ;
// 4.2.3 Command Table
typedef struct _AHCI_COMMAND_TABLE
{
// (16 * 32) + 64 + 16 + 48 = 648
// 128 byte aligned :D
UCHAR CFIS [ 64 ] ;
UCHAR ACMD [ 16 ] ;
UCHAR RSV0 [ 48 ] ;
AHCI_PRDT PRDT [ MAXIMUM_AHCI_PRDT_ENTRIES ] ;
} AHCI_COMMAND_TABLE , * PAHCI_COMMAND_TABLE ;
2016-06-07 11:05:32 +00:00
// 4.2.2 Command Header
2016-06-03 15:54:21 +00:00
typedef struct _AHCI_COMMAND_HEADER
{
2016-06-20 11:49:22 +00:00
AHCI_COMMAND_HEADER_DESCRIPTION DI ; // DW 0
2016-07-19 16:50:59 +00:00
ULONG PRDBC ; // DW 1
ULONG CTBA ; // DW 2
ULONG CTBA_U ; // DW 3
ULONG Reserved [ 4 ] ; // DW 4-7
2016-06-03 15:54:21 +00:00
} AHCI_COMMAND_HEADER , * PAHCI_COMMAND_HEADER ;
// Received FIS
typedef struct _AHCI_RECEIVED_FIS
{
2016-06-07 11:05:32 +00:00
struct _AHCI_FIS_DMA_SETUP DmaSetupFIS ; // 0x00 -- DMA Setup FIS
ULONG pad0 ; // 4 BYTE padding
struct _AHCI_PIO_SETUP_FIS PioSetupFIS ; // 0x20 -- PIO Setup FIS
ULONG pad1 [ 3 ] ; // 12 BYTE padding
struct _AHCI_D2H_REGISTER_FIS RegisterFIS ; // 0x40 -- Register – Device to Host FIS
ULONG pad2 ; // 4 BYTE padding
struct _AHCI_SET_DEVICE_BITS_FIS SetDeviceFIS ; // 0x58 -- Set Device Bit FIS
ULONG UnknowFIS [ 16 ] ; // 0x60 -- Unknown FIS
ULONG Reserved [ 24 ] ; // 0xA0 -- Reserved
2016-06-03 15:54:21 +00:00
} AHCI_RECEIVED_FIS , * PAHCI_RECEIVED_FIS ;
2016-06-07 11:05:32 +00:00
// Holds Port Information
2016-06-02 14:13:06 +00:00
typedef struct _AHCI_PORT
{
2016-06-07 11:05:32 +00:00
ULONG CLB ; // 0x00, command list base address, 1K-byte aligned
ULONG CLBU ; // 0x04, command list base address upper 32 bits
ULONG FB ; // 0x08, FIS base address, 256-byte aligned
ULONG FBU ; // 0x0C, FIS base address upper 32 bits
ULONG IS ; // 0x10, interrupt status
ULONG IE ; // 0x14, interrupt enable
ULONG CMD ; // 0x18, command and status
ULONG RSV0 ; // 0x1C, Reserved
ULONG TFD ; // 0x20, task file data
ULONG SIG ; // 0x24, signature
ULONG SSTS ; // 0x28, SATA status (SCR0:SStatus)
ULONG SCTL ; // 0x2C, SATA control (SCR2:SControl)
ULONG SERR ; // 0x30, SATA error (SCR1:SError)
ULONG SACT ; // 0x34, SATA active (SCR3:SActive)
ULONG CI ; // 0x38, command issue
ULONG SNTF ; // 0x3C, SATA notification (SCR4:SNotification)
ULONG FBS ; // 0x40, FIS-based switch control
ULONG RSV1 [ 11 ] ; // 0x44 ~ 0x6F, Reserved
ULONG Vendor [ 4 ] ; // 0x70 ~ 0x7F, vendor specific
2016-06-03 15:54:21 +00:00
} AHCI_PORT , * PAHCI_PORT ;
2016-06-02 14:13:06 +00:00
2016-07-19 16:50:59 +00:00
typedef union _AHCI_INTERRUPT_ENABLE
2016-07-05 16:51:17 +00:00
{
struct
{
ULONG DHRE : 1 ;
ULONG PSE : 1 ;
ULONG DSE : 1 ;
ULONG SDBE : 1 ;
ULONG UFE : 1 ;
ULONG DPE : 1 ;
ULONG PCE : 1 ;
ULONG DMPE : 1 ;
ULONG DW5_Reserved : 14 ;
ULONG PRCE : 1 ;
ULONG IPME : 1 ;
ULONG OFE : 1 ;
ULONG DW5_Reserved2 : 1 ;
ULONG INFE : 1 ;
ULONG IFE : 1 ;
ULONG HBDE : 1 ;
ULONG HBFE : 1 ;
ULONG TFEE : 1 ;
ULONG CPDE : 1 ;
} ;
2016-07-19 16:50:59 +00:00
2016-07-05 16:51:17 +00:00
ULONG Status ;
} AHCI_INTERRUPT_ENABLE ;
2016-07-04 20:20:25 +00:00
2016-06-02 14:13:06 +00:00
typedef struct _AHCI_MEMORY_REGISTERS
{
2016-06-02 14:43:56 +00:00
// 0x00 - 0x2B, Generic Host Control
2016-06-07 11:05:32 +00:00
ULONG CAP ; // 0x00, Host capability
ULONG GHC ; // 0x04, Global host control
ULONG IS ; // 0x08, Interrupt status
ULONG PI ; // 0x0C, Port implemented
ULONG VS ; // 0x10, Version
ULONG CCC_CTL ; // 0x14, Command completion coalescing control
ULONG CCC_PTS ; // 0x18, Command completion coalescing ports
ULONG EM_LOC ; // 0x1C, Enclosure management location
ULONG EM_CTL ; // 0x20, Enclosure management control
ULONG CAP2 ; // 0x24, Host capabilities extended
ULONG BOHC ; // 0x28, BIOS/OS handoff control and status
2016-07-04 20:20:25 +00:00
ULONG Reserved [ 0x1d ] ; // 0x2C - 0x9F, Reserved
ULONG VendorSpecific [ 0x18 ] ; // 0xA0 - 0xFF, Vendor specific registers
2016-06-07 11:05:32 +00:00
AHCI_PORT PortList [ MAXIMUM_AHCI_PORT_COUNT ] ;
2016-06-02 14:13:06 +00:00
} AHCI_MEMORY_REGISTERS , * PAHCI_MEMORY_REGISTERS ;
2016-06-07 11:05:32 +00:00
// Holds information for each attached attached port to a given adapter.
2016-06-03 15:54:21 +00:00
typedef struct _AHCI_PORT_EXTENSION
{
ULONG PortNumber ;
2016-06-30 16:04:50 +00:00
ULONG QueueSlots ; // slots which we have already assigned task (Slot)
ULONG CommandIssuedSlots ; // slots which has been programmed
2016-07-19 16:50:59 +00:00
ULONG MaxPortQueueDepth ;
struct
{
UCHAR RemovableDevice ;
UCHAR Lba48BitMode ;
UCHAR AccessType ;
UCHAR DeviceType ;
UCHAR IsActive ;
2016-07-23 22:53:15 +00:00
LARGE_INTEGER MaxLba ;
ULONG BytesPerLogicalSector ;
ULONG BytesPerPhysicalSector ;
2016-08-14 12:54:10 +00:00
UCHAR VendorId [ 41 ] ;
UCHAR RevisionID [ 9 ] ;
UCHAR SerialNumber [ 21 ] ;
2016-07-19 16:50:59 +00:00
} DeviceParams ;
STOR_DPC CommandCompletion ;
2016-06-07 11:05:32 +00:00
PAHCI_PORT Port ; // AHCI Port Infomation
2016-06-30 16:04:50 +00:00
AHCI_QUEUE SrbQueue ; // pending Srbs
2016-07-19 16:50:59 +00:00
AHCI_QUEUE CompletionQueue ;
2016-06-30 16:04:50 +00:00
PSCSI_REQUEST_BLOCK Slot [ MAXIMUM_AHCI_PORT_NCS ] ; // Srbs which has been alloted a port
2016-06-03 15:54:21 +00:00
PAHCI_RECEIVED_FIS ReceivedFIS ;
2016-06-07 11:05:32 +00:00
PAHCI_COMMAND_HEADER CommandList ;
STOR_DEVICE_POWER_STATE DevicePowerState ; // Device Power State
2016-06-27 12:58:04 +00:00
PIDENTIFY_DEVICE_DATA IdentifyDeviceData ;
STOR_PHYSICAL_ADDRESS IdentifyDeviceDataPhysicalAddress ;
2016-06-07 11:05:32 +00:00
struct _AHCI_ADAPTER_EXTENSION * AdapterExtension ; // Port's Adapter Information
2016-06-03 15:54:21 +00:00
} AHCI_PORT_EXTENSION , * PAHCI_PORT_EXTENSION ;
2016-06-07 11:05:32 +00:00
// Holds Adapter Information
2016-06-02 14:13:06 +00:00
typedef struct _AHCI_ADAPTER_EXTENSION
{
2016-06-02 14:43:56 +00:00
ULONG SystemIoBusNumber ;
ULONG SlotNumber ;
ULONG AhciBaseAddress ;
2016-06-07 11:05:32 +00:00
PULONG IS ; // Interrupt Status, In case of MSIM == `1`
ULONG PortImplemented ; // bit-mapping of ports which are implemented
2016-06-16 21:14:03 +00:00
ULONG PortCount ;
2016-06-02 14:13:06 +00:00
2016-06-02 14:43:56 +00:00
USHORT VendorID ;
USHORT DeviceID ;
USHORT RevisionID ;
2016-06-02 14:13:06 +00:00
2016-06-02 14:43:56 +00:00
ULONG Version ;
ULONG CAP ;
ULONG CAP2 ;
2016-06-07 18:06:51 +00:00
ULONG LastInterruptPort ;
2016-06-20 11:49:22 +00:00
ULONG CurrentCommandSlot ;
2016-06-03 15:54:21 +00:00
2016-06-30 16:04:50 +00:00
PVOID NonCachedExtension ; // holds virtual address to noncached buffer allocated for Port Extension
2016-06-07 11:05:32 +00:00
struct
{
// Message per port or shared port?
ULONG MessagePerPort : 1 ;
ULONG Removed : 1 ;
ULONG Reserved : 30 ; // not in use -- maintain 4 byte alignment
} StateFlags ;
2016-06-03 15:54:21 +00:00
2016-06-02 14:43:56 +00:00
PAHCI_MEMORY_REGISTERS ABAR_Address ;
2016-06-07 11:05:32 +00:00
AHCI_PORT_EXTENSION PortExtension [ MAXIMUM_AHCI_PORT_COUNT ] ;
2016-06-02 14:13:06 +00:00
} AHCI_ADAPTER_EXTENSION , * PAHCI_ADAPTER_EXTENSION ;
2016-06-22 16:08:45 +00:00
typedef struct _LOCAL_SCATTER_GATHER_LIST
2016-06-20 11:49:22 +00:00
{
2016-06-22 16:08:45 +00:00
ULONG NumberOfElements ;
ULONG_PTR Reserved ;
STOR_SCATTER_GATHER_ELEMENT List [ MAXIMUM_AHCI_PRDT_ENTRIES ] ;
} LOCAL_SCATTER_GATHER_LIST , * PLOCAL_SCATTER_GATHER_LIST ;
2016-06-20 11:49:22 +00:00
2016-06-02 14:13:06 +00:00
typedef struct _AHCI_SRB_EXTENSION
{
2016-06-22 16:08:45 +00:00
AHCI_COMMAND_TABLE CommandTable ;
2016-06-20 11:49:22 +00:00
ULONG AtaFunction ;
ULONG Flags ;
2016-06-27 12:58:04 +00:00
UCHAR CommandReg ;
UCHAR FeaturesLow ;
UCHAR LBA0 ;
UCHAR LBA1 ;
UCHAR LBA2 ;
UCHAR Device ;
UCHAR LBA3 ;
UCHAR LBA4 ;
UCHAR LBA5 ;
UCHAR FeaturesHigh ;
UCHAR SectorCountLow ;
UCHAR SectorCountHigh ;
2016-06-20 11:49:22 +00:00
ULONG SlotIndex ;
2016-06-22 16:08:45 +00:00
LOCAL_SCATTER_GATHER_LIST Sgl ;
2016-07-23 22:53:15 +00:00
PLOCAL_SCATTER_GATHER_LIST pSgl ;
2016-06-30 16:04:50 +00:00
PAHCI_COMPLETION_ROUTINE CompletionRoutine ;
2016-07-23 22:53:15 +00:00
// for alignment purpose -- 128 byte alignment
// do not try to access (R/W) this field
UCHAR Reserved [ 128 ] ;
2016-06-20 11:49:22 +00:00
} AHCI_SRB_EXTENSION , * PAHCI_SRB_EXTENSION ;
2016-06-07 18:06:51 +00:00
//////////////////////////////////////////////////////////////
// Declarations //
//////////////////////////////////////////////////////////////
2016-07-25 11:09:25 +00:00
VOID
AhciProcessIO (
__in PAHCI_ADAPTER_EXTENSION AdapterExtension ,
__in UCHAR PathId ,
__in PSCSI_REQUEST_BLOCK Srb
) ;
2016-06-09 23:47:19 +00:00
BOOLEAN
AhciAdapterReset (
2016-06-10 08:27:20 +00:00
__in PAHCI_ADAPTER_EXTENSION AdapterExtension
2016-06-09 23:47:19 +00:00
) ;
2016-06-07 18:06:51 +00:00
__inline
2016-06-09 23:47:19 +00:00
VOID
AhciZeroMemory (
2016-06-10 08:27:20 +00:00
__out PCHAR Buffer ,
__in ULONG BufferSize
2016-06-09 23:47:19 +00:00
) ;
2016-06-07 18:06:51 +00:00
__inline
2016-06-09 23:47:19 +00:00
BOOLEAN
IsPortValid (
2016-06-10 08:27:20 +00:00
__in PAHCI_ADAPTER_EXTENSION AdapterExtension ,
2016-07-04 20:20:25 +00:00
__in ULONG pathId
2016-06-09 23:47:19 +00:00
) ;
2016-07-25 19:50:09 +00:00
UCHAR DeviceRequestSense (
__in PAHCI_ADAPTER_EXTENSION AdapterExtension ,
__in PSCSI_REQUEST_BLOCK Srb ,
__in PCDB Cdb
) ;
2016-07-23 22:53:15 +00:00
UCHAR DeviceRequestReadWrite (
__in PAHCI_ADAPTER_EXTENSION AdapterExtension ,
__in PSCSI_REQUEST_BLOCK Srb ,
__in PCDB Cdb
) ;
UCHAR DeviceRequestCapacity (
__in PAHCI_ADAPTER_EXTENSION AdapterExtension ,
__in PSCSI_REQUEST_BLOCK Srb ,
__in PCDB Cdb
) ;
2016-07-04 20:20:25 +00:00
UCHAR
2016-06-09 23:47:19 +00:00
DeviceInquiryRequest (
2016-06-10 08:27:20 +00:00
__in PAHCI_ADAPTER_EXTENSION AdapterExtension ,
__in PSCSI_REQUEST_BLOCK Srb ,
2016-07-23 22:53:15 +00:00
__in PCDB Cdb
) ;
2016-07-25 11:09:25 +00:00
UCHAR DeviceRequestComplete (
__in PAHCI_ADAPTER_EXTENSION AdapterExtension ,
__in PSCSI_REQUEST_BLOCK Srb ,
__in PCDB Cdb
) ;
2016-07-23 22:53:15 +00:00
UCHAR DeviceReportLuns (
__in PAHCI_ADAPTER_EXTENSION AdapterExtension ,
__in PSCSI_REQUEST_BLOCK Srb ,
__in PCDB Cdb
2016-06-09 23:47:19 +00:00
) ;
2016-06-16 17:02:55 +00:00
__inline
BOOLEAN
AddQueue (
__inout PAHCI_QUEUE Queue ,
__in PVOID Srb
) ;
__inline
PVOID
RemoveQueue (
__inout PAHCI_QUEUE Queue
) ;
2016-06-22 16:08:45 +00:00
__inline
PAHCI_SRB_EXTENSION
GetSrbExtension (
__in PSCSI_REQUEST_BLOCK Srb
) ;
2016-07-05 16:51:17 +00:00
2016-07-23 22:53:15 +00:00
__inline
ULONG64
AhciGetLba (
2016-07-25 11:09:25 +00:00
__in PCDB Cdb ,
__in ULONG CdbLength
2016-07-23 22:53:15 +00:00
) ;
2016-07-05 16:51:17 +00:00
//////////////////////////////////////////////////////////////
// Assertions //
//////////////////////////////////////////////////////////////
2016-07-19 16:50:59 +00:00
// I assert every silly mistake I can do while coding
// because god never help me debugging the code
// but these asserts do :')
C_ASSERT ( FIELD_OFFSET ( AHCI_MEMORY_REGISTERS , CAP ) = = 0x00 ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_MEMORY_REGISTERS , GHC ) = = 0x04 ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_MEMORY_REGISTERS , IS ) = = 0x08 ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_MEMORY_REGISTERS , PI ) = = 0x0C ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_MEMORY_REGISTERS , VS ) = = 0x10 ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_MEMORY_REGISTERS , CCC_CTL ) = = 0x14 ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_MEMORY_REGISTERS , CCC_PTS ) = = 0x18 ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_MEMORY_REGISTERS , EM_LOC ) = = 0x1C ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_MEMORY_REGISTERS , EM_CTL ) = = 0x20 ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_MEMORY_REGISTERS , CAP2 ) = = 0x24 ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_MEMORY_REGISTERS , BOHC ) = = 0x28 ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_MEMORY_REGISTERS , Reserved ) = = 0x2C ) ;
2016-07-05 16:51:17 +00:00
C_ASSERT ( FIELD_OFFSET ( AHCI_MEMORY_REGISTERS , VendorSpecific ) = = 0xA0 ) ;
2016-07-19 16:50:59 +00:00
C_ASSERT ( FIELD_OFFSET ( AHCI_MEMORY_REGISTERS , PortList ) = = 0x100 ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_PORT , CLB ) = = 0x00 ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_PORT , CLBU ) = = 0x04 ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_PORT , FB ) = = 0x08 ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_PORT , FBU ) = = 0x0C ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_PORT , IS ) = = 0x10 ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_PORT , IE ) = = 0x14 ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_PORT , CMD ) = = 0x18 ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_PORT , RSV0 ) = = 0x1C ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_PORT , TFD ) = = 0x20 ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_PORT , SIG ) = = 0x24 ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_PORT , SSTS ) = = 0x28 ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_PORT , SCTL ) = = 0x2C ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_PORT , SERR ) = = 0x30 ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_PORT , SACT ) = = 0x34 ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_PORT , CI ) = = 0x38 ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_PORT , SNTF ) = = 0x3C ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_PORT , FBS ) = = 0x40 ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_PORT , RSV1 ) = = 0x44 ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_PORT , Vendor ) = = 0x70 ) ;
C_ASSERT ( ( sizeof ( AHCI_COMMAND_TABLE ) % 128 ) = = 0 ) ;
C_ASSERT ( sizeof ( AHCI_GHC ) = = sizeof ( ULONG ) ) ;
C_ASSERT ( sizeof ( AHCI_PORT_CMD ) = = sizeof ( ULONG ) ) ;
C_ASSERT ( sizeof ( AHCI_TASK_FILE_DATA ) = = sizeof ( ULONG ) ) ;
C_ASSERT ( sizeof ( AHCI_INTERRUPT_ENABLE ) = = sizeof ( ULONG ) ) ;
C_ASSERT ( sizeof ( AHCI_SERIAL_ATA_STATUS ) = = sizeof ( ULONG ) ) ;
C_ASSERT ( sizeof ( AHCI_SERIAL_ATA_CONTROL ) = = sizeof ( ULONG ) ) ;
C_ASSERT ( sizeof ( AHCI_COMMAND_HEADER_DESCRIPTION ) = = sizeof ( ULONG ) ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_COMMAND_TABLE , CFIS ) = = 0x00 ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_COMMAND_TABLE , ACMD ) = = 0x40 ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_COMMAND_TABLE , RSV0 ) = = 0x50 ) ;
C_ASSERT ( FIELD_OFFSET ( AHCI_COMMAND_TABLE , PRDT ) = = 0x80 ) ;