[STORAHCI] Merge Storport Miniport driver by Aman Priyadarshi in GSoC.
authorAmine Khaldi <amine.khaldi@reactos.org>
Fri, 27 Jan 2017 10:11:30 +0000 (10:11 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Fri, 27 Jan 2017 10:11:30 +0000 (10:11 +0000)
svn path=/trunk/; revision=73604

1  2 
reactos/drivers/storage/CMakeLists.txt
reactos/drivers/storage/storahci/CMakeLists.txt
reactos/drivers/storage/storahci/Notes.txt
reactos/drivers/storage/storahci/makefile
reactos/drivers/storage/storahci/sources
reactos/drivers/storage/storahci/storahci.c
reactos/drivers/storage/storahci/storahci.h
reactos/drivers/storage/storahci/storahci.inf
reactos/drivers/storage/storahci/storahci.rc

index ff51e59,0000000..44cd868
mode 100644,000000..100644
--- /dev/null
@@@ -1,8 -1,0 +1,9 @@@
 +
 +add_subdirectory(class)
 +add_subdirectory(classpnp)
 +add_subdirectory(fdc)
 +add_subdirectory(floppy)
 +add_subdirectory(ide)
 +add_subdirectory(port)
 +add_subdirectory(scsiport)
++#add_subdirectory(storahci)
index 0000000,039ed8d..039ed8d
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,11 +1,11 @@@
+ add_definitions(-DDEBUG)
+ list(APPEND SOURCE
+     storahci.c)
+ add_library(storahci SHARED ${SOURCE} storahci.rc)
+ set_module_type(storahci kernelmodedriver)
+ add_importlibs(storahci storport ntoskrnl hal)
+ add_cd_file(TARGET storahci DESTINATION reactos/system32/drivers NO_CAB FOR all)
+ add_registry_inf(storahci.inf)
index 0000000,cac4353..cac4353
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,168 +1,168 @@@
+ AhciPortInitialize
+     Flags
+         IMPLEMENTED
+         FULLY_SUPPORTED
+         TESTED
+     Comment
+         NONE
+ AhciAllocateResourceForAdapter
+     Flags
+         IMPLEMENTED
+         FULLY_SUPPORTED
+         TESTED
+     Comment
+         NONE
+ AhciHwInitialize
+     Flags
+         IMPLEMENTED
+         FULLY_SUPPORTED
+         TESTED
+     Comment
+         NONE
+ AhciInterruptHandler
+     Flags
+         NOT_IMPLEMENTED
+         TESTED
+     Comment
+         Fatal Error not supported
+         Error Recovery not supported
+         Complete Request Routine
+ AhciHwInterrupt
+     Flags
+         IMPLEMENTED
+         FULLY_SUPPORTED
+         TESTED
+     Comment
+         NONE
+ AhciHwStartIo
+     Flags
+         IMPLEMENTED
+         TESTED
+     Comment
+         Adapter based IO request not supported
+         Need to implement more srb functions
+ AhciHwResetBus
+     Flags
+         NOT_IMPLEMENTED
+     Comment
+         Adapter master bus reset not implemented
+ AhciHwFindAdapter
+     Flags
+         IMPLEMENTED
+         FULLY_SUPPORTED
+         TESTED
+     Comment
+         NONE
+ DriverEntry
+     Flags
+         IMPLEMENTED
+         FULLY_SUPPORTED
+         TESTED
+     Comment
+         NONE
+ AhciATA_CFIS
+     Flags
+         IMPLEMENTED
+     Comment
+         Need to implement NCQ
+ AhciATAPI_CFIS
+     Flags
+         NOT_IMPLEMENTED
+     Comment
+         Need to configure command table according to Srb function
+ AhciBuild_PRDT
+     Flags
+         IMPLEMENTED
+     Comment
+         NONE
+ AhciProcessSrb
+     Flags
+         IMPLEMENTED
+     Comment
+         Only ATA/ATAPI type CFIS supported
+         Also I am not sure about FIS alignment in SrbExtension.
+ AhciActivatePort
+     Flags
+         IMPLEMENTED
+     Comment
+         NCQ not supported
+ AhciProcessIO
+     Flags
+         IMPLEMENTED
+         FULLY_SUPPORTED
+         TESTED
+     Comment
+         NONE
+ DeviceInquiryRequest
+     Flags
+         IMPLEMENTED
+         TESTED
+     Comment
+         EVPD is not sending Data buffer for IDENTIFY command.
+         Need to implement VPD
+ AhciAdapterReset
+     Flags
+         NOT_IMPLEMENTED
+     Comment
+         NONE
+ AhciZeroMemory
+     Flags
+         IMPLEMENTED
+         FULLY_SUPPORTED
+         TESTED
+     Comment
+         NONE
+ IsPortValid
+     Flags
+         IMPLEMENTED
+         FULLY_SUPPORTED
+         TESTED
+     Comment
+         NONE
+ AddQueue
+     Flags
+         IMPLEMENTED
+         FULLY_SUPPORTED
+         TESTED
+     Comment
+         NONE
+ RemoveQueue
+     Flags
+         IMPLEMENTED
+         FULLY_SUPPORTED
+         TESTED
+     Comment
+         NONE
+ AhciCompleteIssuedSrb
+     Flags
+         IMPLEMENTED
+         FULLY_SUPPORTED
+     Comment
+         NONE
+ InquiryCompletion
+     Flags
+         NOT_IMPLEMENTED
+     Comment
+         NONE
index 0000000,756c299..756c299
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,2 +1,2 @@@
+ MINIMUM_NT_TARGET_VERSION=0x502
+ !INCLUDE $(NTMAKEENV)\makefile.def
index 0000000,a1772ae..a1772ae
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,10 +1,10 @@@
+ TARGETNAME = storahci
+ TARGETTYPE = MINIPORT
+ MSC_WARNING_LEVEL=/W4
+ TARGETLIBS=$(DDK_LIB_PATH)\storport.lib
+ INCLUDES   = %BUILD%\inc
+ LIBS       = %BUILD%\lib
+ SOURCES    = storahci.c \
+                        storahci.rc
index 0000000,97138a6..97138a6
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,2570 +1,2570 @@@
+ /*
+  * 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)
+  */
+ #include "storahci.h"
+ /**
+  * @name AhciPortInitialize
+  * @implemented
+  *
+  * Initialize port by setting up PxCLB & PxFB Registers
+  *
+  * @param PortExtension
+  *
+  * @return
+  * Return true if intialization was successful
+  */
+ BOOLEAN
+ AhciPortInitialize (
+     __in PAHCI_PORT_EXTENSION PortExtension
+     )
+ {
+     AHCI_PORT_CMD cmd;
+     PAHCI_MEMORY_REGISTERS abar;
+     ULONG mappedLength, portNumber, ticks;
+     PAHCI_ADAPTER_EXTENSION adapterExtension;
+     STOR_PHYSICAL_ADDRESS commandListPhysical, receivedFISPhysical;
+     AhciDebugPrint("AhciPortInitialize()\n");
+     adapterExtension = PortExtension->AdapterExtension;
+     abar = adapterExtension->ABAR_Address;
+     portNumber = PortExtension->PortNumber;
+     NT_ASSERT(abar != NULL);
+     NT_ASSERT(portNumber < adapterExtension->PortCount);
+     PortExtension->Port = &abar->PortList[portNumber];
+     commandListPhysical = StorPortGetPhysicalAddress(adapterExtension,
+                                                      NULL,
+                                                      PortExtension->CommandList,
+                                                      &mappedLength);
+     if ((mappedLength == 0) || ((commandListPhysical.LowPart % 1024) != 0))
+     {
+         AhciDebugPrint("\tcommandListPhysical mappedLength:%d\n", mappedLength);
+         return FALSE;
+     }
+     receivedFISPhysical = StorPortGetPhysicalAddress(adapterExtension,
+                                                      NULL,
+                                                      PortExtension->ReceivedFIS,
+                                                      &mappedLength);
+     if ((mappedLength == 0) || ((receivedFISPhysical.LowPart % 256) != 0))
+     {
+         AhciDebugPrint("\treceivedFISPhysical mappedLength:%d\n", mappedLength);
+         return FALSE;
+     }
+     // Ensure that the controller is not in the running state by reading and examining each
+     // implemented port’s PxCMD register. If PxCMD.ST, PxCMD.CR, PxCMD.FRE and
+     // PxCMD.FR are all cleared, the port is in an idle state. Otherwise, the port is not idle and
+     // should be placed in the idle state prior to manipulating HBA and port specific registers.
+     // System software places a port into the idle state by clearing PxCMD.ST and waiting for
+     // PxCMD.CR to return ‘0’ when read. Software should wait at least 500 milliseconds for
+     // this to occur. If PxCMD.FRE is set to ‘1’, software should clear it to ‘0’ and wait at least
+     // 500 milliseconds for PxCMD.FR to return ‘0’ when read. If PxCMD.CR or PxCMD.FR do
+     // not clear to ‘0’ correctly, then software may attempt a port reset or a full HBA reset to recove
+     // TODO: Check if port is in idle state or not, if not then restart port
+     cmd.Status = StorPortReadRegisterUlong(adapterExtension, &PortExtension->Port->CMD);
+     if ((cmd.FR != 0) || (cmd.CR != 0) || (cmd.FRE != 0) || (cmd.ST != 0))
+     {
+         cmd.ST = 0;
+         cmd.FRE = 0;
+         ticks = 3;
+         do
+         {
+             StorPortStallExecution(50000);
+             cmd.Status = StorPortReadRegisterUlong(adapterExtension, &PortExtension->Port->CMD);
+             if (ticks == 0)
+             {
+                 AhciDebugPrint("\tAttempt to reset port failed: %x\n", cmd);
+                 return FALSE;
+             }
+             ticks--;
+         }
+         while(cmd.CR != 0 || cmd.FR != 0);
+     }
+     // 10.1.2 For each implemented port, system software shall allocate memory for and program:
+     //  PxCLB and PxCLBU (if CAP.S64A is set to ‘1’)
+     //  PxFB and PxFBU (if CAP.S64A is set to ‘1’)
+     // Note: Assuming 32bit support only
+     StorPortWriteRegisterUlong(adapterExtension, &PortExtension->Port->CLB, commandListPhysical.LowPart);
+     if (IsAdapterCAPS64(adapterExtension->CAP))
+     {
+         StorPortWriteRegisterUlong(adapterExtension, &PortExtension->Port->CLBU, commandListPhysical.HighPart);
+     }
+     StorPortWriteRegisterUlong(adapterExtension, &PortExtension->Port->FB, receivedFISPhysical.LowPart);
+     if (IsAdapterCAPS64(adapterExtension->CAP))
+     {
+         StorPortWriteRegisterUlong(adapterExtension, &PortExtension->Port->FBU, receivedFISPhysical.HighPart);
+     }
+     PortExtension->IdentifyDeviceDataPhysicalAddress = StorPortGetPhysicalAddress(adapterExtension,
+                                                                                   NULL,
+                                                                                   PortExtension->IdentifyDeviceData,
+                                                                                   &mappedLength);
+     // set device power state flag to D0
+     PortExtension->DevicePowerState = StorPowerDeviceD0;
+     // clear pending interrupts
+     StorPortWriteRegisterUlong(adapterExtension, &PortExtension->Port->SERR, (ULONG)~0);
+     StorPortWriteRegisterUlong(adapterExtension, &PortExtension->Port->IS, (ULONG)~0);
+     StorPortWriteRegisterUlong(adapterExtension, adapterExtension->IS, (1 << PortExtension->PortNumber));
+     return TRUE;
+ }// -- AhciPortInitialize();
+ /**
+  * @name AhciAllocateResourceForAdapter
+  * @implemented
+  *
+  * Allocate memory from poll for required pointers
+  *
+  * @param AdapterExtension
+  * @param ConfigInfo
+  *
+  * @return
+  * return TRUE if allocation was successful
+  */
+ BOOLEAN
+ AhciAllocateResourceForAdapter (
+     __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
+     __in PPORT_CONFIGURATION_INFORMATION ConfigInfo
+     )
+ {
+     PCHAR nonCachedExtension, tmp;
+     ULONG index, NCS, AlignedNCS;
+     ULONG portCount, portImplemented, nonCachedExtensionSize;
+     PAHCI_PORT_EXTENSION PortExtension;
+     AhciDebugPrint("AhciAllocateResourceForAdapter()\n");
+     NCS = AHCI_Global_Port_CAP_NCS(AdapterExtension->CAP);
+     AlignedNCS = ROUND_UP(NCS, 8);
+     // get port count -- Number of set bits in `AdapterExtension->PortImplemented`
+     portCount = 0;
+     portImplemented = AdapterExtension->PortImplemented;
+     NT_ASSERT(portImplemented != 0);
+     for (index = MAXIMUM_AHCI_PORT_COUNT - 1; index > 0; index--)
+         if ((portImplemented & (1 << index)) != 0)
+             break;
+     portCount = index + 1;
+     AhciDebugPrint("\tPort Count: %d\n", portCount);
+     AdapterExtension->PortCount = portCount;
+     nonCachedExtensionSize =    sizeof(AHCI_COMMAND_HEADER) * AlignedNCS + //should be 1K aligned
+                                 sizeof(AHCI_RECEIVED_FIS) +
+                                 sizeof(IDENTIFY_DEVICE_DATA);
+     // align nonCachedExtensionSize to 1024
+     nonCachedExtensionSize = ROUND_UP(nonCachedExtensionSize, 1024);
+     AdapterExtension->NonCachedExtension = StorPortGetUncachedExtension(AdapterExtension,
+                                                                         ConfigInfo,
+                                                                         nonCachedExtensionSize * portCount);
+     if (AdapterExtension->NonCachedExtension == NULL)
+     {
+         AhciDebugPrint("\tadapterExtension->NonCachedExtension == NULL\n");
+         return FALSE;
+     }
+     nonCachedExtension = AdapterExtension->NonCachedExtension;
+     AhciZeroMemory(nonCachedExtension, nonCachedExtensionSize * portCount);
+     for (index = 0; index < portCount; index++)
+     {
+         PortExtension = &AdapterExtension->PortExtension[index];
+         PortExtension->DeviceParams.IsActive = FALSE;
+         if ((AdapterExtension->PortImplemented & (1 << index)) != 0)
+         {
+             PortExtension->PortNumber = index;
+             PortExtension->DeviceParams.IsActive = TRUE;
+             PortExtension->AdapterExtension = AdapterExtension;
+             PortExtension->CommandList = (PAHCI_COMMAND_HEADER)nonCachedExtension;
+             tmp = (PCHAR)(nonCachedExtension + sizeof(AHCI_COMMAND_HEADER) * AlignedNCS);
+             PortExtension->ReceivedFIS = (PAHCI_RECEIVED_FIS)tmp;
+             PortExtension->IdentifyDeviceData = (PIDENTIFY_DEVICE_DATA)(tmp + sizeof(AHCI_RECEIVED_FIS));
+             PortExtension->MaxPortQueueDepth = NCS;
+             nonCachedExtension += nonCachedExtensionSize;
+         }
+     }
+     return TRUE;
+ }// -- AhciAllocateResourceForAdapter();
+ /**
+  * @name AhciStartPort
+  * @implemented
+  *
+  * Try to start the port device
+  *
+  * @param AdapterExtension
+  * @param PortExtension
+  *
+  */
+ BOOLEAN
+ AhciStartPort (
+     __in PAHCI_PORT_EXTENSION PortExtension
+     )
+ {
+     ULONG index;
+     AHCI_PORT_CMD cmd;
+     AHCI_TASK_FILE_DATA tfd;
+     AHCI_INTERRUPT_ENABLE ie;
+     AHCI_SERIAL_ATA_STATUS ssts;
+     AHCI_SERIAL_ATA_CONTROL sctl;
+     PAHCI_ADAPTER_EXTENSION AdapterExtension;
+     AhciDebugPrint("AhciStartPort()\n");
+     AdapterExtension = PortExtension->AdapterExtension;
+     cmd.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->CMD);
+     if ((cmd.FR == 1) && (cmd.CR == 1) && (cmd.FRE == 1) && (cmd.ST == 1))
+     {
+         // Already Running
+         return TRUE;
+     }
+     cmd.SUD = 1;
+     StorPortWriteRegisterUlong(AdapterExtension, &PortExtension->Port->CMD, cmd.Status);
+     if (((cmd.FR == 1) && (cmd.FRE == 0)) ||
+         ((cmd.CR == 1) && (cmd.ST == 0)))
+     {
+         AhciDebugPrint("\tCOMRESET\n");
+         // perform COMRESET
+         // section 10.4.2
+         // Software causes a port reset (COMRESET) by writing 1h to the PxSCTL.DET field to invoke a
+         // COMRESET on the interface and start a re-establishment of Phy layer communications. Software shall
+         // wait at least 1 millisecond before clearing PxSCTL.DET to 0h; this ensures that at least one COMRESET
+         // signal is sent over the interface. After clearing PxSCTL.DET to 0h, software should wait for
+         // communication to be re-established as indicated by PxSSTS.DET being set to 3h. Then software should
+         // write all 1s to the PxSERR register to clear any bits that were set as part of the port reset.
+         sctl.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->SCTL);
+         sctl.DET = 1;
+         StorPortWriteRegisterUlong(AdapterExtension, &PortExtension->Port->SCTL, sctl.Status);
+         StorPortStallExecution(1000);
+         sctl.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->SCTL);
+         sctl.DET = 0;
+         StorPortWriteRegisterUlong(AdapterExtension, &PortExtension->Port->SCTL, sctl.Status);
+         // Poll DET to verify if a device is attached to the port
+         index = 0;
+         do
+         {
+             StorPortStallExecution(1000);
+             ssts.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->SSTS);
+             index++;
+             if (ssts.DET != 0)
+             {
+                 break;
+             }
+         }
+         while(index < 30);
+     }
+     ssts.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->SSTS);
+     switch (ssts.DET)
+     {
+         case 0x3:
+             {
+                 NT_ASSERT(cmd.ST == 0);
+                 // make sure FIS Recieve is enabled (cmd.FRE)
+                 index = 0;
+                 do
+                 {
+                     StorPortStallExecution(10000);
+                     cmd.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->CMD);
+                     cmd.FRE = 1;
+                     StorPortWriteRegisterUlong(AdapterExtension, &PortExtension->Port->CMD, cmd.Status);
+                     index++;
+                 }
+                 while((cmd.FR != 1) && (index < 3));
+                 if (cmd.FR != 1)
+                 {
+                     // failed to start FIS DMA engine
+                     // it can crash the driver later
+                     // so better to turn this port off
+                     return FALSE;
+                 }
+                 // start port channel
+                 // set cmd.ST
+                 NT_ASSERT(cmd.FRE == 1);
+                 NT_ASSERT(cmd.CR == 0);
+                 // why assert? well If we face such condition on DET = 0x3
+                 // then we don't have port in idle state and hence before executing this part of code
+                 // we must have restarted it.
+                 tfd.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->TFD);
+                 if ((tfd.STS.BSY) || (tfd.STS.DRQ))
+                 {
+                     AhciDebugPrint("\tUnhandled Case BSY-DRQ\n");
+                 }
+                 // clear pending interrupts
+                 StorPortWriteRegisterUlong(AdapterExtension, &PortExtension->Port->SERR, (ULONG)~0);
+                 StorPortWriteRegisterUlong(AdapterExtension, &PortExtension->Port->IS, (ULONG)~0);
+                 StorPortWriteRegisterUlong(AdapterExtension, AdapterExtension->IS, (1 << PortExtension->PortNumber));
+                 // set IE
+                 ie.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->IE);
+                 /* Device to Host Register FIS Interrupt Enable */
+                 ie.DHRE = 1;
+                 /* PIO Setup FIS Interrupt Enable */
+                 ie.PSE = 1;
+                 /* DMA Setup FIS Interrupt Enable  */
+                 ie.DSE = 1;
+                 /* Set Device Bits FIS Interrupt Enable */
+                 ie.SDBE = 1;
+                 /* Unknown FIS Interrupt Enable */
+                 ie.UFE = 0;
+                 /* Descriptor Processed Interrupt Enable */
+                 ie.DPE = 0;
+                 /* Port Change Interrupt Enable */
+                 ie.PCE = 1;
+                 /* Device Mechanical Presence Enable */
+                 ie.DMPE = 0;
+                 /* PhyRdy Change Interrupt Enable */
+                 ie.PRCE = 1;
+                 /* Incorrect Port Multiplier Enable */
+                 ie.IPME = 0;
+                 /* Overflow Enable */
+                 ie.OFE = 1;
+                 /* Interface Non-fatal Error Enable */
+                 ie.INFE = 1;
+                 /* Interface Fatal Error Enable */
+                 ie.IFE = 1;
+                 /* Host Bus Data Error Enable */
+                 ie.HBDE = 1;
+                 /* Host Bus Fatal Error Enable */
+                 ie.HBFE = 1;
+                 /* Task File Error Enable */
+                 ie.TFEE = 1;
+                 cmd.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->CMD);
+                 /* Cold Presence Detect Enable */
+                 if (cmd.CPD) // does it support CPD?
+                 {
+                     // disable it for now
+                     ie.CPDE = 0;
+                 }
+                 // should I replace this to single line?
+                 // by directly setting ie.Status?
+                 StorPortWriteRegisterUlong(AdapterExtension, &PortExtension->Port->IE, ie.Status);
+                 cmd.ST = 1;
+                 StorPortWriteRegisterUlong(AdapterExtension, &PortExtension->Port->CMD, cmd.Status);
+                 cmd.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->CMD);
+                 if (cmd.ST != 1)
+                 {
+                     AhciDebugPrint("\tFailed to start Port\n");
+                     return FALSE;
+                 }
+                 return TRUE;
+             }
+         default:
+             // unhandled case
+             AhciDebugPrint("\tDET == %x Unsupported\n", ssts.DET);
+             return FALSE;
+     }
+ }// -- AhciStartPort();
+ /**
+  * @name AhciCommandCompletionDpcRoutine
+  * @implemented
+  *
+  * Handles Completed Commands
+  *
+  * @param Dpc
+  * @param AdapterExtension
+  * @param SystemArgument1
+  * @param SystemArgument2
+  */
+ VOID
+ AhciCommandCompletionDpcRoutine (
+     __in PSTOR_DPC Dpc,
+     __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
+     __in PAHCI_PORT_EXTENSION PortExtension,
+     __in PVOID SystemArgument2
+   )
+ {
+     PSCSI_REQUEST_BLOCK Srb;
+     PAHCI_SRB_EXTENSION SrbExtension;
+     STOR_LOCK_HANDLE lockhandle = {0};
+     PAHCI_COMPLETION_ROUTINE CompletionRoutine;
+     UNREFERENCED_PARAMETER(Dpc);
+     UNREFERENCED_PARAMETER(SystemArgument2);
+     AhciDebugPrint("AhciCommandCompletionDpcRoutine()\n");
+     StorPortAcquireSpinLock(AdapterExtension, InterruptLock, NULL, &lockhandle);
+     Srb = RemoveQueue(&PortExtension->CompletionQueue);
+     StorPortReleaseSpinLock(AdapterExtension, &lockhandle);
+     NT_ASSERT(Srb != NULL);
+     if (Srb->SrbStatus == SRB_STATUS_PENDING)
+     {
+         Srb->SrbStatus = SRB_STATUS_SUCCESS;
+     }
+     else
+     {
+         return;
+     }
+     SrbExtension = GetSrbExtension(Srb);
+     CompletionRoutine = SrbExtension->CompletionRoutine;
+     NT_ASSERT(CompletionRoutine != NULL);
+     // now it's completion routine responsibility to set SrbStatus
+     CompletionRoutine(PortExtension, Srb);
+     StorPortNotification(RequestComplete, AdapterExtension, Srb);
+     return;
+ }// -- AhciCommandCompletionDpcRoutine();
+ /**
+  * @name AhciHwPassiveInitialize
+  * @implemented
+  *
+  * initializes the HBA and finds all devices that are of interest to the miniport driver. (at PASSIVE LEVEL)
+  *
+  * @param adapterExtension
+  *
+  * @return
+  * return TRUE if intialization was successful
+  */
+ BOOLEAN
+ AhciHwPassiveInitialize (
+     __in PAHCI_ADAPTER_EXTENSION AdapterExtension
+     )
+ {
+     ULONG index;
+     PAHCI_PORT_EXTENSION PortExtension;
+     AhciDebugPrint("AhciHwPassiveInitialize()\n");
+     for (index = 0; index < AdapterExtension->PortCount; index++)
+     {
+         if ((AdapterExtension->PortImplemented & (0x1 << index)) != 0)
+         {
+             PortExtension = &AdapterExtension->PortExtension[index];
+             PortExtension->DeviceParams.IsActive = AhciStartPort(PortExtension);
+             StorPortInitializeDpc(AdapterExtension, &PortExtension->CommandCompletion, AhciCommandCompletionDpcRoutine);
+         }
+     }
+     return TRUE;
+ }// -- AhciHwPassiveInitialize();
+ /**
+  * @name AhciHwInitialize
+  * @implemented
+  *
+  * initializes the HBA and finds all devices that are of interest to the miniport driver.
+  *
+  * @param adapterExtension
+  *
+  * @return
+  * return TRUE if intialization was successful
+  */
+ BOOLEAN
+ AhciHwInitialize (
+     __in PAHCI_ADAPTER_EXTENSION AdapterExtension
+     )
+ {
+     AHCI_GHC ghc;
+     AhciDebugPrint("AhciHwInitialize()\n");
+     AdapterExtension->StateFlags.MessagePerPort = FALSE;
+     // First check what type of interrupt/synchronization device is using
+     ghc.Status = 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.MRSM == 0)
+     {
+         AdapterExtension->StateFlags.MessagePerPort = TRUE;
+         AhciDebugPrint("\tMultiple MSI based message not supported\n");
+     }
+     StorPortEnablePassiveInitialization(AdapterExtension, AhciHwPassiveInitialize);
+     return TRUE;
+ }// -- AhciHwInitialize();
+ /**
+  * @name AhciCompleteIssuedSrb
+  * @implemented
+  *
+  * Complete issued Srbs
+  *
+  * @param PortExtension
+  *
+  */
+ VOID
+ AhciCompleteIssuedSrb (
+     __in PAHCI_PORT_EXTENSION PortExtension,
+     __in ULONG CommandsToComplete
+     )
+ {
+     ULONG NCS, i;
+     PSCSI_REQUEST_BLOCK Srb;
+     PAHCI_SRB_EXTENSION SrbExtension;
+     PAHCI_ADAPTER_EXTENSION AdapterExtension;
+     AhciDebugPrint("AhciCompleteIssuedSrb()\n");
+     NT_ASSERT(CommandsToComplete != 0);
+     AhciDebugPrint("\tCompleted Commands: %d\n", CommandsToComplete);
+     AdapterExtension = PortExtension->AdapterExtension;
+     NCS = AHCI_Global_Port_CAP_NCS(AdapterExtension->CAP);
+     for (i = 0; i < NCS; i++)
+     {
+         if (((1 << i) & CommandsToComplete) != 0)
+         {
+             Srb = PortExtension->Slot[i];
+             if (Srb == NULL)
+             {
+                 continue;
+             }
+             SrbExtension = GetSrbExtension(Srb);
+             NT_ASSERT(SrbExtension != NULL);
+             if (SrbExtension->CompletionRoutine != NULL)
+             {
+                 AddQueue(&PortExtension->CompletionQueue, Srb);
+                 StorPortIssueDpc(AdapterExtension, &PortExtension->CommandCompletion, PortExtension, Srb);
+             }
+             else
+             {
+                 NT_ASSERT(Srb->SrbStatus == SRB_STATUS_PENDING);
+                 Srb->SrbStatus = SRB_STATUS_SUCCESS;
+                 StorPortNotification(RequestComplete, AdapterExtension, Srb);
+             }
+         }
+     }
+     return;
+ }// -- AhciCompleteIssuedSrb();
+ /**
+  * @name AhciInterruptHandler
+  * @not_implemented
+  *
+  * Interrupt Handler for PortExtension
+  *
+  * @param PortExtension
+  *
+  */
+ VOID
+ AhciInterruptHandler (
+     __in PAHCI_PORT_EXTENSION PortExtension
+     )
+ {
+     ULONG is, ci, sact, outstanding;
+     AHCI_INTERRUPT_STATUS PxIS;
+     AHCI_INTERRUPT_STATUS PxISMasked;
+     PAHCI_ADAPTER_EXTENSION AdapterExtension;
+     AhciDebugPrint("AhciInterruptHandler()\n");
+     AhciDebugPrint("\tPort Number: %d\n", PortExtension->PortNumber);
+     AdapterExtension = PortExtension->AdapterExtension;
+     NT_ASSERT(IsPortValid(AdapterExtension, PortExtension->PortNumber));
+     // 5.5.3
+     // 1. Software determines the cause of the interrupt by reading the PxIS register.
+     //    It is possible for multiple bits to be set
+     // 2. Software clears appropriate bits in the PxIS register corresponding to the cause of the interrupt.
+     // 3. Software clears the interrupt bit in IS.IPS corresponding to the port.
+     // 4. If executing non-queued commands, software reads the PxCI register, and compares the current value to
+     //    the list of commands previously issued by software that are still outstanding.
+     //    If executing native queued commands, software reads the PxSACT register and compares the current
+     //    value to the list of commands previously issued by software.
+     //    Software completes with success any outstanding command whose corresponding bit has been cleared in
+     //    the respective register. PxCI and PxSACT are volatile registers; software should only use their values
+     //    to determine commands that have completed, not to determine which commands have previously been issued.
+     // 5. If there were errors, noted in the PxIS register, software performs error recovery actions (see section 6.2.2).
+     PxISMasked.Status = 0;
+     PxIS.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->IS);
+     // 6.2.2
+     // Fatal Error
+     // signified by the setting of PxIS.HBFS, PxIS.HBDS, PxIS.IFS, or PxIS.TFES
+     if (PxIS.HBFS || PxIS.HBDS || PxIS.IFS || PxIS.TFES)
+     {
+         // In this state, the HBA shall not issue any new commands nor acknowledge DMA Setup FISes to process
+         // any native command queuing commands. To recover, the port must be restarted
+         // To detect an error that requires software recovery actions to be performed,
+         // software should check whether any of the following status bits are set on an interrupt:
+         // PxIS.HBFS, PxIS.HBDS, PxIS.IFS, and PxIS.TFES.  If any of these bits are set,
+         // software should perform the appropriate error recovery actions based on whether
+         // non-queued commands were being issued or native command queuing commands were being issued.
+         AhciDebugPrint("\tFatal Error: %x\n", PxIS.Status);
+     }
+     // Normal Command Completion
+     // 3.3.5
+     // A D2H Register FIS has been received with the ‘I’ bit set, and has been copied into system memory.
+     PxISMasked.DHRS = PxIS.DHRS;
+     // A PIO Setup FIS has been received with the ‘I’ bit set, it has been copied into system memory.
+     PxISMasked.PSS = PxIS.PSS;
+     // A DMA Setup FIS has been received with the ‘I’ bit set and has been copied into system memory.
+     PxISMasked.DSS = PxIS.DSS;
+     // A Set Device Bits FIS has been received with the ‘I’ bit set and has been copied into system memory/
+     PxISMasked.SDBS = PxIS.SDBS;
+     // A PRD with the ‘I’ bit set has transferred all of its data.
+     PxISMasked.DPS = PxIS.DPS;
+     if (PxISMasked.Status != 0)
+     {
+         StorPortWriteRegisterUlong(AdapterExtension, &PortExtension->Port->IS, PxISMasked.Status);
+     }
+     // 10.7.1.1
+     // Clear port interrupt
+     // It is set by the level of the virtual interrupt line being a set, and cleared by a write of ‘1’ from the software.
+     is = (1 << PortExtension->PortNumber);
+     StorPortWriteRegisterUlong(AdapterExtension, AdapterExtension->IS, is);
+     ci = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->CI);
+     sact = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->SACT);
+     outstanding = ci | sact; // NOTE: Including both non-NCQ and NCQ based commands
+     if ((PortExtension->CommandIssuedSlots & (~outstanding)) != 0)
+     {
+         AhciCompleteIssuedSrb(PortExtension, (PortExtension->CommandIssuedSlots & (~outstanding)));
+         PortExtension->CommandIssuedSlots &= outstanding;
+     }
+     return;
+ }// -- AhciInterruptHandler();
+ /**
+  * @name AhciHwInterrupt
+  * @implemented
+  *
+  * The Storport driver calls the HwStorInterrupt routine after the HBA generates an interrupt request.
+  *
+  * @param AdapterExtension
+  *
+  * @return
+  * return TRUE Indicates that an interrupt was pending on adapter.
+  * return FALSE Indicates the interrupt was not ours.
+  */
+ BOOLEAN
+ AhciHwInterrupt (
+     __in PAHCI_ADAPTER_EXTENSION AdapterExtension
+     )
+ {
+     ULONG portPending, nextPort, i, portCount;
+     if (AdapterExtension->StateFlags.Removed)
+     {
+         return FALSE;
+     }
+     portPending = StorPortReadRegisterUlong(AdapterExtension, AdapterExtension->IS);
+     // we process interrupt for implemented ports only
+     portCount = AdapterExtension->PortCount;
+     portPending = portPending & AdapterExtension->PortImplemented;
+     if (portPending == 0)
+     {
+         return FALSE;
+     }
+     for (i = 1; i <= portCount; i++)
+     {
+         nextPort = (AdapterExtension->LastInterruptPort + i) % portCount;
+         if ((portPending & (0x1 << nextPort)) == 0)
+             continue;
+         NT_ASSERT(IsPortValid(AdapterExtension, nextPort));
+         if (AdapterExtension->PortExtension[nextPort].DeviceParams.IsActive == FALSE)
+         {
+             continue;
+         }
+         // we can assign this interrupt to this port
+         AdapterExtension->LastInterruptPort = nextPort;
+         AhciInterruptHandler(&AdapterExtension->PortExtension[nextPort]);
+         portPending &= ~(1 << nextPort);
+         // interrupt belongs to this device
+         // should always return TRUE
+         return TRUE;
+     }
+     AhciDebugPrint("\tSomething went wrong");
+     return FALSE;
+ }// -- AhciHwInterrupt();
+ /**
+  * @name AhciHwStartIo
+  * @not_implemented
+  *
+  * The Storport driver calls the HwStorStartIo routine one time for each incoming I/O request.
+  *
+  * @param adapterExtension
+  * @param Srb
+  *
+  * @return
+  * return TRUE if the request was accepted
+  * return FALSE if the request must be submitted later
+  */
+ BOOLEAN
+ AhciHwStartIo (
+     __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
+     __in PSCSI_REQUEST_BLOCK Srb
+     )
+ {
+     AhciDebugPrint("AhciHwStartIo()\n");
+     if (!IsPortValid(AdapterExtension, Srb->PathId))
+     {
+         Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
+         StorPortNotification(RequestComplete, AdapterExtension, Srb);
+         return TRUE;
+     }
+     switch(Srb->Function)
+     {
+         case SRB_FUNCTION_PNP:
+             {
+                 // 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.
+                 PSCSI_PNP_REQUEST_BLOCK pnpRequest;
+                 pnpRequest = (PSCSI_PNP_REQUEST_BLOCK)Srb;
+                 if ((pnpRequest->SrbPnPFlags & SRB_PNP_FLAGS_ADAPTER_REQUEST) != 0)
+                 {
+                     switch(pnpRequest->PnPAction)
+                     {
+                         case StorRemoveDevice:
+                         case StorSurpriseRemoval:
+                             {
+                                 Srb->SrbStatus = SRB_STATUS_SUCCESS;
+                                 AdapterExtension->StateFlags.Removed = 1;
+                                 AhciDebugPrint("\tAdapter removed\n");
+                             }
+                             break;
+                         case StorStopDevice:
+                             {
+                                 Srb->SrbStatus = SRB_STATUS_SUCCESS;
+                                 AhciDebugPrint("\tRequested to Stop the adapter\n");
+                             }
+                             break;
+                         default:
+                             Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
+                             break;
+                     }
+                 }
+                 else
+                 {
+                     Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
+                 }
+             }
+             break;
+         case 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.
+                 PCDB cdb = (PCDB)&Srb->Cdb;
+                 if (Srb->CdbLength == 0)
+                 {
+                     AhciDebugPrint("\tOperationCode: %d\n", cdb->CDB10.OperationCode);
+                     Srb->SrbStatus = SRB_STATUS_BAD_FUNCTION;
+                     break;
+                 }
+                 NT_ASSERT(cdb != NULL);
+                 switch(cdb->CDB10.OperationCode)
+                 {
+                     case SCSIOP_INQUIRY:
+                         Srb->SrbStatus = DeviceInquiryRequest(AdapterExtension, Srb, cdb);
+                         break;
+                     case SCSIOP_REPORT_LUNS:
+                         Srb->SrbStatus = DeviceReportLuns(AdapterExtension, Srb, cdb);
+                         break;
+                     case SCSIOP_READ_CAPACITY:
+                         Srb->SrbStatus = DeviceRequestCapacity(AdapterExtension, Srb, cdb);
+                         break;
+                     case SCSIOP_TEST_UNIT_READY:
+                         Srb->SrbStatus = DeviceRequestComplete(AdapterExtension, Srb, cdb);
+                         break;
+                     case SCSIOP_MODE_SENSE:
+                         Srb->SrbStatus = DeviceRequestSense(AdapterExtension, Srb, cdb);
+                         break;
+                     case SCSIOP_READ:
+                     case SCSIOP_WRITE:
+                         Srb->SrbStatus = DeviceRequestReadWrite(AdapterExtension, Srb, cdb);
+                         break;
+                     default:
+                         AhciDebugPrint("\tOperationCode: %d\n", cdb->CDB10.OperationCode);
+                         Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
+                         break;
+                 }
+             }
+             break;
+         default:
+             AhciDebugPrint("\tUnknown function code recieved: %x\n", Srb->Function);
+             Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
+             break;
+     }
+     if (Srb->SrbStatus != SRB_STATUS_PENDING)
+     {
+         StorPortNotification(RequestComplete, AdapterExtension, Srb);
+     }
+     else
+     {
+         AhciProcessIO(AdapterExtension, Srb->PathId, Srb);
+     }
+     return TRUE;
+ }// -- AhciHwStartIo();
+ /**
+  * @name AhciHwResetBus
+  * @not_implemented
+  *
+  * The HwStorResetBus routine is called by the port driver to clear error conditions.
+  *
+  * @param adapterExtension
+  * @param PathId
+  *
+  * @return
+  * return TRUE if bus was successfully reset
+  */
+ BOOLEAN
+ AhciHwResetBus (
+     __in PVOID AdapterExtension,
+     __in ULONG PathId
+     )
+ {
+     STOR_LOCK_HANDLE lockhandle = {0};
+     PAHCI_ADAPTER_EXTENSION adapterExtension;
+     AhciDebugPrint("AhciHwResetBus()\n");
+     adapterExtension = AdapterExtension;
+     if (IsPortValid(AdapterExtension, PathId))
+     {
+         // Acquire Lock
+         StorPortAcquireSpinLock(AdapterExtension, InterruptLock, NULL, &lockhandle);
+         // TODO: Perform port reset
+         // Release lock
+         StorPortReleaseSpinLock(AdapterExtension, &lockhandle);
+     }
+     return FALSE;
+ }// -- AhciHwResetBus();
+ /**
+  * @name AhciHwFindAdapter
+  * @implemented
+  *
+  * The HwStorFindAdapter routine uses the supplied configuration to determine whether a specific
+  * HBA is supported and, if it is, to return configuration information about that adapter.
+  *
+  *  10.1 Platform Communication
+  *  http://www.intel.in/content/dam/www/public/us/en/documents/technical-specifications/serial-ata-ahci-spec-rev1_2.pdf
+  * @param DeviceExtension
+  * @param HwContext
+  * @param BusInformation
+  * @param ArgumentString
+  * @param ConfigInfo
+  * @param Reserved3
+  *
+  * @return
+  *      SP_RETURN_FOUND
+  *          Indicates that a supported HBA was found and that the HBA-relevant configuration information was successfully determined and set in the PORT_CONFIGURATION_INFORMATION structure.
+  *
+  *      SP_RETURN_ERROR
+  *          Indicates that an HBA was found but there was an error obtaining the configuration information. If possible, such an error should be logged with StorPortLogError.
+  *
+  *      SP_RETURN_BAD_CONFIG
+  *          Indicates that the supplied configuration information was invalid for the adapter.
+  *
+  *      SP_RETURN_NOT_FOUND
+  *          Indicates that no supported HBA was found for the supplied configuration information.
+  *
+  * @remarks Called by Storport.
+  */
+ ULONG
+ AhciHwFindAdapter (
+     __in PVOID AdapterExtension,
+     __in PVOID HwContext,
+     __in PVOID BusInformation,
+     __in PVOID ArgumentString,
+     __inout PPORT_CONFIGURATION_INFORMATION ConfigInfo,
+     __in PBOOLEAN Reserved3
+     )
+ {
+     AHCI_GHC ghc;
+     ULONG index, pci_cfg_len;
+     PACCESS_RANGE accessRange;
+     UCHAR pci_cfg_buf[sizeof(PCI_COMMON_CONFIG)];
+     PAHCI_MEMORY_REGISTERS abar;
+     PPCI_COMMON_CONFIG pciConfigData;
+     PAHCI_ADAPTER_EXTENSION adapterExtension;
+     AhciDebugPrint("AhciHwFindAdapter()\n");
+     UNREFERENCED_PARAMETER(HwContext);
+     UNREFERENCED_PARAMETER(BusInformation);
+     UNREFERENCED_PARAMETER(ArgumentString);
+     UNREFERENCED_PARAMETER(Reserved3);
+     adapterExtension = AdapterExtension;
+     adapterExtension->SlotNumber = ConfigInfo->SlotNumber;
+     adapterExtension->SystemIoBusNumber = ConfigInfo->SystemIoBusNumber;
+     // get PCI configuration header
+     pci_cfg_len = StorPortGetBusData(
+                         adapterExtension,
+                         PCIConfiguration,
+                         adapterExtension->SystemIoBusNumber,
+                         adapterExtension->SlotNumber,
+                         pci_cfg_buf,
+                         sizeof(PCI_COMMON_CONFIG));
+     if (pci_cfg_len != sizeof(PCI_COMMON_CONFIG))
+     {
+         AhciDebugPrint("\tpci_cfg_len != %d :: %d", sizeof(PCI_COMMON_CONFIG), pci_cfg_len);
+         return SP_RETURN_ERROR;//Not a valid device at the given bus number
+     }
+     pciConfigData = (PPCI_COMMON_CONFIG)pci_cfg_buf;
+     adapterExtension->VendorID = pciConfigData->VendorID;
+     adapterExtension->DeviceID = pciConfigData->DeviceID;
+     adapterExtension->RevisionID = pciConfigData->RevisionID;
+     // The last PCI base address register (BAR[5], header offset 0x24) points to the AHCI base memory, it’s called ABAR (AHCI Base Memory Register).
+     adapterExtension->AhciBaseAddress = pciConfigData->u.type0.BaseAddresses[5] & (0xFFFFFFF0);
+     AhciDebugPrint("\tVendorID:%d  DeviceID:%d  RevisionID:%d\n", adapterExtension->VendorID,
+                                                               adapterExtension->DeviceID,
+                                                               adapterExtension->RevisionID);
+     // 2.1.11
+     abar = NULL;
+     if (ConfigInfo->NumberOfAccessRanges > 0)
+     {
+         accessRange = *(ConfigInfo->AccessRanges);
+         for (index = 0; index < ConfigInfo->NumberOfAccessRanges; index++)
+         {
+             if (accessRange[index].RangeStart.QuadPart == adapterExtension->AhciBaseAddress)
+             {
+                 abar = StorPortGetDeviceBase(adapterExtension,
+                                              ConfigInfo->AdapterInterfaceType,
+                                              ConfigInfo->SystemIoBusNumber,
+                                              accessRange[index].RangeStart,
+                                              accessRange[index].RangeLength,
+                                              !accessRange[index].RangeInMemory);
+                 break;
+             }
+         }
+     }
+     if (abar == NULL)
+     {
+         AhciDebugPrint("\tabar == NULL\n");
+         return SP_RETURN_ERROR; // corrupted information supplied
+     }
+     adapterExtension->ABAR_Address = abar;
+     adapterExtension->CAP = StorPortReadRegisterUlong(adapterExtension, &abar->CAP);
+     adapterExtension->CAP2 = StorPortReadRegisterUlong(adapterExtension, &abar->CAP2);
+     adapterExtension->Version = StorPortReadRegisterUlong(adapterExtension, &abar->VS);
+     adapterExtension->LastInterruptPort = (ULONG)-1;
+     // 10.1.2
+     // 1. Indicate that system software is AHCI aware by setting GHC.AE to ‘1’.
+     // 3.1.2 -- AE bit is read-write only if CAP.SAM is '0'
+     ghc.Status = StorPortReadRegisterUlong(adapterExtension, &abar->GHC);
+     // AE := Highest Significant bit of GHC
+     if (ghc.AE != 0)// Hmm, controller was already in power state
+     {
+         // reset controller to have it in known state
+         AhciDebugPrint("\tAE Already set, Reset()\n");
+         if (!AhciAdapterReset(adapterExtension))
+         {
+             AhciDebugPrint("\tReset Failed!\n");
+             return SP_RETURN_ERROR;// reset failed
+         }
+     }
+     ghc.Status = 0;
+     ghc.AE = 1;// only AE=1
+     // tell the controller that we know about AHCI
+     StorPortWriteRegisterUlong(adapterExtension, &abar->GHC, ghc.Status);
+     adapterExtension->IS = &abar->IS;
+     adapterExtension->PortImplemented = StorPortReadRegisterUlong(adapterExtension, &abar->PI);
+     if (adapterExtension->PortImplemented == 0)
+     {
+         AhciDebugPrint("\tadapterExtension->PortImplemented == 0\n");
+         return SP_RETURN_ERROR;
+     }
+     ConfigInfo->Master = TRUE;
+     ConfigInfo->AlignmentMask = 0x3;
+     ConfigInfo->ScatterGather = TRUE;
+     ConfigInfo->DmaWidth = Width32Bits;
+     ConfigInfo->WmiDataProvider = FALSE;
+     ConfigInfo->Dma32BitAddresses = TRUE;
+     if (IsAdapterCAPS64(adapterExtension->CAP))
+     {
+         ConfigInfo->Dma64BitAddresses = TRUE;
+     }
+     ConfigInfo->MaximumNumberOfTargets = 1;
+     ConfigInfo->ResetTargetSupported = TRUE;
+     ConfigInfo->NumberOfPhysicalBreaks = 0x21;
+     ConfigInfo->MaximumNumberOfLogicalUnits = 1;
+     ConfigInfo->NumberOfBuses = MAXIMUM_AHCI_PORT_COUNT;
+     ConfigInfo->MaximumTransferLength = MAXIMUM_TRANSFER_LENGTH;
+     ConfigInfo->SynchronizationModel = StorSynchronizeFullDuplex;
+     // Turn IE -- Interrupt Enabled
+     ghc.Status = StorPortReadRegisterUlong(adapterExtension, &abar->GHC);
+     ghc.IE = 1;
+     StorPortWriteRegisterUlong(adapterExtension, &abar->GHC, ghc.Status);
+     // allocate necessary resource for each port
+     if (!AhciAllocateResourceForAdapter(adapterExtension, ConfigInfo))
+     {
+         NT_ASSERT(FALSE);
+         return SP_RETURN_ERROR;
+     }
+     for (index = 0; index < adapterExtension->PortCount; index++)
+     {
+         if ((adapterExtension->PortImplemented & (0x1 << index)) != 0)
+             AhciPortInitialize(&adapterExtension->PortExtension[index]);
+     }
+     return SP_RETURN_FOUND;
+ }// -- AhciHwFindAdapter();
+ /**
+  * @name DriverEntry
+  * @implemented
+  *
+  * Initial Entrypoint for storahci miniport driver
+  *
+  * @param DriverObject
+  * @param RegistryPath
+  *
+  * @return
+  * NT_STATUS in case of driver loaded successfully.
+  */
+ ULONG
+ DriverEntry (
+     __in PVOID DriverObject,
+     __in PVOID RegistryPath
+     )
+ {
+     ULONG status;
+     // initialize the hardware data structure
+     HW_INITIALIZATION_DATA hwInitializationData = {0};
+     // set size of hardware initialization structure
+     hwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
+     // identity required miniport entry point routines
+     hwInitializationData.HwStartIo = AhciHwStartIo;
+     hwInitializationData.HwResetBus = AhciHwResetBus;
+     hwInitializationData.HwInterrupt = AhciHwInterrupt;
+     hwInitializationData.HwInitialize = AhciHwInitialize;
+     hwInitializationData.HwFindAdapter = AhciHwFindAdapter;
+     // adapter specific information
+     hwInitializationData.TaggedQueuing = TRUE;
+     hwInitializationData.AutoRequestSense = TRUE;
+     hwInitializationData.MultipleRequestPerLu = TRUE;
+     hwInitializationData.NeedPhysicalAddresses = TRUE;
+     hwInitializationData.NumberOfAccessRanges = 6;
+     hwInitializationData.AdapterInterfaceType = PCIBus;
+     hwInitializationData.MapBuffers = STOR_MAP_NON_READ_WRITE_BUFFERS;
+     // 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);
+     NT_ASSERT(status == STATUS_SUCCESS);
+     return status;
+ }// -- DriverEntry();
+ /**
+  * @name AhciATA_CFIS
+  * @implemented
+  *
+  * create ATA CFIS from Srb
+  *
+  * @param PortExtension
+  * @param Srb
+  *
+  * @return
+  * Number of CFIS fields used in DWORD
+  */
+ ULONG
+ AhciATA_CFIS (
+     __in PAHCI_PORT_EXTENSION PortExtension,
+     __in PAHCI_SRB_EXTENSION SrbExtension
+     )
+ {
+     PAHCI_COMMAND_TABLE cmdTable;
+     UNREFERENCED_PARAMETER(PortExtension);
+     AhciDebugPrint("AhciATA_CFIS()\n");
+     cmdTable = (PAHCI_COMMAND_TABLE)SrbExtension;
+     AhciZeroMemory((PCHAR)cmdTable->CFIS, sizeof(cmdTable->CFIS));
+     cmdTable->CFIS[AHCI_ATA_CFIS_FisType] = FIS_TYPE_REG_H2D;       // FIS Type
+     cmdTable->CFIS[AHCI_ATA_CFIS_PMPort_C] = (1 << 7);              // PM Port & C
+     cmdTable->CFIS[AHCI_ATA_CFIS_CommandReg] = SrbExtension->CommandReg;
+     cmdTable->CFIS[AHCI_ATA_CFIS_FeaturesLow] = SrbExtension->FeaturesLow;
+     cmdTable->CFIS[AHCI_ATA_CFIS_LBA0] = SrbExtension->LBA0;
+     cmdTable->CFIS[AHCI_ATA_CFIS_LBA1] = SrbExtension->LBA1;
+     cmdTable->CFIS[AHCI_ATA_CFIS_LBA2] = SrbExtension->LBA2;
+     cmdTable->CFIS[AHCI_ATA_CFIS_Device] = SrbExtension->Device;
+     cmdTable->CFIS[AHCI_ATA_CFIS_LBA3] = SrbExtension->LBA3;
+     cmdTable->CFIS[AHCI_ATA_CFIS_LBA4] = SrbExtension->LBA4;
+     cmdTable->CFIS[AHCI_ATA_CFIS_LBA5] = SrbExtension->LBA5;
+     cmdTable->CFIS[AHCI_ATA_CFIS_FeaturesHigh] = SrbExtension->FeaturesHigh;
+     cmdTable->CFIS[AHCI_ATA_CFIS_SectorCountLow] = SrbExtension->SectorCountLow;
+     cmdTable->CFIS[AHCI_ATA_CFIS_SectorCountHigh] = SrbExtension->SectorCountHigh;
+     return 5;
+ }// -- AhciATA_CFIS();
+ /**
+  * @name AhciATAPI_CFIS
+  * @not_implemented
+  *
+  * create ATAPI CFIS from Srb
+  *
+  * @param PortExtension
+  * @param Srb
+  *
+  * @return
+  * Number of CFIS fields used in DWORD
+  */
+ ULONG
+ AhciATAPI_CFIS (
+     __in PAHCI_PORT_EXTENSION PortExtension,
+     __in PAHCI_SRB_EXTENSION SrbExtension
+     )
+ {
+     PAHCI_COMMAND_TABLE cmdTable;
+     UNREFERENCED_PARAMETER(PortExtension);
+     AhciDebugPrint("AhciATAPI_CFIS()\n");
+     cmdTable = (PAHCI_COMMAND_TABLE)SrbExtension;
+     NT_ASSERT(SrbExtension->CommandReg == IDE_COMMAND_ATAPI_PACKET);
+     AhciZeroMemory((PCHAR)cmdTable->CFIS, sizeof(cmdTable->CFIS));
+     cmdTable->CFIS[AHCI_ATA_CFIS_FisType] = FIS_TYPE_REG_H2D;       // FIS Type
+     cmdTable->CFIS[AHCI_ATA_CFIS_PMPort_C] = (1 << 7);              // PM Port & C
+     cmdTable->CFIS[AHCI_ATA_CFIS_CommandReg] = SrbExtension->CommandReg;
+     cmdTable->CFIS[AHCI_ATA_CFIS_FeaturesLow] = SrbExtension->FeaturesLow;
+     cmdTable->CFIS[AHCI_ATA_CFIS_LBA0] = SrbExtension->LBA0;
+     cmdTable->CFIS[AHCI_ATA_CFIS_LBA1] = SrbExtension->LBA1;
+     cmdTable->CFIS[AHCI_ATA_CFIS_LBA2] = SrbExtension->LBA2;
+     cmdTable->CFIS[AHCI_ATA_CFIS_Device] = SrbExtension->Device;
+     cmdTable->CFIS[AHCI_ATA_CFIS_LBA3] = SrbExtension->LBA3;
+     cmdTable->CFIS[AHCI_ATA_CFIS_LBA4] = SrbExtension->LBA4;
+     cmdTable->CFIS[AHCI_ATA_CFIS_LBA5] = SrbExtension->LBA5;
+     cmdTable->CFIS[AHCI_ATA_CFIS_FeaturesHigh] = SrbExtension->FeaturesHigh;
+     cmdTable->CFIS[AHCI_ATA_CFIS_SectorCountLow] = SrbExtension->SectorCountLow;
+     cmdTable->CFIS[AHCI_ATA_CFIS_SectorCountHigh] = SrbExtension->SectorCountHigh;
+     return 5;
+ }// -- AhciATAPI_CFIS();
+ /**
+  * @name AhciBuild_PRDT
+  * @implemented
+  *
+  * Build PRDT for data transfer
+  *
+  * @param PortExtension
+  * @param Srb
+  *
+  * @return
+  * Return number of entries in PRDT.
+  */
+ ULONG
+ AhciBuild_PRDT (
+     __in PAHCI_PORT_EXTENSION PortExtension,
+     __in PAHCI_SRB_EXTENSION SrbExtension
+     )
+ {
+     ULONG index;
+     PAHCI_COMMAND_TABLE cmdTable;
+     PLOCAL_SCATTER_GATHER_LIST sgl;
+     PAHCI_ADAPTER_EXTENSION AdapterExtension;
+     AhciDebugPrint("AhciBuild_PRDT()\n");
+     sgl = SrbExtension->pSgl;
+     cmdTable = (PAHCI_COMMAND_TABLE)SrbExtension;
+     AdapterExtension = PortExtension->AdapterExtension;
+     NT_ASSERT(sgl != NULL);
+     NT_ASSERT(sgl->NumberOfElements < MAXIMUM_AHCI_PRDT_ENTRIES);
+     for (index = 0; index < sgl->NumberOfElements; index++)
+     {
+         NT_ASSERT(sgl->List[index].Length <= MAXIMUM_TRANSFER_LENGTH);
+         cmdTable->PRDT[index].DBA = sgl->List[index].PhysicalAddress.LowPart;
+         if (IsAdapterCAPS64(AdapterExtension->CAP))
+         {
+             cmdTable->PRDT[index].DBAU = sgl->List[index].PhysicalAddress.HighPart;
+         }
+         // Data Byte Count (DBC): A ‘0’ based value that Indicates the length, in bytes, of the data block.
+         // A maximum of length of 4MB may exist for any entry. Bit ‘0’ of this field must always be ‘1’ to
+         // indicate an even byte count. A value of ‘1’ indicates 2 bytes, ‘3’ indicates 4 bytes, etc.
+         cmdTable->PRDT[index].DBC = sgl->List[index].Length - 1;
+     }
+     return sgl->NumberOfElements;
+ }// -- AhciBuild_PRDT();
+ /**
+  * @name AhciProcessSrb
+  * @implemented
+  *
+  * Prepare Srb for IO processing
+  *
+  * @param PortExtension
+  * @param Srb
+  * @param SlotIndex
+  *
+  */
+ VOID
+ AhciProcessSrb (
+     __in PAHCI_PORT_EXTENSION PortExtension,
+     __in PSCSI_REQUEST_BLOCK Srb,
+     __in ULONG SlotIndex
+     )
+ {
+     ULONG prdtlen, sig, length, cfl;
+     PAHCI_SRB_EXTENSION SrbExtension;
+     PAHCI_COMMAND_HEADER CommandHeader;
+     PAHCI_ADAPTER_EXTENSION AdapterExtension;
+     STOR_PHYSICAL_ADDRESS CommandTablePhysicalAddress;
+     AhciDebugPrint("AhciProcessSrb()\n");
+     NT_ASSERT(Srb->PathId == PortExtension->PortNumber);
+     SrbExtension = GetSrbExtension(Srb);
+     AdapterExtension = PortExtension->AdapterExtension;
+     NT_ASSERT(SrbExtension != NULL);
+     NT_ASSERT(SrbExtension->AtaFunction != 0);
+     if ((SrbExtension->AtaFunction == ATA_FUNCTION_ATA_IDENTIFY) &&
+         (SrbExtension->CommandReg == IDE_COMMAND_NOT_VALID))
+     {
+         // Here we are safe to check SIG register
+         sig = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->SIG);
+         if (sig == 0x101)
+         {
+             AhciDebugPrint("\tATA Device Found!\n");
+             SrbExtension->CommandReg = IDE_COMMAND_IDENTIFY;
+         }
+         else
+         {
+             AhciDebugPrint("\tATAPI Device Found!\n");
+             SrbExtension->CommandReg = IDE_COMMAND_ATAPI_IDENTIFY;
+         }
+     }
+     NT_ASSERT(SlotIndex < AHCI_Global_Port_CAP_NCS(AdapterExtension->CAP));
+     SrbExtension->SlotIndex = SlotIndex;
+     // program the CFIS in the CommandTable
+     CommandHeader = &PortExtension->CommandList[SlotIndex];
+     cfl = 0;
+     if (IsAtapiCommand(SrbExtension->AtaFunction))
+     {
+         cfl = AhciATAPI_CFIS(PortExtension, SrbExtension);
+     }
+     else if (IsAtaCommand(SrbExtension->AtaFunction))
+     {
+         cfl = AhciATA_CFIS(PortExtension, SrbExtension);
+     }
+     else
+     {
+         NT_ASSERT(FALSE);
+     }
+     prdtlen = 0;
+     if (IsDataTransferNeeded(SrbExtension))
+     {
+         prdtlen = AhciBuild_PRDT(PortExtension, SrbExtension);
+         NT_ASSERT(prdtlen != -1);
+     }
+     // Program the command header
+     CommandHeader->DI.PRDTL = prdtlen; // number of entries in PRD table
+     CommandHeader->DI.CFL = cfl;
+     CommandHeader->DI.A = (SrbExtension->AtaFunction & ATA_FUNCTION_ATAPI_COMMAND) ? 1 : 0;
+     CommandHeader->DI.W = (SrbExtension->Flags & ATA_FLAGS_DATA_OUT) ? 1 : 0;
+     CommandHeader->DI.P = 0;    // ATA Specifications says so
+     CommandHeader->DI.PMP = 0;  // Port Multiplier
+     // Reset -- Manual Configuation
+     CommandHeader->DI.R = 0;
+     CommandHeader->DI.B = 0;
+     CommandHeader->DI.C = 0;
+     CommandHeader->PRDBC = 0;
+     CommandHeader->Reserved[0] = 0;
+     CommandHeader->Reserved[1] = 0;
+     CommandHeader->Reserved[2] = 0;
+     CommandHeader->Reserved[3] = 0;
+     // set CommandHeader CTBA
+     CommandTablePhysicalAddress = StorPortGetPhysicalAddress(AdapterExtension,
+                                                              NULL,
+                                                              SrbExtension,
+                                                              &length);
+     NT_ASSERT(length != 0);
+     // command table alignment
+     NT_ASSERT((CommandTablePhysicalAddress.LowPart % 128) == 0);
+     CommandHeader->CTBA = CommandTablePhysicalAddress.LowPart;
+     if (IsAdapterCAPS64(AdapterExtension->CAP))
+     {
+         CommandHeader->CTBA_U = CommandTablePhysicalAddress.HighPart;
+     }
+     // mark this slot
+     PortExtension->Slot[SlotIndex] = Srb;
+     PortExtension->QueueSlots |= 1 << SlotIndex;
+     return;
+ }// -- AhciProcessSrb();
+ /**
+  * @name AhciActivatePort
+  * @implemented
+  *
+  * Program Port and populate command list
+  *
+  * @param PortExtension
+  *
+  */
+ VOID
+ AhciActivatePort (
+     __in PAHCI_PORT_EXTENSION PortExtension
+     )
+ {
+     AHCI_PORT_CMD cmd;
+     ULONG QueueSlots, slotToActivate, tmp;
+     PAHCI_ADAPTER_EXTENSION AdapterExtension;
+     AhciDebugPrint("AhciActivatePort()\n");
+     AdapterExtension = PortExtension->AdapterExtension;
+     QueueSlots = PortExtension->QueueSlots;
+     if (QueueSlots == 0)
+     {
+         return;
+     }
+     // section 3.3.14
+     // Bits in this field shall only be set to ‘1’ by software when PxCMD.ST is set to ‘1’
+     cmd.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->CMD);
+     if (cmd.ST == 0) // PxCMD.ST == 0
+     {
+         return;
+     }
+     // get the lowest set bit
+     tmp = QueueSlots & (QueueSlots - 1);
+     if (tmp == 0)
+         slotToActivate = QueueSlots;
+     else
+         slotToActivate = (QueueSlots & (~tmp));
+     // mark that bit off in QueueSlots
+     // so we can know we it is really needed to activate port or not
+     PortExtension->QueueSlots &= ~slotToActivate;
+     // mark this CommandIssuedSlots
+     // to validate in completeIssuedCommand
+     PortExtension->CommandIssuedSlots |= slotToActivate;
+     // tell the HBA to issue this Command Slot to the given port
+     StorPortWriteRegisterUlong(AdapterExtension, &PortExtension->Port->CI, slotToActivate);
+     return;
+ }// -- AhciActivatePort();
+ /**
+  * @name AhciProcessIO
+  * @implemented
+  *
+  * Acquire Exclusive lock to port, populate pending commands to command List
+  * program controller's port to process new commands in command list.
+  *
+  * @param AdapterExtension
+  * @param PathId
+  * @param Srb
+  *
+  */
+ VOID
+ AhciProcessIO (
+     __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
+     __in UCHAR PathId,
+     __in PSCSI_REQUEST_BLOCK Srb
+     )
+ {
+     PSCSI_REQUEST_BLOCK tmpSrb;
+     STOR_LOCK_HANDLE lockhandle = {0};
+     PAHCI_PORT_EXTENSION PortExtension;
+     ULONG commandSlotMask, occupiedSlots, slotIndex, NCS;
+     AhciDebugPrint("AhciProcessIO()\n");
+     AhciDebugPrint("\tPathId: %d\n", PathId);
+     PortExtension = &AdapterExtension->PortExtension[PathId];
+     NT_ASSERT(PathId < AdapterExtension->PortCount);
+     // Acquire Lock
+     StorPortAcquireSpinLock(AdapterExtension, InterruptLock, NULL, &lockhandle);
+     // add Srb to queue
+     AddQueue(&PortExtension->SrbQueue, Srb);
+     if (PortExtension->DeviceParams.IsActive == FALSE)
+     {
+         // Release Lock
+         StorPortReleaseSpinLock(AdapterExtension, &lockhandle);
+         return; // we should wait for device to get active
+     }
+     occupiedSlots = (PortExtension->QueueSlots | PortExtension->CommandIssuedSlots); // Busy command slots for given port
+     NCS = AHCI_Global_Port_CAP_NCS(AdapterExtension->CAP);
+     commandSlotMask = (1 << NCS) - 1; // available slots mask
+     commandSlotMask = (commandSlotMask & ~occupiedSlots);
+     if(commandSlotMask != 0)
+     {
+         // iterate over HBA port slots
+         for (slotIndex = 0; slotIndex < NCS; slotIndex++)
+         {
+             // find first free slot
+             if ((commandSlotMask & (1 << slotIndex)) != 0)
+             {
+                 tmpSrb = RemoveQueue(&PortExtension->SrbQueue);
+                 if (tmpSrb != NULL)
+                 {
+                     NT_ASSERT(tmpSrb->PathId == PathId);
+                     AhciProcessSrb(PortExtension, tmpSrb, slotIndex);
+                 }
+                 else
+                 {
+                     break;
+                 }
+             }
+             else
+             {
+                 break;
+             }
+         }
+     }
+     // program HBA port
+     AhciActivatePort(PortExtension);
+     // Release Lock
+     StorPortReleaseSpinLock(AdapterExtension, &lockhandle);
+     return;
+ }// -- AhciProcessIO();
+ /**
+  * @name AtapiInquiryCompletion
+  * @implemented
+  *
+  * AtapiInquiryCompletion routine should be called after device signals
+  * for device inquiry request is completed (through interrupt) -- ATAPI Device only
+  *
+  * @param PortExtension
+  * @param Srb
+  *
+  */
+ VOID
+ AtapiInquiryCompletion (
+     __in PAHCI_PORT_EXTENSION PortExtension,
+     __in PSCSI_REQUEST_BLOCK Srb
+     )
+ {
+     BOOLEAN status;
+     PAHCI_ADAPTER_EXTENSION AdapterExtension;
+     AhciDebugPrint("AtapiInquiryCompletion()\n");
+     NT_ASSERT(Srb != NULL);
+     NT_ASSERT(PortExtension != NULL);
+     AdapterExtension = PortExtension->AdapterExtension;
+     // send queue depth
+     status = StorPortSetDeviceQueueDepth(PortExtension->AdapterExtension,
+                                          Srb->PathId,
+                                          Srb->TargetId,
+                                          Srb->Lun,
+                                          AHCI_Global_Port_CAP_NCS(AdapterExtension->CAP));
+     NT_ASSERT(status == TRUE);
+     return;
+ }// -- AtapiInquiryCompletion();
+ /**
+  * @name InquiryCompletion
+  * @implemented
+  *
+  * InquiryCompletion routine should be called after device signals
+  * for device inquiry request is completed (through interrupt)
+  *
+  * @param PortExtension
+  * @param Srb
+  *
+  */
+ VOID
+ InquiryCompletion (
+     __in PAHCI_PORT_EXTENSION PortExtension,
+     __in PSCSI_REQUEST_BLOCK Srb
+     )
+ {
+     PCDB cdb;
+     BOOLEAN status;
+     PINQUIRYDATA InquiryData;
+     PAHCI_SRB_EXTENSION SrbExtension;
+     PAHCI_ADAPTER_EXTENSION AdapterExtension;
+     PIDENTIFY_DEVICE_DATA IdentifyDeviceData;
+     AhciDebugPrint("InquiryCompletion()\n");
+     NT_ASSERT(Srb != NULL);
+     NT_ASSERT(PortExtension != NULL);
+     cdb = (PCDB)&Srb->Cdb;
+     InquiryData = Srb->DataBuffer;
+     SrbExtension = GetSrbExtension(Srb);
+     AdapterExtension = PortExtension->AdapterExtension;
+     IdentifyDeviceData = PortExtension->IdentifyDeviceData;
+     if (Srb->SrbStatus != SRB_STATUS_SUCCESS)
+     {
+         if (Srb->SrbStatus == SRB_STATUS_NO_DEVICE)
+         {
+             PortExtension->DeviceParams.DeviceType = AHCI_DEVICE_TYPE_NODEVICE;
+         }
+         return;
+     }
+     NT_ASSERT(InquiryData != NULL);
+     NT_ASSERT(Srb->SrbStatus == SRB_STATUS_SUCCESS);
+     // Device specific data
+     PortExtension->DeviceParams.MaxLba.QuadPart = 0;
+     if (SrbExtension->CommandReg == IDE_COMMAND_IDENTIFY)
+     {
+         PortExtension->DeviceParams.DeviceType = AHCI_DEVICE_TYPE_ATA;
+         if (IdentifyDeviceData->GeneralConfiguration.RemovableMedia)
+         {
+             PortExtension->DeviceParams.RemovableDevice = 1;
+         }
+         if ((IdentifyDeviceData->CommandSetSupport.BigLba) && (IdentifyDeviceData->CommandSetActive.BigLba))
+         {
+             PortExtension->DeviceParams.Lba48BitMode = 1;
+         }
+         PortExtension->DeviceParams.AccessType = DIRECT_ACCESS_DEVICE;
+         /* Device max address lba */
+         if (PortExtension->DeviceParams.Lba48BitMode)
+         {
+             PortExtension->DeviceParams.MaxLba.LowPart = IdentifyDeviceData->Max48BitLBA[0];
+             PortExtension->DeviceParams.MaxLba.HighPart = IdentifyDeviceData->Max48BitLBA[1];
+         }
+         else
+         {
+             PortExtension->DeviceParams.MaxLba.LowPart = IdentifyDeviceData->UserAddressableSectors;
+         }
+         /* Bytes Per Logical Sector */
+         if (IdentifyDeviceData->PhysicalLogicalSectorSize.LogicalSectorLongerThan256Words)
+         {
+             AhciDebugPrint("\tBytesPerLogicalSector != DEVICE_ATA_BLOCK_SIZE\n");
+             NT_ASSERT(FALSE);
+         }
+         PortExtension->DeviceParams.BytesPerLogicalSector = DEVICE_ATA_BLOCK_SIZE;
+         /* Bytes Per Physical Sector */
+         if (IdentifyDeviceData->PhysicalLogicalSectorSize.MultipleLogicalSectorsPerPhysicalSector)
+         {
+             AhciDebugPrint("\tBytesPerPhysicalSector != DEVICE_ATA_BLOCK_SIZE\n");
+             NT_ASSERT(FALSE);
+         }
+         PortExtension->DeviceParams.BytesPerPhysicalSector = DEVICE_ATA_BLOCK_SIZE;
+         // last byte should be NULL
+         StorPortCopyMemory(PortExtension->DeviceParams.VendorId, IdentifyDeviceData->ModelNumber, sizeof(PortExtension->DeviceParams.VendorId) - 1);
+         StorPortCopyMemory(PortExtension->DeviceParams.RevisionID, IdentifyDeviceData->FirmwareRevision, sizeof(PortExtension->DeviceParams.RevisionID) - 1);
+         StorPortCopyMemory(PortExtension->DeviceParams.SerialNumber, IdentifyDeviceData->SerialNumber, sizeof(PortExtension->DeviceParams.SerialNumber) - 1);
+         PortExtension->DeviceParams.VendorId[sizeof(PortExtension->DeviceParams.VendorId) - 1] = '\0';
+         PortExtension->DeviceParams.RevisionID[sizeof(PortExtension->DeviceParams.RevisionID) - 1] = '\0';
+         PortExtension->DeviceParams.SerialNumber[sizeof(PortExtension->DeviceParams.SerialNumber) - 1] = '\0';
+         // TODO: Add other device params
+         AhciDebugPrint("\tATA Device\n");
+     }
+     else
+     {
+         AhciDebugPrint("\tATAPI Device\n");
+         PortExtension->DeviceParams.DeviceType = AHCI_DEVICE_TYPE_ATAPI;
+         PortExtension->DeviceParams.AccessType = READ_ONLY_DIRECT_ACCESS_DEVICE;
+     }
+     // INQUIRYDATABUFFERSIZE = 36 ; Defined in storport.h
+     if (Srb->DataTransferLength < INQUIRYDATABUFFERSIZE)
+     {
+         AhciDebugPrint("\tDataBufferLength < sizeof(INQUIRYDATA), Could crash the driver.\n");
+         NT_ASSERT(FALSE);
+     }
+     // update data transfer length
+     Srb->DataTransferLength = INQUIRYDATABUFFERSIZE;
+     // prepare data to send
+     InquiryData->Versions = 2;
+     InquiryData->Wide32Bit = 1;
+     InquiryData->CommandQueue = 0; // NCQ not supported
+     InquiryData->ResponseDataFormat = 0x2;
+     InquiryData->DeviceTypeModifier = 0;
+     InquiryData->DeviceTypeQualifier = DEVICE_CONNECTED;
+     InquiryData->AdditionalLength = INQUIRYDATABUFFERSIZE - 5;
+     InquiryData->DeviceType = PortExtension->DeviceParams.AccessType;
+     InquiryData->RemovableMedia = PortExtension->DeviceParams.RemovableDevice;
+     // Fill VendorID, Product Revision Level and other string fields
+     StorPortCopyMemory(InquiryData->VendorId, PortExtension->DeviceParams.VendorId, sizeof(InquiryData->VendorId) - 1);
+     StorPortCopyMemory(InquiryData->ProductId, PortExtension->DeviceParams.RevisionID, sizeof(PortExtension->DeviceParams.RevisionID));
+     StorPortCopyMemory(InquiryData->ProductRevisionLevel, PortExtension->DeviceParams.SerialNumber, sizeof(InquiryData->ProductRevisionLevel) - 1);
+     InquiryData->VendorId[sizeof(InquiryData->VendorId) - 1] = '\0';
+     InquiryData->ProductId[sizeof(InquiryData->ProductId) - 1] = '\0';
+     InquiryData->ProductRevisionLevel[sizeof(InquiryData->ProductRevisionLevel) - 1] = '\0';
+     // send queue depth
+     status = StorPortSetDeviceQueueDepth(PortExtension->AdapterExtension,
+                                          Srb->PathId,
+                                          Srb->TargetId,
+                                          Srb->Lun,
+                                          AHCI_Global_Port_CAP_NCS(AdapterExtension->CAP));
+     NT_ASSERT(status == TRUE);
+     return;
+ }// -- InquiryCompletion();
+  /**
+  * @name AhciATAPICommand
+  * @implemented
+  *
+  * Handles ATAPI Requests commands
+  *
+  * @param AdapterExtension
+  * @param Srb
+  * @param Cdb
+  *
+  * @return
+  * return STOR status for AhciATAPICommand
+  */
+ UCHAR
+ AhciATAPICommand (
+     __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
+     __in PSCSI_REQUEST_BLOCK Srb,
+     __in PCDB Cdb
+     )
+ {
+     ULONG SrbFlags, DataBufferLength;
+     PAHCI_SRB_EXTENSION SrbExtension;
+     PAHCI_PORT_EXTENSION PortExtension;
+     AhciDebugPrint("AhciATAPICommand()\n");
+     SrbFlags = Srb->SrbFlags;
+     SrbExtension = GetSrbExtension(Srb);
+     DataBufferLength = Srb->DataTransferLength;
+     PortExtension = &AdapterExtension->PortExtension[Srb->PathId];
+     NT_ASSERT(PortExtension->DeviceParams.DeviceType == AHCI_DEVICE_TYPE_ATAPI);
+     NT_ASSERT(SrbExtension != NULL);
+     SrbExtension->AtaFunction = ATA_FUNCTION_ATAPI_COMMAND;
+     SrbExtension->Flags = 0;
+     if (SrbFlags & SRB_FLAGS_DATA_IN)
+     {
+         SrbExtension->Flags |= ATA_FLAGS_DATA_IN;
+     }
+     if (SrbFlags & SRB_FLAGS_DATA_OUT)
+     {
+         SrbExtension->Flags |= ATA_FLAGS_DATA_OUT;
+     }
+     SrbExtension->FeaturesLow = 0;
+     SrbExtension->CompletionRoutine = NULL;
+     NT_ASSERT(Cdb != NULL);
+     switch(Cdb->CDB10.OperationCode)
+     {
+         case SCSIOP_INQUIRY:
+             SrbExtension->Flags |= ATA_FLAGS_DATA_IN;
+             SrbExtension->CompletionRoutine = AtapiInquiryCompletion;
+             break;
+         case SCSIOP_READ:
+             SrbExtension->Flags |= ATA_FLAGS_USE_DMA;
+             SrbExtension->FeaturesLow = 0x5;
+             break;
+         case SCSIOP_WRITE:
+             SrbExtension->Flags |= ATA_FLAGS_USE_DMA;
+             SrbExtension->FeaturesLow = 0x1;
+             break;
+     }
+     SrbExtension->CommandReg = IDE_COMMAND_ATAPI_PACKET;
+     SrbExtension->LBA0 = 0;
+     SrbExtension->LBA1 = (UCHAR)(DataBufferLength >> 0);
+     SrbExtension->LBA2 = (UCHAR)(DataBufferLength >> 8);
+     SrbExtension->Device = 0;
+     SrbExtension->LBA3 = 0;
+     SrbExtension->LBA4 = 0;
+     SrbExtension->LBA5 = 0;
+     SrbExtension->FeaturesHigh = 0;
+     SrbExtension->SectorCountLow = 0;
+     SrbExtension->SectorCountHigh = 0;
+     if ((SrbExtension->Flags & ATA_FLAGS_DATA_IN) || (SrbExtension->Flags & ATA_FLAGS_DATA_OUT))
+     {
+         SrbExtension->pSgl = (PLOCAL_SCATTER_GATHER_LIST)StorPortGetScatterGatherList(AdapterExtension, Srb);
+     }
+     return SRB_STATUS_PENDING;
+ }// -- AhciATAPICommand();
+ /**
+  * @name DeviceRequestSense
+  * @implemented
+  *
+  * Handle SCSIOP_MODE_SENSE OperationCode
+  *
+  * @param AdapterExtension
+  * @param Srb
+  * @param Cdb
+  *
+  * @return
+  * return STOR status for DeviceRequestSense
+  */
+ UCHAR
+ DeviceRequestSense (
+     __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
+     __in PSCSI_REQUEST_BLOCK Srb,
+     __in PCDB Cdb
+     )
+ {
+     PMODE_PARAMETER_HEADER ModeHeader;
+     PAHCI_PORT_EXTENSION PortExtension;
+     AhciDebugPrint("DeviceRequestSense()\n");
+     NT_ASSERT(IsPortValid(AdapterExtension, Srb->PathId));
+     NT_ASSERT(Cdb->CDB10.OperationCode == SCSIOP_MODE_SENSE);
+     PortExtension = &AdapterExtension->PortExtension[Srb->PathId];
+     if (PortExtension->DeviceParams.DeviceType == AHCI_DEVICE_TYPE_ATAPI)
+     {
+         return AhciATAPICommand(AdapterExtension, Srb, Cdb);
+     }
+     ModeHeader = (PMODE_PARAMETER_HEADER)Srb->DataBuffer;
+     NT_ASSERT(ModeHeader != NULL);
+     AhciZeroMemory((PCHAR)ModeHeader, Srb->DataTransferLength);
+     ModeHeader->ModeDataLength = sizeof(MODE_PARAMETER_HEADER);
+     ModeHeader->MediumType = 0;
+     ModeHeader->DeviceSpecificParameter = 0;
+     ModeHeader->BlockDescriptorLength = 0;
+     if (Cdb->MODE_SENSE.PageCode == MODE_SENSE_CURRENT_VALUES)
+     {
+         ModeHeader->ModeDataLength = sizeof(MODE_PARAMETER_HEADER) + sizeof(MODE_PARAMETER_BLOCK);
+         ModeHeader->BlockDescriptorLength = sizeof(MODE_PARAMETER_BLOCK);
+     }
+     return SRB_STATUS_SUCCESS;
+ }// -- DeviceRequestSense();
+ /**
+  * @name DeviceRequestReadWrite
+  * @implemented
+  *
+  * Handle SCSIOP_READ SCSIOP_WRITE OperationCode
+  *
+  * @param AdapterExtension
+  * @param Srb
+  * @param Cdb
+  *
+  * @return
+  * return STOR status for DeviceRequestReadWrite
+  */
+ UCHAR
+ DeviceRequestReadWrite (
+     __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
+     __in PSCSI_REQUEST_BLOCK Srb,
+     __in PCDB Cdb
+     )
+ {
+     BOOLEAN IsReading;
+     ULONG64 StartOffset;
+     PAHCI_SRB_EXTENSION SrbExtension;
+     PAHCI_PORT_EXTENSION PortExtension;
+     ULONG DataTransferLength, BytesPerSector, SectorCount;
+     AhciDebugPrint("DeviceRequestReadWrite()\n");
+     NT_ASSERT(IsPortValid(AdapterExtension, Srb->PathId));
+     NT_ASSERT((Cdb->CDB10.OperationCode == SCSIOP_READ) || (Cdb->CDB10.OperationCode == SCSIOP_WRITE));
+     SrbExtension = GetSrbExtension(Srb);
+     PortExtension = &AdapterExtension->PortExtension[Srb->PathId];
+     if (PortExtension->DeviceParams.DeviceType == AHCI_DEVICE_TYPE_ATAPI)
+     {
+         return AhciATAPICommand(AdapterExtension, Srb, Cdb);
+     }
+     DataTransferLength = Srb->DataTransferLength;
+     BytesPerSector = PortExtension->DeviceParams.BytesPerLogicalSector;
+     NT_ASSERT(BytesPerSector > 0);
+     //ROUND_UP(DataTransferLength, BytesPerSector);
+     SectorCount = DataTransferLength / BytesPerSector;
+     Srb->DataTransferLength = SectorCount * BytesPerSector;
+     StartOffset = AhciGetLba(Cdb, Srb->CdbLength);
+     IsReading = (Cdb->CDB10.OperationCode == SCSIOP_READ);
+     NT_ASSERT(SectorCount > 0);
+     SrbExtension->AtaFunction = ATA_FUNCTION_ATA_READ;
+     SrbExtension->Flags |= ATA_FLAGS_USE_DMA;
+     SrbExtension->CompletionRoutine = NULL;
+     if (IsReading)
+     {
+         SrbExtension->Flags |= ATA_FLAGS_DATA_IN;
+         SrbExtension->CommandReg = IDE_COMMAND_READ_DMA;
+     }
+     else
+     {
+         SrbExtension->Flags |= ATA_FLAGS_DATA_OUT;
+         SrbExtension->CommandReg = IDE_COMMAND_WRITE_DMA;
+     }
+     SrbExtension->FeaturesLow = 0;
+     SrbExtension->LBA0 = (StartOffset >> 0) & 0xFF;
+     SrbExtension->LBA1 = (StartOffset >> 8) & 0xFF;
+     SrbExtension->LBA2 = (StartOffset >> 16) & 0xFF;
+     SrbExtension->Device = (0xA0 | IDE_LBA_MODE);
+     if (PortExtension->DeviceParams.Lba48BitMode)
+     {
+         SrbExtension->Flags |= ATA_FLAGS_48BIT_COMMAND;
+         if (IsReading)
+         {
+             SrbExtension->CommandReg = IDE_COMMAND_READ_DMA_EXT;
+         }
+         else
+         {
+             SrbExtension->CommandReg = IDE_COMMAND_WRITE_DMA_EXT;
+         }
+         SrbExtension->LBA3 = (StartOffset >> 24) & 0xFF;
+         SrbExtension->LBA4 = (StartOffset >> 32) & 0xFF;
+         SrbExtension->LBA5 = (StartOffset >> 40) & 0xFF;
+     }
+     else
+     {
+         NT_ASSERT(FALSE);
+     }
+     SrbExtension->FeaturesHigh = 0;
+     SrbExtension->SectorCountLow = (SectorCount >> 0) & 0xFF;
+     SrbExtension->SectorCountHigh = (SectorCount >> 8) & 0xFF;
+     NT_ASSERT(SectorCount < 0x100);
+     SrbExtension->pSgl = (PLOCAL_SCATTER_GATHER_LIST)StorPortGetScatterGatherList(AdapterExtension, Srb);
+     return SRB_STATUS_PENDING;
+ }// -- DeviceRequestReadWrite();
+ /**
+  * @name DeviceRequestCapacity
+  * @implemented
+  *
+  * Handle SCSIOP_READ_CAPACITY OperationCode
+  *
+  * @param AdapterExtension
+  * @param Srb
+  * @param Cdb
+  *
+  * @return
+  * return STOR status for DeviceRequestCapacity
+  */
+ UCHAR
+ DeviceRequestCapacity (
+     __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
+     __in PSCSI_REQUEST_BLOCK Srb,
+     __in PCDB Cdb
+     )
+ {
+     ULONG MaxLba, BytesPerLogicalSector;
+     PREAD_CAPACITY_DATA ReadCapacity;
+     PAHCI_PORT_EXTENSION PortExtension;
+     AhciDebugPrint("DeviceRequestCapacity()\n");
+     UNREFERENCED_PARAMETER(AdapterExtension);
+     UNREFERENCED_PARAMETER(Cdb);
+     NT_ASSERT(Srb->DataBuffer != NULL);
+     NT_ASSERT(IsPortValid(AdapterExtension, Srb->PathId));
+     PortExtension = &AdapterExtension->PortExtension[Srb->PathId];
+     if (PortExtension->DeviceParams.DeviceType == AHCI_DEVICE_TYPE_ATAPI)
+     {
+         return AhciATAPICommand(AdapterExtension, Srb, Cdb);
+     }
+     if (Cdb->CDB10.OperationCode == SCSIOP_READ_CAPACITY)
+     {
+         ReadCapacity = (PREAD_CAPACITY_DATA)Srb->DataBuffer;
+         BytesPerLogicalSector = PortExtension->DeviceParams.BytesPerLogicalSector;
+         MaxLba = (ULONG)PortExtension->DeviceParams.MaxLba.QuadPart - 1;
+         // I trust you windows :D
+         NT_ASSERT(Srb->DataTransferLength >= sizeof(READ_CAPACITY_DATA));
+         // I trust you user :D
+         NT_ASSERT(PortExtension->DeviceParams.MaxLba.QuadPart < (ULONG)-1);
+         // Actually I don't trust anyone :p
+         Srb->DataTransferLength = sizeof(READ_CAPACITY_DATA);
+         REVERSE_BYTES(&ReadCapacity->BytesPerBlock, &BytesPerLogicalSector);
+         REVERSE_BYTES(&ReadCapacity->LogicalBlockAddress, &MaxLba);
+     }
+     else
+     {
+         AhciDebugPrint("\tSCSIOP_READ_CAPACITY16 not supported\n");
+         NT_ASSERT(FALSE);
+     }
+     return SRB_STATUS_SUCCESS;
+ }// -- DeviceRequestCapacity();
+ /**
+  * @name DeviceRequestComplete
+  * @implemented
+  *
+  * Handle UnHandled Requests
+  *
+  * @param AdapterExtension
+  * @param Srb
+  * @param Cdb
+  *
+  * @return
+  * return STOR status for DeviceRequestComplete
+  */
+ UCHAR
+ DeviceRequestComplete (
+     __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
+     __in PSCSI_REQUEST_BLOCK Srb,
+     __in PCDB Cdb
+     )
+ {
+     AhciDebugPrint("DeviceRequestComplete()\n");
+     UNREFERENCED_PARAMETER(AdapterExtension);
+     UNREFERENCED_PARAMETER(Cdb);
+     Srb->ScsiStatus = SCSISTAT_GOOD;
+     return SRB_STATUS_SUCCESS;
+ }// -- DeviceRequestComplete();
+ /**
+  * @name DeviceReportLuns
+  * @implemented
+  *
+  * Handle SCSIOP_REPORT_LUNS OperationCode
+  *
+  * @param AdapterExtension
+  * @param Srb
+  * @param Cdb
+  *
+  * @return
+  * return STOR status for DeviceReportLuns
+  */
+ UCHAR
+ DeviceReportLuns (
+     __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
+     __in PSCSI_REQUEST_BLOCK Srb,
+     __in PCDB Cdb
+     )
+ {
+     PLUN_LIST LunList;
+     PAHCI_PORT_EXTENSION PortExtension;
+     AhciDebugPrint("DeviceReportLuns()\n");
+     UNREFERENCED_PARAMETER(Cdb);
+     PortExtension = &AdapterExtension->PortExtension[Srb->PathId];
+     NT_ASSERT(Srb->DataTransferLength >= sizeof(LUN_LIST));
+     NT_ASSERT(Cdb->CDB10.OperationCode == SCSIOP_REPORT_LUNS);
+     if (PortExtension->DeviceParams.DeviceType == AHCI_DEVICE_TYPE_ATAPI)
+     {
+         return AhciATAPICommand(AdapterExtension, Srb, Cdb);
+     }
+     LunList = (PLUN_LIST)Srb->DataBuffer;
+     NT_ASSERT(LunList != NULL);
+     AhciZeroMemory((PCHAR)LunList, sizeof(LUN_LIST));
+     LunList->LunListLength[3] = 8;
+     Srb->ScsiStatus = SCSISTAT_GOOD;
+     Srb->DataTransferLength = sizeof(LUN_LIST);
+     return SRB_STATUS_SUCCESS;
+ }// -- DeviceReportLuns();
+ /**
+  * @name DeviceInquiryRequest
+  * @implemented
+  *
+  * Tells wheather given port is implemented or not
+  *
+  * @param AdapterExtension
+  * @param Srb
+  * @param Cdb
+  *
+  * @return
+  * return STOR status for DeviceInquiryRequest
+  *
+  * @remark
+  * http://www.seagate.com/staticfiles/support/disc/manuals/Interface%20manuals/100293068c.pdf
+  */
+ UCHAR
+ DeviceInquiryRequest (
+     __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
+     __in PSCSI_REQUEST_BLOCK Srb,
+     __in PCDB Cdb
+     )
+ {
+     PVOID DataBuffer;
+     PAHCI_SRB_EXTENSION SrbExtension;
+     PAHCI_PORT_EXTENSION PortExtension;
+     PVPD_SUPPORTED_PAGES_PAGE VpdOutputBuffer;
+     ULONG DataBufferLength, RequiredDataBufferLength;
+     AhciDebugPrint("DeviceInquiryRequest()\n");
+     NT_ASSERT(Cdb->CDB10.OperationCode == SCSIOP_INQUIRY);
+     NT_ASSERT(IsPortValid(AdapterExtension, Srb->PathId));
+     SrbExtension = GetSrbExtension(Srb);
+     PortExtension = &AdapterExtension->PortExtension[Srb->PathId];
+     if (PortExtension->DeviceParams.DeviceType == AHCI_DEVICE_TYPE_ATAPI)
+     {
+         return AhciATAPICommand(AdapterExtension, Srb, Cdb);
+     }
+     if (Srb->Lun != 0)
+     {
+         return SRB_STATUS_SELECTION_TIMEOUT;
+     }
+     else if (Cdb->CDB6INQUIRY3.EnableVitalProductData == 0)
+     {
+         // 3.6.1
+         // If the EVPD bit is set to zero, the device server shall return the standard INQUIRY data
+         AhciDebugPrint("\tEVPD Inquired\n");
+         NT_ASSERT(SrbExtension != NULL);
+         SrbExtension->AtaFunction = ATA_FUNCTION_ATA_IDENTIFY;
+         SrbExtension->Flags |= ATA_FLAGS_DATA_IN;
+         SrbExtension->CompletionRoutine = InquiryCompletion;
+         SrbExtension->CommandReg = IDE_COMMAND_NOT_VALID;
+         // TODO: Should use AhciZeroMemory
+         SrbExtension->FeaturesLow = 0;
+         SrbExtension->LBA0 = 0;
+         SrbExtension->LBA1 = 0;
+         SrbExtension->LBA2 = 0;
+         SrbExtension->Device = 0xA0;
+         SrbExtension->LBA3 = 0;
+         SrbExtension->LBA4 = 0;
+         SrbExtension->LBA5 = 0;
+         SrbExtension->FeaturesHigh = 0;
+         SrbExtension->SectorCountLow = 0;
+         SrbExtension->SectorCountHigh = 0;
+         SrbExtension->Sgl.NumberOfElements = 1;
+         SrbExtension->Sgl.List[0].PhysicalAddress.LowPart = PortExtension->IdentifyDeviceDataPhysicalAddress.LowPart;
+         SrbExtension->Sgl.List[0].PhysicalAddress.HighPart = PortExtension->IdentifyDeviceDataPhysicalAddress.HighPart;
+         SrbExtension->Sgl.List[0].Length = sizeof(IDENTIFY_DEVICE_DATA);
+         SrbExtension->pSgl = &SrbExtension->Sgl;
+         return SRB_STATUS_PENDING;
+     }
+     else
+     {
+         AhciDebugPrint("\tVPD Inquired\n");
+         DataBuffer = Srb->DataBuffer;
+         DataBufferLength = Srb->DataTransferLength;
+         RequiredDataBufferLength = DataBufferLength; // make the compiler happy :p
+         if (DataBuffer == NULL)
+         {
+             return SRB_STATUS_INVALID_REQUEST;
+         }
+         AhciZeroMemory(DataBuffer, DataBufferLength);
+         switch(Cdb->CDB6INQUIRY3.PageCode)
+         {
+             case VPD_SUPPORTED_PAGES:
+                 {
+                     AhciDebugPrint("\tVPD_SUPPORTED_PAGES\n");
+                     RequiredDataBufferLength = sizeof(VPD_SUPPORTED_PAGES_PAGE) + 1;
+                     if (DataBufferLength < RequiredDataBufferLength)
+                     {
+                         AhciDebugPrint("\tDataBufferLength: %d Required: %d\n", DataBufferLength, RequiredDataBufferLength);
+                         return SRB_STATUS_INVALID_REQUEST;
+                     }
+                     VpdOutputBuffer = (PVPD_SUPPORTED_PAGES_PAGE)DataBuffer;
+                     VpdOutputBuffer->DeviceType = PortExtension->DeviceParams.AccessType;
+                     VpdOutputBuffer->DeviceTypeQualifier = 0;
+                     VpdOutputBuffer->PageCode = VPD_SUPPORTED_PAGES;
+                     VpdOutputBuffer->PageLength = 1;
+                     VpdOutputBuffer->SupportedPageList[0] = VPD_SUPPORTED_PAGES;
+                     //VpdOutputBuffer->SupportedPageList[1] = VPD_SERIAL_NUMBER;
+                     //VpdOutputBuffer->SupportedPageList[2] = VPD_DEVICE_IDENTIFIERS;
+                     NT_ASSERT(VpdOutputBuffer->DeviceType == DIRECT_ACCESS_DEVICE);
+                 }
+                 break;
+             case VPD_SERIAL_NUMBER:
+                 {
+                     AhciDebugPrint("\tVPD_SERIAL_NUMBER\n");
+                 }
+                 break;
+             case VPD_DEVICE_IDENTIFIERS:
+                 {
+                     AhciDebugPrint("\tVPD_DEVICE_IDENTIFIERS\n");
+                 }
+                 break;
+             default:
+                 AhciDebugPrint("\tPageCode: %x\n", Cdb->CDB6INQUIRY3.PageCode);
+                 return SRB_STATUS_INVALID_REQUEST;
+         }
+         Srb->DataTransferLength = RequiredDataBufferLength;
+         return SRB_STATUS_SUCCESS;
+     }
+ }// -- DeviceInquiryRequest();
+ /**
+  * @name AhciAdapterReset
+  * @implemented
+  *
+  * 10.4.3 HBA Reset
+  * If the HBA becomes unusable for multiple ports, and a software reset or port reset does not correct the
+  * problem, software may reset the entire HBA by setting GHC.HR to ‘1’. When software sets the GHC.HR
+  * bit to ‘1’, the HBA shall perform an internal reset action. The bit shall be cleared to ‘0’ by the HBA when
+  * the reset is complete. A software write of ‘0’ to GHC.HR shall have no effect. To perform the HBA reset,
+  * 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.
+  *
+  * @param AdapterExtension
+  *
+  * @return
+  * TRUE in case AHCI Controller RESTARTED successfully. i.e GHC.HR == 0
+  */
+ BOOLEAN
+ AhciAdapterReset (
+     __in PAHCI_ADAPTER_EXTENSION AdapterExtension
+     )
+ {
+     ULONG ticks;
+     AHCI_GHC ghc;
+     PAHCI_MEMORY_REGISTERS abar = NULL;
+     AhciDebugPrint("AhciAdapterReset()\n");
+     abar = AdapterExtension->ABAR_Address;
+     if (abar == NULL) // basic sanity
+     {
+         return FALSE;
+     }
+     // HR -- Very first bit (lowest significant)
+     ghc.HR = 1;
+     StorPortWriteRegisterUlong(AdapterExtension, &abar->GHC, ghc.Status);
+     for (ticks = 0; ticks < 50; ++ticks)
+     {
+         ghc.Status = StorPortReadRegisterUlong(AdapterExtension, &abar->GHC);
+         if (ghc.HR == 0)
+         {
+             break;
+         }
+         StorPortStallExecution(20000);
+     }
+     if (ticks == 50)// 1 second
+     {
+         AhciDebugPrint("\tDevice Timeout\n");
+         return FALSE;
+     }
+     return TRUE;
+ }// -- AhciAdapterReset();
+ /**
+  * @name AhciZeroMemory
+  * @implemented
+  *
+  * Clear buffer by filling zeros
+  *
+  * @param Buffer
+  * @param BufferSize
+  */
+ __inline
+ VOID
+ AhciZeroMemory (
+     __out PCHAR Buffer,
+     __in ULONG BufferSize
+     )
+ {
+     ULONG i;
+     for (i = 0; i < BufferSize; i++)
+     {
+         Buffer[i] = 0;
+     }
+     return;
+ }// -- AhciZeroMemory();
+ /**
+  * @name IsPortValid
+  * @implemented
+  *
+  * Tells wheather given port is implemented or not
+  *
+  * @param AdapterExtension
+  * @param PathId
+  *
+  * @return
+  * return TRUE if provided port is valid (implemented) or not
+  */
+ __inline
+ BOOLEAN
+ IsPortValid (
+     __in PAHCI_ADAPTER_EXTENSION AdapterExtension,
+     __in ULONG pathId
+     )
+ {
+     NT_ASSERT(pathId < MAXIMUM_AHCI_PORT_COUNT);
+     if (pathId >= AdapterExtension->PortCount)
+     {
+         return FALSE;
+     }
+     return AdapterExtension->PortExtension[pathId].DeviceParams.IsActive;
+ }// -- IsPortValid()
+ /**
+  * @name AddQueue
+  * @implemented
+  *
+  * Add Srb to Queue
+  *
+  * @param Queue
+  * @param Srb
+  *
+  * @return
+  * return TRUE if Srb is successfully added to Queue
+  *
+  */
+ __inline
+ BOOLEAN
+ AddQueue (
+     __inout PAHCI_QUEUE Queue,
+     __in PVOID Srb
+     )
+ {
+     NT_ASSERT(Queue->Head < MAXIMUM_QUEUE_BUFFER_SIZE);
+     NT_ASSERT(Queue->Tail < MAXIMUM_QUEUE_BUFFER_SIZE);
+     if (Queue->Tail == ((Queue->Head + 1) % MAXIMUM_QUEUE_BUFFER_SIZE))
+         return FALSE;
+     Queue->Buffer[Queue->Head++] = Srb;
+     Queue->Head %= MAXIMUM_QUEUE_BUFFER_SIZE;
+     return TRUE;
+ }// -- AddQueue();
+ /**
+  * @name RemoveQueue
+  * @implemented
+  *
+  * Remove and return Srb from Queue
+  *
+  * @param Queue
+  *
+  * @return
+  * return Srb
+  *
+  */
+ __inline
+ PVOID
+ RemoveQueue (
+     __inout PAHCI_QUEUE Queue
+     )
+ {
+     PVOID Srb;
+     NT_ASSERT(Queue->Head < MAXIMUM_QUEUE_BUFFER_SIZE);
+     NT_ASSERT(Queue->Tail < MAXIMUM_QUEUE_BUFFER_SIZE);
+     if (Queue->Head == Queue->Tail)
+         return NULL;
+     Srb = Queue->Buffer[Queue->Tail++];
+     Queue->Tail %= MAXIMUM_QUEUE_BUFFER_SIZE;
+     return Srb;
+ }// -- RemoveQueue();
+ /**
+  * @name GetSrbExtension
+  * @implemented
+  *
+  * GetSrbExtension from Srb make sure It is properly aligned
+  *
+  * @param Srb
+  *
+  * @return
+  * return SrbExtension
+  *
+  */
+ __inline
+ PAHCI_SRB_EXTENSION
+ GetSrbExtension (
+     __in PSCSI_REQUEST_BLOCK Srb
+     )
+ {
+     ULONG Offset;
+     ULONG_PTR SrbExtension;
+     SrbExtension = (ULONG_PTR)Srb->SrbExtension;
+     Offset = SrbExtension % 128;
+     // CommandTable should be 128 byte aligned
+     if (Offset != 0)
+         Offset = 128 - Offset;
+     return (PAHCI_SRB_EXTENSION)(SrbExtension + Offset);
+ }// -- PAHCI_SRB_EXTENSION();
+ /**
+  * @name AhciGetLba
+  * @implemented
+  *
+  * Find the logical address of demand block from Cdb
+  *
+  * @param Srb
+  *
+  * @return
+  * return Logical Address of the block
+  *
+  */
+ __inline
+ ULONG64
+ AhciGetLba (
+     __in PCDB Cdb,
+     __in ULONG CdbLength
+     )
+ {
+     ULONG64 lba = 0;
+     NT_ASSERT(Cdb != NULL);
+     NT_ASSERT(CdbLength != 0);
+     if (CdbLength == 0x10)
+     {
+         REVERSE_BYTES_QUAD(&lba, Cdb->CDB16.LogicalBlock);
+     }
+     else
+     {
+         lba |= Cdb->CDB10.LogicalBlockByte3 << 0;
+         lba |= Cdb->CDB10.LogicalBlockByte2 << 8;
+         lba |= Cdb->CDB10.LogicalBlockByte1 << 16;
+         lba |= Cdb->CDB10.LogicalBlockByte0 << 24;
+     }
+     return lba;
+ }// -- AhciGetLba();
index 0000000,6adcc50..6adcc50
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,711 +1,711 @@@
+ /*
+  * 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)
+  */
+ #include <ntddk.h>
+ #include <ata.h>
+ #include <storport.h>
+ #define DEBUG 1
+ #pragma warning(disable:4214) // bit field types other than int
+ #pragma warning(disable:4201) // nameless struct/union
+ #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_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__)
+ 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
+                             // 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;
+     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;
+     UCHAR Reserved1 :5;
+     UCHAR D :1;
+     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];
+ } AHCI_PIO_SETUP_FIS;
+ typedef struct _AHCI_D2H_REGISTER_FIS
+ {
+     UCHAR FisType;
+     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;
+ typedef struct _AHCI_SET_DEVICE_BITS_FIS
+ {
+     UCHAR FisType;
+     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];
+ } 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
+ {
+     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
+ typedef struct _AHCI_RECEIVED_FIS
+ {
+     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
+ } 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 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[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;
+     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;
+ // Holds Adapter Information
+ typedef struct _AHCI_ADAPTER_EXTENSION
+ {
+     ULONG   SystemIoBusNumber;
+     ULONG   SlotNumber;
+     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;
+     USHORT  RevisionID;
+     ULONG   Version;
+     ULONG   CAP;
+     ULONG   CAP2;
+     ULONG   LastInterruptPort;
+     ULONG   CurrentCommandSlot;
+     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[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
+ {
+     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);
index 0000000,f291c2b..f291c2b
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,77 +1,77 @@@
+ ;\r
+ ; PROJECT:        ROS Kernel\r
+ ; LICENSE:        GNU GPLv2 only as published by the Free Software Foundation\r
+ ; PURPOSE:        Storahci Driver INF\r
+ ; PROGRAMMERS:    Aman Priyadarshi (aman.eureka@gmail.com)\r
+ ;\r
\r
+ [version]\r
+ signature="$Windows NT$"\r
+ Class=hdc\r
+ ClassGuid={4D36E96A-E325-11CE-BFC1-08002BE10318}\r
+ Provider=%ROS%\r
\r
+ [SourceDisksNames]\r
+ 1 = %DeviceDesc%,,,\r
\r
+ [SourceDisksFiles]\r
+ storahci.sys = 1\r
\r
+ [DestinationDirs]\r
+ DefaultDestDir = 12 ; DIRID_DRIVERS\r
\r
+ [Manufacturer]\r
+ %ROS%=STORAHCI,NTx86\r
\r
+ [STORAHCI]\r
\r
+ [STORAHCI.NTx86]\r
+ %SATA_AHCI.DeviceDesc%=storahci_Inst, PCI\CC_010601; Standard SATA AHCI Controller\r
\r
+ [ControlFlags]\r
+ ExcludeFromSelect = *\r
\r
+ [storahci_Inst]\r
+ CopyFiles = storahci_CopyFiles\r
\r
+ [storahci_Inst.HW]\r
+ ; Enables Storport IPM for this adapter\r
+ HKR, "StorPort", "EnableIdlePowerManagement", %REG_DWORD%, 0x01\r
\r
+ [storahci_Inst.Services]\r
+ AddService = storahci, %SPSVCINST_ASSOCSERVICE%, storahci_Service_Inst, Miniport_EventLog_Inst\r
\r
+ [storahci_Service_Inst]\r
+ DisplayName    = %DeviceDesc%\r
+ ServiceType    = %SERVICE_KERNEL_DRIVER%\r
+ StartType      = %SERVICE_BOOT_START%\r
+ ErrorControl   = %SERVICE_ERROR_CRITICAL%\r
+ ServiceBinary  = %12%\storahci.sys\r
+ LoadOrderGroup = SCSI Miniport\r
+ AddReg         = ahci_addreg\r
\r
+ [storahci_CopyFiles]\r
+ storahci.sys,,,1\r
\r
+ [ahci_addreg]\r
+ HKR, "Parameters\PnpInterface", "5", %REG_DWORD%, 0x00000001\r
+ HKR, "Parameters", "BusType", %REG_DWORD%, 0x0000000B\r
\r
+ [Miniport_EventLog_Inst]\r
+ AddReg = Miniport_EventLog_AddReg\r
\r
+ [Miniport_EventLog_AddReg]\r
+ HKR,,EventMessageFile,%REG_EXPAND_SZ%,"%%SystemRoot%%\System32\IoLogMsg.dll"\r
+ HKR,,TypesSupported,%REG_DWORD%,7\r
\r
+ [Strings]\r
+ ROS                     = "ReactOS"\r
+ DeviceDesc              = "AHCI SATA Driver"\r
+ SATA_AHCI.DeviceDesc    = "Standard SATA AHCI Controller"\r
\r
+ SPSVCINST_ASSOCSERVICE = 0x00000002\r
+ SERVICE_KERNEL_DRIVER  = 1\r
+ SERVICE_BOOT_START     = 0\r
+ SERVICE_ERROR_CRITICAL = 3\r
+ REG_EXPAND_SZ          = 0x00020000\r
+ REG_DWORD              = 0x00010001\r
index 0000000,5950ce2..5950ce2
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,22 +1,22 @@@
+ //
+ // 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)
+ //
+ #define VERSION       1
+ #define VERSION_STR "1.0"
+ #define REACTOS_FILETYPE              VFT_DRV
+ #define REACTOS_FILESUBTYPE           VFT2_DRV_SYSTEM
+ #define REACTOS_FILEVERSION           VERSION
+ #define REACTOS_PRODUCTVERSION        VERSION
+ #define REACTOS_STR_COMPANY_NAME      "ReactOS Development Team"
+ #define REACTOS_STR_FILE_DESCRIPTION  "AHCI Storport Miniport Driver"
+ #define REACTOS_STR_FILE_VERSION      VERSION_STR
+ #define REACTOS_STR_INTERNAL_NAME     "storahci.sys"
+ #define REACTOS_STR_ORIGINAL_FILENAME "storahci.sys"
+ #define REACTOS_STR_LEGAL_COPYRIGHT   "Copyright 2016 ReactOS Team"
+ #define REACTOS_STR_PRODUCT_NAME      "AHCI Driver for ReactOS"
+ #define REACTOS_STR_PRODUCT_VERSION   VERSION_STR