From d4c9e20b36049ad874c16a4e77c54085592cff17 Mon Sep 17 00:00:00 2001 From: Aman Priyadarshi Date: Tue, 7 Jun 2016 11:05:32 +0000 Subject: [PATCH 1/1] AHCI-SATA Interface almost ready. - tested on VM. - need to implement Interrupt Routine (MessagePerPort) and ATA/ATAPI Based SCSI Query. svn path=/branches/GSoC_2016/AHCI/; revision=71588 --- drivers/storage/storahci/sources | 1 + drivers/storage/storahci/storahci.c | 186 ++++++++++++++++++++++------ drivers/storage/storahci/storahci.h | 153 +++++++++++++---------- 3 files changed, 236 insertions(+), 104 deletions(-) diff --git a/drivers/storage/storahci/sources b/drivers/storage/storahci/sources index 9e0285ae80f..a586e71368b 100644 --- a/drivers/storage/storahci/sources +++ b/drivers/storage/storahci/sources @@ -1,6 +1,7 @@ TARGETNAME = storahci TARGETTYPE = MINIPORT +MSC_WARNING_LEVEL=/W4 TARGETLIBS=$(DDK_LIB_PATH)\storport.lib INCLUDES = %BUILD%\inc diff --git a/drivers/storage/storahci/storahci.c b/drivers/storage/storahci/storahci.c index 82601d92e76..c3d16c9741e 100644 --- a/drivers/storage/storahci/storahci.c +++ b/drivers/storage/storahci/storahci.c @@ -11,11 +11,18 @@ BOOLEAN AhciAdapterReset( __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 @@ -40,6 +47,7 @@ BOOLEAN AhciPortInitialize( adapterExtension = portExtension->AdapterExtension; abar = adapterExtension->ABAR_Address; + portExtension->Port = &abar->PortList[portExtension->PortNumber]; commandListPhysical = StorPortGetPhysicalAddress(adapterExtension, NULL, portExtension->CommandList, &mappedLength); @@ -61,6 +69,14 @@ BOOLEAN AhciPortInitialize( 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(); @@ -87,7 +103,7 @@ BOOLEAN AhciAllocateResourceForAdapter( 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; @@ -116,33 +132,16 @@ BOOLEAN AhciAllocateResourceForAdapter( 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<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); @@ -168,11 +167,26 @@ BOOLEAN AhciHwInitialize( __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(); @@ -199,7 +213,7 @@ BOOLEAN AhciHwInterrupt( adapterExtension = (PAHCI_ADAPTER_EXTENSION)AdapterExtension; - return TRUE; + return FALSE; }// -- AhciHwInterrupt(); /** @@ -221,14 +235,87 @@ BOOLEAN AhciHwStartIo( ) { - 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(); @@ -305,7 +392,7 @@ ULONG AhciHwFindAdapter( ULONG portCount, portImplemented; ULONG pci_cfg_len; UCHAR pci_cfg_buf[0x30]; - + PAHCI_MEMORY_REGISTERS abar; PPCI_COMMON_CONFIG pciConfigData; PAHCI_ADAPTER_EXTENSION adapterExtension; @@ -315,7 +402,7 @@ ULONG AhciHwFindAdapter( adapterExtension = (PAHCI_ADAPTER_EXTENSION)AdapterExtension; adapterExtension->SlotNumber = ConfigInfo->SlotNumber; adapterExtension->SystemIoBusNumber = ConfigInfo->SystemIoBusNumber; - + // get PCI configuration header pci_cfg_len = StorPortGetBusData( adapterExtension, @@ -374,7 +461,7 @@ ULONG AhciHwFindAdapter( // 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"); @@ -384,10 +471,10 @@ ULONG AhciHwFindAdapter( } } - 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){ @@ -400,23 +487,23 @@ ULONG AhciHwFindAdapter( 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<PortImplemented & (0x1<PortExtension[index]); } @@ -443,7 +530,7 @@ ULONG DriverEntry( 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)); @@ -471,13 +558,14 @@ ULONG DriverEntry( // 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(); @@ -494,7 +582,7 @@ ULONG 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 * @@ -538,6 +626,7 @@ BOOLEAN AhciAdapterReset( * * @param buffer */ +__inline VOID AhciZeroMemory( __in PCHAR buffer, __in ULONG bufferSize @@ -547,3 +636,26 @@ VOID AhciZeroMemory( 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() diff --git a/drivers/storage/storahci/storahci.h b/drivers/storage/storahci/storahci.h index cca53f936e2..22a47e7d527 100644 --- a/drivers/storage/storahci/storahci.h +++ b/drivers/storage/storahci/storahci.h @@ -4,11 +4,22 @@ * 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 { @@ -24,7 +35,7 @@ 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 @@ -54,12 +65,11 @@ 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; @@ -83,9 +93,9 @@ typedef struct _AHCI_D2H_REGISTER_FIS 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; @@ -100,9 +110,13 @@ typedef struct _AHCI_SET_DEVICE_BITS_FIS { 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 @@ -115,84 +129,81 @@ typedef struct _AHCI_COMMAND_HEADER // 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; @@ -202,10 +213,18 @@ typedef struct _AHCI_ADAPTER_EXTENSION 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 -- 2.17.1