__in PAHCI_ADAPTER_EXTENSION adapterExtension
);
+__inline
VOID AhciZeroMemory(
__in PCHAR buffer,
__in ULONG bufferSize
);
+__inline
+BOOLEAN IsPortValid(
+ __in PAHCI_ADAPTER_EXTENSION adapterExtension,
+ __in UCHAR pathId
+);
+
/**
* @name AhciPortInitialize
* @implemented
adapterExtension = portExtension->AdapterExtension;
abar = adapterExtension->ABAR_Address;
+
portExtension->Port = &abar->PortList[portExtension->PortNumber];
commandListPhysical = StorPortGetPhysicalAddress(adapterExtension, NULL, portExtension->CommandList, &mappedLength);
StorPortWriteRegisterUlong(adapterExtension, &portExtension->Port->CLB, commandListPhysical.LowPart);
StorPortWriteRegisterUlong(adapterExtension, &portExtension->Port->FB, receivedFISPhysical.LowPart);
+ // set device power state flag to D0
+ portExtension->DevicePowerState = StorPowerDeviceD0;
+
+ // clear pending interrupts
+ StorPortWriteRegisterUlong(adapterExtension, &portExtension->Port->SERR, (ULONG)-1);
+ StorPortWriteRegisterUlong(adapterExtension, &portExtension->Port->IS, (ULONG)-1);
+ StorPortWriteRegisterUlong(adapterExtension, portExtension->AdapterExtension->IS, (1 << portExtension->PortNumber));
+
return TRUE;
}// -- AhciPortInitialize();
StorPortDebugPrint(0, "AhciAllocateResourceForAdapter()\n");
- // 3.1.1 NCS = CAP[12:08] -> Align
+ // 3.1.1 NCS = CAP[12:08] -> Align
NCS = (adapterExtension->CAP & 0xF00) >> 8;
AlignedNCS = ((NCS/8) + 1) * 8;
nonCachedExtension = (PCHAR)adapterExtension->NonCachedExtension;
AhciZeroMemory(nonCachedExtension, nonCachedExtensionSize);
-
-
- // allocate memory for port extension
- /* --> Allocate memory for port extension, but right now it is returning STOR_STATUS_NOT_IMPLEMENTED
- so, for testing purpose, I allocated during driver entry itself.
- status = StorPortAllocatePool(
- adapterExtension,
- portCount * sizeof(AHCI_PORT_EXTENSION),
- AHCI_POOL_TAG,
- (PVOID*)&portsExtension);
-
- if (status != STOR_STATUS_SUCCESS){
- StorPortDebugPrint(0, "\tstatus : %x\n", status);
- return FALSE;
- }
- AhciZeroMemory((PCHAR)portsExtension, portCount * sizeof(AHCI_PORT_EXTENSION));
- */
nonCachedExtensionSize /= portCount;
currentCount = 0;
- for (index = 0; index < 32; index++)
+ for (index = 0; index < MAXIMUM_AHCI_PORT_COUNT; index++)
{
+ adapterExtension->PortExtension[index].IsActive = FALSE;
if ((adapterExtension->PortImplemented & (1<<index)) != 0)
{
- //adapterExtension->PortExtension[index] = (PAHCI_PORT_EXTENSION)((PCHAR)portsExtension + sizeof(AHCI_PORT_EXTENSION) * currentCount);
-
adapterExtension->PortExtension[index].PortNumber = index;
+ adapterExtension->PortExtension[index].IsActive = TRUE;
adapterExtension->PortExtension[index].AdapterExtension = adapterExtension;
adapterExtension->PortExtension[index].CommandList = (PAHCI_COMMAND_HEADER)(nonCachedExtension + (currentCount*nonCachedExtensionSize));
adapterExtension->PortExtension[index].ReceivedFIS = (PAHCI_RECEIVED_FIS)((PCHAR)adapterExtension->PortExtension[index].CommandList + sizeof(AHCI_COMMAND_HEADER) * AlignedNCS);
__in PVOID AdapterExtension
)
{
+ ULONG ghc, messageCount, status;
PAHCI_ADAPTER_EXTENSION adapterExtension;
StorPortDebugPrint(0, "AhciHwInitialize()\n");
adapterExtension = (PAHCI_ADAPTER_EXTENSION)AdapterExtension;
+ adapterExtension->StateFlags.MessagePerPort = FALSE;
+
+ // First check what type of interrupt/synchronization device is using
+ ghc = StorPortReadRegisterUlong(adapterExtension, &adapterExtension->ABAR_Address->GHC);
+
+ //When set to ‘1’ by hardware, indicates that the HBA requested more than one MSI vector
+ //but has reverted to using the first vector only. When this bit is cleared to ‘0’,
+ //the HBA has not reverted to single MSI mode (i.e. hardware is already in single MSI mode,
+ //software has allocated the number of messages requested
+ if ((ghc & AHCI_Global_HBA_CONTROL_MRSM) == 0)
+ {
+ adapterExtension->StateFlags.MessagePerPort = TRUE;
+ StorPortDebugPrint(0, "\tMultiple MSI based message not supported\n");
+ }
return TRUE;
}// -- AhciHwInitialize();
adapterExtension = (PAHCI_ADAPTER_EXTENSION)AdapterExtension;
- return TRUE;
+ return FALSE;
}// -- AhciHwInterrupt();
/**
)
{
- UCHAR function;
+ UCHAR function, pathId;
PAHCI_ADAPTER_EXTENSION adapterExtension;
StorPortDebugPrint(0, "AhciHwStartIo()\n");
- adapterExtension = (PAHCI_ADAPTER_EXTENSION)AdapterExtension;
+ pathId = Srb->PathId;
function = Srb->Function;
+ adapterExtension = (PAHCI_ADAPTER_EXTENSION)AdapterExtension;
+
+ if (!IsPortValid(adapterExtension, pathId))
+ {
+ Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
+ StorPortNotification(RequestComplete, adapterExtension, Srb);
+ return TRUE;
+ }
+ // https://msdn.microsoft.com/windows/hardware/drivers/storage/handling-srb-function-pnp
+ // If the function member of an SRB is set to SRB_FUNCTION_PNP,
+ // the SRB is a structure of type SCSI_PNP_REQUEST_BLOCK.
+ if (function == SRB_FUNCTION_PNP)
+ {
+ PSCSI_PNP_REQUEST_BLOCK pnpRequest;
+
+ pnpRequest = (PSCSI_PNP_REQUEST_BLOCK)Srb;
+ if ((pnpRequest->SrbPnPFlags & SRB_PNP_FLAGS_ADAPTER_REQUEST) != 0)
+ {
+ if (pnpRequest->PnPAction == StorRemoveDevice ||
+ pnpRequest->PnPAction == StorSurpriseRemoval)
+ {
+ Srb->SrbStatus = SRB_STATUS_SUCCESS;
+ adapterExtension->StateFlags.Removed = 1;
+ StorPortDebugPrint(0, "\tadapter removed\n");
+ }
+ else if (pnpRequest->PnPAction == StorStopDevice)
+ {
+ Srb->SrbStatus = SRB_STATUS_SUCCESS;
+ StorPortDebugPrint(0, "\tRequested to Stop the adapter\n");
+ }
+ else
+ Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
+ StorPortNotification(RequestComplete, adapterExtension, Srb);
+ return TRUE;
+ }
+ }
+
+ if (function == SRB_FUNCTION_EXECUTE_SCSI)
+ {
+ // https://msdn.microsoft.com/en-us/windows/hardware/drivers/storage/handling-srb-function-execute-scsi
+ // On receipt of an SRB_FUNCTION_EXECUTE_SCSI request, a miniport driver's HwScsiStartIo
+ // routine does the following:
+ //
+ // - Gets and/or sets up whatever context the miniport driver maintains in its device,
+ // logical unit, and/or SRB extensions
+ // For example, a miniport driver might set up a logical unit extension with pointers
+ // to the SRB itself and the SRB DataBuffer pointer, the SRB DataTransferLength value,
+ // and a driver-defined value (or CDB SCSIOP_XXX value) indicating the operation to be
+ // carried out on the HBA.
+ //
+ // - Calls an internal routine to program the HBA, as partially directed by the SrbFlags,
+ // for the requested operation
+ // For a device I/O operation, such an internal routine generally selects the target device
+ // and sends the CDB over the bus to the target logical unit.
+ if (Srb->CdbLength > 0)
+ {
+ PCDB cdb = (PCDB)&Srb->Cdb;
+ if (cdb->CDB10.OperationCode == SCSIOP_INQUIRY)
+ {
+ StorPortDebugPrint(0, "\tINQUIRY Called!\n");
+ }
+ }
+ else
+ {
+ Srb->SrbStatus = SRB_STATUS_BAD_FUNCTION;
+ StorPortNotification(RequestComplete, adapterExtension, Srb);
+ return TRUE;
+ }
+ }
+
+ StorPortDebugPrint(0, "\tUnknow function code recieved: %x\n", function);
+ Srb->SrbStatus = SRB_STATUS_BAD_FUNCTION;
+ StorPortNotification(RequestComplete, adapterExtension, Srb);
return TRUE;
}// -- AhciHwStartIo();
ULONG portCount, portImplemented;
ULONG pci_cfg_len;
UCHAR pci_cfg_buf[0x30];
-
+
PAHCI_MEMORY_REGISTERS abar;
PPCI_COMMON_CONFIG pciConfigData;
PAHCI_ADAPTER_EXTENSION adapterExtension;
adapterExtension = (PAHCI_ADAPTER_EXTENSION)AdapterExtension;
adapterExtension->SlotNumber = ConfigInfo->SlotNumber;
adapterExtension->SystemIoBusNumber = ConfigInfo->SystemIoBusNumber;
-
+
// get PCI configuration header
pci_cfg_len = StorPortGetBusData(
adapterExtension,
// 3.1.2 -- AE bit is read-write only if CAP.SAM is '0'
ghc = StorPortReadRegisterUlong(adapterExtension, &abar->GHC);
// AE := Highest Significant bit of GHC
- if ((ghc & (0x1<<31)) == 1)//Hmm, controller was already in power state
+ if ((ghc & AHCI_Global_HBA_CONTROL_AE) == 1)//Hmm, controller was already in power state
{
// reset controller to have it in know state
StorPortDebugPrint(0, "\tAE Already set, Reset()\n");
}
}
- ghc = 0x1<<31;// only AE=1
+ ghc = AHCI_Global_HBA_CONTROL_AE;// only AE=1
StorPortWriteRegisterUlong(adapterExtension, &abar->GHC, ghc);
- adapterExtension->IS = abar->IS;
+ adapterExtension->IS = &abar->IS;
adapterExtension->PortImplemented = StorPortReadRegisterUlong(adapterExtension, &abar->PI);
if (adapterExtension->PortImplemented == 0){
ConfigInfo->MaximumNumberOfTargets = 1;
ConfigInfo->MaximumNumberOfLogicalUnits = 1;
ConfigInfo->ResetTargetSupported = TRUE;
- ConfigInfo->NumberOfBuses = 32;
+ ConfigInfo->NumberOfBuses = MAXIMUM_AHCI_PORT_COUNT;
ConfigInfo->SynchronizationModel = StorSynchronizeFullDuplex;
ConfigInfo->ScatterGather = TRUE;
// Turn IE -- Interrupt Enabled
- ghc |= 0x2;
+ ghc |= AHCI_Global_HBA_CONTROL_IE;
StorPortWriteRegisterUlong(adapterExtension, &abar->GHC, ghc);
-
+
// allocate necessary resource for each port
if (!AhciAllocateResourceForAdapter(adapterExtension, ConfigInfo)){
StorPortDebugPrint(0, "\tAhciAllocateResourceForAdapter() == FALSE\n");
return SP_RETURN_ERROR;
}
- for (index = 0; index < 32; index++)
+ for (index = 0; index < MAXIMUM_AHCI_PORT_COUNT; index++)
{
- if ((adapterExtension->PortImplemented & (1<<index)) != 0)
+ if ((adapterExtension->PortImplemented & (0x1<<index)) != 0)
AhciPortInitialize(&adapterExtension->PortExtension[index]);
}
HW_INITIALIZATION_DATA hwInitializationData;
ULONG i, status;
- StorPortDebugPrint(0, "Storahci Loaded 10023\n");
+ StorPortDebugPrint(0, "Storahci Loaded\n");
// initialize the hardware data structure
AhciZeroMemory((PCHAR)&hwInitializationData, sizeof(HW_INITIALIZATION_DATA));
// set required extension sizes
hwInitializationData.SrbExtensionSize = sizeof(AHCI_SRB_EXTENSION);
hwInitializationData.DeviceExtensionSize = sizeof(AHCI_ADAPTER_EXTENSION);
-
+
// register our hw init data
status = StorPortInitialize(
DriverObject,
RegistryPath,
&hwInitializationData,
NULL);
+
StorPortDebugPrint(0, "\tstatus:%x\n", status);
return status;
}// -- DriverEntry();
* software sets GHC.HR to ‘1’ and may poll until this bit is read to be ‘0’, at which point software knows that
* the HBA reset has completed.
* If the HBA has not cleared GHC.HR to ‘0’ within 1 second of software setting GHC.HR to ‘1’, the HBA is in
- * a hung or locked state.
+ * a hung or locked state.
*
* @param adapterExtension
*
*
* @param buffer
*/
+__inline
VOID AhciZeroMemory(
__in PCHAR buffer,
__in ULONG bufferSize
for (i = 0; i < bufferSize; i++)
buffer[i] = 0;
}// -- AhciZeroMemory();
+
+/**
+ * @name IsPortValid
+ * @implemented
+ *
+ * Tells wheather given port is implemented or not
+ *
+ * @param adapterExtension
+ * @param PathId
+ *
+ * @return
+ * return TRUE if bus was successfully reset
+ */
+__inline
+BOOLEAN IsPortValid(
+ __in PAHCI_ADAPTER_EXTENSION adapterExtension,
+ __in UCHAR pathId
+)
+{
+ if (pathId >= MAXIMUM_AHCI_PORT_COUNT)
+ return FALSE;
+ return adapterExtension->PortExtension[pathId].IsActive;
+}// -- IsPortValid()
* PURPOSE: To Implement AHCI Miniport driver targeting storport NT 5.2
* PROGRAMMERS: Aman Priyadarshi (aman.eureka@gmail.com)
*/
-
+
#include "miniport.h"
#include "storport.h"
#define AHCI_POOL_TAG 'ahci'
+#define MAXIMUM_AHCI_PORT_COUNT 12
+
+// 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)
+
+//////////////////////////////////////////////////////////////
+// ---- Support Structures --- //
+//////////////////////////////////////////////////////////////
typedef struct _AHCI_FIS_DMA_SETUP
{
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 Reserved3; //Reserved
} AHCI_FIS_DMA_SETUP;
typedef struct _AHCI_PIO_SETUP_FIS
USHORT TransferCount;
UCHAR Reserved5[2];
-
-} AHCI_PIO_SETUP_FIS;
+} AHCI_PIO_SETUP_FIS;
typedef struct _AHCI_D2H_REGISTER_FIS
{
- UCHAR FisType; // 0x34
+ UCHAR FisType;
UCHAR Reserved1 :6;
UCHAR I:1;
UCHAR Reserved2 :1;
UCHAR Reserved4[4];
} AHCI_D2H_REGISTER_FIS;
-typedef struct _AHCI_SET_DEVICE_BITS_FIS {
-
- UCHAR FisType; //0xA1
+typedef struct _AHCI_SET_DEVICE_BITS_FIS
+{
+ UCHAR FisType;
UCHAR PMPort: 4;
UCHAR Reserved1 :2;
UCHAR Error;
UCHAR Reserved5[4];
-} AHCI_SET_DEVICE_BITS_FIS;
+} AHCI_SET_DEVICE_BITS_FIS;
-// 4.2.2
+//////////////////////////////////////////////////////////////
+// --------------------------- //
+//////////////////////////////////////////////////////////////
+
+// 4.2.2 Command Header
typedef struct _AHCI_COMMAND_HEADER
{
ULONG HEADER_DESCRIPTION; // DW 0
// Received FIS
typedef struct _AHCI_RECEIVED_FIS
{
- AHCI_FIS_DMA_SETUP DmaSetupFIS; // 0x00 -- DMA Setup FIS
- ULONG pad0; // 4 BYTE padding
- AHCI_PIO_SETUP_FIS PioSetupFIS; // 0x20 -- PIO Setup FIS
- ULONG pad1[3]; // 12 BYTE padding
- AHCI_D2H_REGISTER_FIS RegisterFIS; // 0x40 -- Register – Device to Host FIS
- ULONG pad2; // 4 BYTE padding
- AHCI_SET_DEVICE_BITS_FIS SetDeviceFIS; // 0x58 -- Set Device Bit FIS
- ULONG UnknowFIS[16]; // 0x60 -- Unknown FIS
- ULONG Reserved[24]; // 0xA0 -- Reserved
+ 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
} AHCI_RECEIVED_FIS, *PAHCI_RECEIVED_FIS;
+// Holds Port Information
typedef struct _AHCI_PORT
{
- 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
+ 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
} AHCI_PORT, *PAHCI_PORT;
typedef struct _AHCI_MEMORY_REGISTERS
{
// 0x00 - 0x2B, Generic Host Control
- 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
-
- // 0x2C - 0x9F, Reserved
- ULONG Reserved[0xA0-0x2C];
-
- // 0xA0 - 0xFF, Vendor specific registers
- ULONG VendorSpecific[0x100-0xA0];
-
- AHCI_PORT PortList[32];//1~32
+ 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
+ ULONG Reserved[0xA0-0x2C]; // 0x2C - 0x9F, Reserved
+ ULONG VendorSpecific[0x100-0xA0]; // 0xA0 - 0xFF, Vendor specific registers
+ AHCI_PORT PortList[MAXIMUM_AHCI_PORT_COUNT];
} AHCI_MEMORY_REGISTERS, *PAHCI_MEMORY_REGISTERS;
-struct _AHCI_ADAPTER_EXTENSION;
-
+// Holds information for each attached attached port to a given adapter.
typedef struct _AHCI_PORT_EXTENSION
{
ULONG PortNumber;
- struct _AHCI_ADAPTER_EXTENSION* AdapterExtension;
- PAHCI_COMMAND_HEADER CommandList;
+ BOOLEAN IsActive;
+ PAHCI_PORT Port; // AHCI Port Infomation
PAHCI_RECEIVED_FIS ReceivedFIS;
- PAHCI_PORT Port;
+ PAHCI_COMMAND_HEADER CommandList;
+ STOR_DEVICE_POWER_STATE DevicePowerState; // Device Power State
+ struct _AHCI_ADAPTER_EXTENSION* AdapterExtension; // Port's Adapter Information
} AHCI_PORT_EXTENSION, *PAHCI_PORT_EXTENSION;
+// Holds Adapter Information
typedef struct _AHCI_ADAPTER_EXTENSION
{
- ULONG AdapterNumber;
ULONG SystemIoBusNumber;
ULONG SlotNumber;
ULONG AhciBaseAddress;
- ULONG IS; // Interrupt status
- ULONG PortImplemented;
+ PULONG IS;// Interrupt Status, In case of MSIM == `1`
+ ULONG PortImplemented;// bit-mapping of ports which are implemented
USHORT VendorID;
USHORT DeviceID;
ULONG CAP;
ULONG CAP2;
- PVOID NonCachedExtension;
+ PVOID NonCachedExtension;// holds virtual address to noncached buffer allocated for Port Extension
+
+ struct
+ {
+ // Message per port or shared port?
+ ULONG MessagePerPort : 1;
+ ULONG Removed : 1;
+ ULONG Reserved : 30; // not in use -- maintain 4 byte alignment
+ } StateFlags;
PAHCI_MEMORY_REGISTERS ABAR_Address;
- AHCI_PORT_EXTENSION PortExtension[32];
+ AHCI_PORT_EXTENSION PortExtension[MAXIMUM_AHCI_PORT_COUNT];
} AHCI_ADAPTER_EXTENSION, *PAHCI_ADAPTER_EXTENSION;
typedef struct _AHCI_SRB_EXTENSION