* PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com)
*/
-#include "miniport.h"
-#include "storport.h"
+#include <ntddk.h>
+#include <ata.h>
+#include <storport.h>
-#define AHCI_POOL_TAG 'ahci'
-#define MAXIMUM_AHCI_PORT_COUNT 12
+#define NDEBUG
+#include <debug.h>
+
+#define DEBUG 1
+#if defined(_MSC_VER)
+#pragma warning(disable:4214) // bit field types other than int
+#pragma warning(disable:4201) // nameless struct/union
+#endif
+
+#define MAXIMUM_AHCI_PORT_COUNT 32
+#define MAXIMUM_AHCI_PRDT_ENTRIES 32
+#define MAXIMUM_AHCI_PORT_NCS 30
+#define MAXIMUM_QUEUE_BUFFER_SIZE 255
+#define MAXIMUM_TRANSFER_LENGTH (128*1024) // 128 KB
+
+#define DEVICE_ATA_BLOCK_SIZE 512
+
+// device type (DeviceParams)
+#define AHCI_DEVICE_TYPE_ATA 1
+#define AHCI_DEVICE_TYPE_ATAPI 2
+#define AHCI_DEVICE_TYPE_NODEVICE 3
// section 3.1.2
-#define AHCI_Global_HBA_CONTROL_HR (0x1<<0)
-#define AHCI_Global_HBA_CONTROL_IE (0x1<<1)
-#define AHCI_Global_HBA_CONTROL_MRSM (0x1<<2)
-#define AHCI_Global_HBA_CONTROL_AE (0x1<<31)
+#define AHCI_Global_HBA_CAP_S64A (1 << 31)
+
+// 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
+
+#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
+
+// ATA Functions
+#define ATA_FUNCTION_ATA_COMMAND 0x100
+#define ATA_FUNCTION_ATA_IDENTIFY 0x101
+#define ATA_FUNCTION_ATA_READ 0x102
+
+// ATAPI Functions
+#define ATA_FUNCTION_ATAPI_COMMAND 0x200
+
+// ATA Flags
+#define ATA_FLAGS_DATA_IN (1 << 1)
+#define ATA_FLAGS_DATA_OUT (1 << 2)
+#define ATA_FLAGS_48BIT_COMMAND (1 << 3)
+#define ATA_FLAGS_USE_DMA (1 << 4)
+
+#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)
+
+// 3.1.1 NCS = CAP[12:08] -> Align
+#define AHCI_Global_Port_CAP_NCS(x) (((x) & 0xF00) >> 8)
+
+#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
+//#define AhciDebugPrint(format, ...) StorPortDebugPrint(0, format, __VA_ARGS__)
+#define AhciDebugPrint(format, ...) DbgPrint("(%s:%d) " format, __RELFILE__, __LINE__, ##__VA_ARGS__)
+
+typedef
+VOID
+(*PAHCI_COMPLETION_ROUTINE) (
+ __in PVOID PortExtension,
+ __in PVOID Srb
+ );
//////////////////////////////////////////////////////////////
// ---- Support Structures --- //
//////////////////////////////////////////////////////////////
+// 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;
+
typedef struct _AHCI_FIS_DMA_SETUP
{
ULONG ULONG0_1; // FIS_TYPE_DMA_SETUP
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;
- 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
+ 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
} AHCI_FIS_DMA_SETUP;
typedef struct _AHCI_PIO_SETUP_FIS
{
- UCHAR FisType; //0x5F
+ UCHAR FisType;
UCHAR Reserved1 :5;
- UCHAR D :1; // 1 is write (device to host)
+ UCHAR D :1;
UCHAR I :1;
UCHAR Reserved2 :1;
UCHAR Status;
UCHAR Reserved5[4];
} AHCI_SET_DEVICE_BITS_FIS;
+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;
+
//////////////////////////////////////////////////////////////
// --------------------------- //
//////////////////////////////////////////////////////////////
+typedef union _AHCI_COMMAND_HEADER_DESCRIPTION
+{
+ struct
+ {
+ 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
+ ULONG RSV : 1;
+ ULONG PMP : 4; //Port Multiplier Port
+
+ ULONG PRDTL : 16; //Physical Region Descriptor Table Length
+ };
+
+ ULONG Status;
+} AHCI_COMMAND_HEADER_DESCRIPTION;
+
+typedef union _AHCI_GHC
+{
+ struct
+ {
+ ULONG HR : 1;
+ ULONG IE : 1;
+ ULONG MRSM : 1;
+ ULONG RSV0 : 28;
+ ULONG AE : 1;
+ };
+
+ ULONG Status;
+} AHCI_GHC;
+
+// 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;
+
+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;
+
+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;
+
// 4.2.2 Command Header
typedef struct _AHCI_COMMAND_HEADER
{
- ULONG HEADER_DESCRIPTION; // DW 0
- ULONG PRDBC; // DW 1
- ULONG CTBA0; // DW 2
- ULONG CTBA_U0; // DW 3
- ULONG Reserved[4]; // DW 4-7
+ AHCI_COMMAND_HEADER_DESCRIPTION DI; // DW 0
+ ULONG PRDBC; // DW 1
+ ULONG CTBA; // DW 2
+ ULONG CTBA_U; // DW 3
+ ULONG Reserved[4]; // DW 4-7
} AHCI_COMMAND_HEADER, *PAHCI_COMMAND_HEADER;
// Received FIS
ULONG Vendor[4]; // 0x70 ~ 0x7F, vendor specific
} AHCI_PORT, *PAHCI_PORT;
+typedef union _AHCI_INTERRUPT_ENABLE
+{
+ 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;
+ };
+
+ ULONG Status;
+} AHCI_INTERRUPT_ENABLE;
+
typedef struct _AHCI_MEMORY_REGISTERS
{
// 0x00 - 0x2B, Generic Host Control
ULONG EM_CTL; // 0x20, Enclosure management control
ULONG CAP2; // 0x24, Host capabilities extended
ULONG BOHC; // 0x28, BIOS/OS handoff control and status
- ULONG Reserved[0xA0-0x2C]; // 0x2C - 0x9F, Reserved
- ULONG VendorSpecific[0x100-0xA0]; // 0xA0 - 0xFF, Vendor specific registers
+ ULONG Reserved[0x1d]; // 0x2C - 0x9F, Reserved
+ ULONG VendorSpecific[0x18]; // 0xA0 - 0xFF, Vendor specific registers
AHCI_PORT PortList[MAXIMUM_AHCI_PORT_COUNT];
-
} AHCI_MEMORY_REGISTERS, *PAHCI_MEMORY_REGISTERS;
// Holds information for each attached attached port to a given adapter.
typedef struct _AHCI_PORT_EXTENSION
{
ULONG PortNumber;
- BOOLEAN IsActive;
+ ULONG QueueSlots; // slots which we have already assigned task (Slot)
+ ULONG CommandIssuedSlots; // slots which has been programmed
+ ULONG MaxPortQueueDepth;
+
+ struct
+ {
+ UCHAR RemovableDevice;
+ UCHAR Lba48BitMode;
+ UCHAR AccessType;
+ UCHAR DeviceType;
+ UCHAR IsActive;
+ LARGE_INTEGER MaxLba;
+ ULONG BytesPerLogicalSector;
+ ULONG BytesPerPhysicalSector;
+ UCHAR VendorId[41];
+ UCHAR RevisionID[9];
+ UCHAR SerialNumber[21];
+ } DeviceParams;
+
+ STOR_DPC CommandCompletion;
PAHCI_PORT Port; // AHCI Port Infomation
+ AHCI_QUEUE SrbQueue; // pending Srbs
+ AHCI_QUEUE CompletionQueue;
+ PSCSI_REQUEST_BLOCK Slot[MAXIMUM_AHCI_PORT_NCS]; // Srbs which has been alloted a port
PAHCI_RECEIVED_FIS ReceivedFIS;
PAHCI_COMMAND_HEADER CommandList;
STOR_DEVICE_POWER_STATE DevicePowerState; // Device Power State
+ PIDENTIFY_DEVICE_DATA IdentifyDeviceData;
+ STOR_PHYSICAL_ADDRESS IdentifyDeviceDataPhysicalAddress;
struct _AHCI_ADAPTER_EXTENSION* AdapterExtension; // Port's Adapter Information
} AHCI_PORT_EXTENSION, *PAHCI_PORT_EXTENSION;
ULONG AhciBaseAddress;
PULONG IS;// Interrupt Status, In case of MSIM == `1`
ULONG PortImplemented;// bit-mapping of ports which are implemented
+ ULONG PortCount;
USHORT VendorID;
USHORT DeviceID;
ULONG Version;
ULONG CAP;
ULONG CAP2;
+ ULONG LastInterruptPort;
+ ULONG CurrentCommandSlot;
- PVOID NonCachedExtension;// holds virtual address to noncached buffer allocated for Port Extension
+ PVOID NonCachedExtension; // holds virtual address to noncached buffer allocated for Port Extension
struct
{
AHCI_PORT_EXTENSION PortExtension[MAXIMUM_AHCI_PORT_COUNT];
} AHCI_ADAPTER_EXTENSION, *PAHCI_ADAPTER_EXTENSION;
+typedef struct _LOCAL_SCATTER_GATHER_LIST
+{
+ ULONG NumberOfElements;
+ ULONG_PTR Reserved;
+ STOR_SCATTER_GATHER_ELEMENT List[MAXIMUM_AHCI_PRDT_ENTRIES];
+} LOCAL_SCATTER_GATHER_LIST, *PLOCAL_SCATTER_GATHER_LIST;
+
typedef struct _AHCI_SRB_EXTENSION
{
- ULONG Reserved[4];
-} AHCI_SRB_EXTENSION;
+ AHCI_COMMAND_TABLE CommandTable;
+ ULONG AtaFunction;
+ ULONG Flags;
+
+ UCHAR CommandReg;
+ UCHAR FeaturesLow;
+ UCHAR LBA0;
+ UCHAR LBA1;
+ UCHAR LBA2;
+ UCHAR Device;
+ UCHAR LBA3;
+ UCHAR LBA4;
+ UCHAR LBA5;
+ UCHAR FeaturesHigh;
+
+ UCHAR SectorCountLow;
+ UCHAR SectorCountHigh;
+
+ ULONG SlotIndex;
+ LOCAL_SCATTER_GATHER_LIST Sgl;
+ PLOCAL_SCATTER_GATHER_LIST pSgl;
+ PAHCI_COMPLETION_ROUTINE CompletionRoutine;
+
+ // for alignment purpose -- 128 byte alignment
+ // do not try to access (R/W) this field
+ UCHAR Reserved[128];
+} AHCI_SRB_EXTENSION, *PAHCI_SRB_EXTENSION;
+
+//////////////////////////////////////////////////////////////
+// Declarations //
+//////////////////////////////////////////////////////////////
+
+VOID
+AhciProcessIO (
+ __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
+ __in UCHAR PathId,
+ __in PSCSI_REQUEST_BLOCK Srb
+ );
+
+BOOLEAN
+AhciAdapterReset (
+ __in PAHCI_ADAPTER_EXTENSION AdapterExtension
+ );
+
+__inline
+VOID
+AhciZeroMemory (
+ __out PCHAR Buffer,
+ __in ULONG BufferSize
+ );
+
+__inline
+BOOLEAN
+IsPortValid (
+ __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
+ __in ULONG pathId
+ );
+
+UCHAR DeviceRequestSense (
+ __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
+ __in PSCSI_REQUEST_BLOCK Srb,
+ __in PCDB Cdb
+ );
+
+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
+ );
+
+UCHAR
+DeviceInquiryRequest (
+ __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
+ __in PSCSI_REQUEST_BLOCK Srb,
+ __in PCDB Cdb
+ );
+
+UCHAR DeviceRequestComplete (
+ __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
+ __in PSCSI_REQUEST_BLOCK Srb,
+ __in PCDB Cdb
+ );
+
+UCHAR DeviceReportLuns (
+ __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
+ __in PSCSI_REQUEST_BLOCK Srb,
+ __in PCDB Cdb
+ );
+
+__inline
+BOOLEAN
+AddQueue (
+ __inout PAHCI_QUEUE Queue,
+ __in PVOID Srb
+ );
+
+__inline
+PVOID
+RemoveQueue (
+ __inout PAHCI_QUEUE Queue
+ );
+
+__inline
+PAHCI_SRB_EXTENSION
+GetSrbExtension(
+ __in PSCSI_REQUEST_BLOCK Srb
+ );
+
+__inline
+ULONG64
+AhciGetLba (
+ __in PCDB Cdb,
+ __in ULONG CdbLength
+ );
+
+//////////////////////////////////////////////////////////////
+// Assertions //
+//////////////////////////////////////////////////////////////
+
+// 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);
+C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, VendorSpecific) == 0xA0);
+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);