== Storahci driver
authorAman Priyadarshi <aman.eureka@gmail.com>
Thu, 2 Jun 2016 14:13:06 +0000 (14:13 +0000)
committerAman Priyadarshi <aman.eureka@gmail.com>
Thu, 2 Jun 2016 14:13:06 +0000 (14:13 +0000)
- Added DriverEntry
- Added AhciFindAdapter : Need to add code for port initialization.
- Compile : OK
- Test : NOT TESTED

svn path=/branches/GSoC_2016/AHCI/; revision=71499

drivers/storage/storahci/makefile [new file with mode: 0644]
drivers/storage/storahci/sources [new file with mode: 0644]
drivers/storage/storahci/storahci.c [new file with mode: 0644]
drivers/storage/storahci/storahci.h [new file with mode: 0644]

diff --git a/drivers/storage/storahci/makefile b/drivers/storage/storahci/makefile
new file mode 100644 (file)
index 0000000..e9acee2
--- /dev/null
@@ -0,0 +1,3 @@
+
+MINIMUM_NT_TARGET_VERSION=0x502
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/drivers/storage/storahci/sources b/drivers/storage/storahci/sources
new file mode 100644 (file)
index 0000000..a0c63d5
--- /dev/null
@@ -0,0 +1,8 @@
+TARGETNAME = storahci
+TARGETTYPE = MINIPORT
+
+TARGETLIBS=$(DDK_LIB_PATH)\storport.lib
+INCLUDES   = %BUILD%\inc
+LIBS       = %BUILD%\lib
+SOURCES    = storahci.c
diff --git a/drivers/storage/storahci/storahci.c b/drivers/storage/storahci/storahci.c
new file mode 100644 (file)
index 0000000..f6912e2
--- /dev/null
@@ -0,0 +1,231 @@
+#include "storahci.h"
+
+BOOLEAN AhciAdapterReset(
+    __in  PAHCI_ADAPTER_EXTENSION                      adapterExtension        
+);
+
+ULONG AhciFindAdapter(
+          IN PVOID                                                     DeviceExtension,
+  __in    PVOID                                                                HwContext,
+  __in    PVOID                                                                BusInformation,
+  __in    IN PVOID                                                     ArgumentString,
+  __inout PPORT_CONFIGURATION_INFORMATION      ConfigInfo,
+  __in    PBOOLEAN                                                     Reserved3
+)
+{
+       /* Description :
+        *              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.
+        *
+        * Refernce:
+        *              10.1 Platform Communication
+        *              http://www.intel.in/content/dam/www/public/us/en/documents/technical-specifications/serial-ata-ahci-spec-rev1_2.pdf
+        *
+        * Return Value:
+        *              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.
+        */
+
+       ULONG ghc;
+       ULONG portCount, portImplemented;
+       ULONG pci_cfg_len;
+       UCHAR pci_cfg_buf[0x30];
+       
+       PAHCI_MEMORY_REGISTERS abar;
+       PPCI_COMMON_CONFIG pciConfigData;
+       PAHCI_ADAPTER_EXTENSION adapterExtension;
+
+       adapterExtension = (PAHCI_ADAPTER_EXTENSION)DeviceExtension;
+       adapterExtension->SlotNumber = ConfigInfo->SlotNumber;
+       adapterExtension->SystemIoBusNumber = ConfigInfo->SystemIoBusNumber;
+       
+       // get PCI configuration header
+       pci_cfg_len = StorPortGetBusData(
+                                               adapterExtension,
+                                               PCIConfiguration,
+                                               adapterExtension->SystemIoBusNumber,
+                                               adapterExtension->SlotNumber,
+                                               (PVOID)pci_cfg_buf,
+                                               (ULONG)0x30);
+
+       if (pci_cfg_len != 0x30)
+               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);
+
+       // 2.1.11
+       abar = NULL;
+       if (ConfigInfo->NumberOfAccessRanges > 0)
+       {
+               ULONG accessIndex;
+               for (accessIndex = 0; accessIndex < ConfigInfo->NumberOfAccessRanges; accessIndex++)
+               {
+                       if ((*(ConfigInfo->AccessRanges))[accessIndex].RangeStart.QuadPart == adapterExtension->AhciBaseAddress)
+                       {
+                               abar = (PAHCI_MEMORY_REGISTERS)StorPortGetDeviceBase(
+                                                               adapterExtension,
+                                                               ConfigInfo->AdapterInterfaceType,
+                                                               ConfigInfo->SystemIoBusNumber,
+                                                               (*(ConfigInfo->AccessRanges))[accessIndex].RangeStart,
+                                                               (*(ConfigInfo->AccessRanges))[accessIndex].RangeLength,
+                                                               (BOOLEAN)!(*(ConfigInfo->AccessRanges))[accessIndex].RangeInMemory);
+                               break;
+                       }
+               }
+       }
+
+       if (abar == NULL)
+               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);
+
+       // 10.1.2
+       // 1. Indicate that system software is AHCI aware by setting GHC.AE to ‘1’.
+       ghc = StorPortReadRegisterUlong(adapterExtension, &abar->GHC);
+       // AE := Highest Significant bit of GHC
+       if ((ghc & (0x1<<31)) == 1)//Hmm, controller was already in power state
+       {
+               // reset controller to have it in know state
+               DebugPrint("AhciFindAdapter -> AE Already set, Reset()\n");
+               if (!AhciAdapterReset(adapterExtension))
+                       return SP_RETURN_ERROR;// reset failed
+       }
+
+       ghc = 0x1<<31;// only AE=1
+       StorPortWriteRegisterUlong(adapterExtension, &abar->GHC, ghc);
+
+       adapterExtension->IS = abar->IS;
+       adapterExtension->PortImplemented = StorPortReadRegisterUlong(adapterExtension, &abar->PI);
+
+       if (adapterExtension->PortImplemented == 0)
+               return SP_RETURN_ERROR;
+
+       // get port count -- Number of set bits in `adapterExtension->PortImplemented`
+       portCount = 0;
+       portImplemented = adapterExtension->PortImplemented;
+       while(portImplemented > 0)
+       {
+               portCount++;
+               portImplemented &= (portImplemented - 1);// i love playing with bits :D
+       }
+
+       ConfigInfo->MaximumTransferLength = 128 * 1024;//128 KB
+       ConfigInfo->NumberOfPhysicalBreaks = 0x21;
+       ConfigInfo->MaximumNumberOfTargets = 1;
+       ConfigInfo->MaximumNumberOfLogicalUnits = 1;
+       ConfigInfo->ResetTargetSupported = TRUE;
+       ConfigInfo->NumberOfBuses = 32;
+       ConfigInfo->SynchronizationModel = StorSynchronizeFullDuplex;
+       ConfigInfo->ScatterGather = TRUE;
+
+       // Turn IE -- Interrupt Enabled
+       ghc |= 0x2;
+       StorPortWriteRegisterUlong(adapterExtension, &abar->GHC, ghc);
+
+
+
+       return SP_RETURN_FOUND;
+}//    -- AhciFindAdapter();
+
+ULONG DriverEntry(
+                       IN PVOID                                                DriverObject,
+                       IN PVOID                                                RegistryPath
+)
+{
+       /*
+        * Description :
+        *              Initial Entrypoint for storahci miniport driver
+        */
+
+       HW_INITIALIZATION_DATA hwInitializationData;
+       ULONG i, status;
+
+       DebugPrint("Storahci -> DriverEntry()\n");
+
+       // initialize the hardware data structure
+       for (i = 0; i < sizeof(HW_INITIALIZATION_DATA); i++)
+               ((PUCHAR)&hwInitializationData)[i] = 0;
+
+       // set size of hardware initialization structure
+       hwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
+
+       // identity required miniport entry point routines
+       hwInitializationData.HwFindAdapter = AhciFindAdapter;
+
+       // adapter specific information
+       hwInitializationData.NeedPhysicalAddresses = TRUE;
+       hwInitializationData.TaggedQueuing = TRUE;
+       hwInitializationData.AutoRequestSense = TRUE;
+       hwInitializationData.MultipleRequestPerLu = 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);
+
+    return status;
+}// -- DriverEntry();
+
+BOOLEAN AhciAdapterReset(
+      PAHCI_ADAPTER_EXTENSION                  adapterExtension        
+)
+{
+       /*
+        * 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. 
+        */
+        ULONG ghc, ticks;
+        PAHCI_MEMORY_REGISTERS abar = NULL;
+
+        abar = adapterExtension->ABAR_Address;
+
+        if (abar == NULL) // basic sanity
+               return FALSE;
+
+        // HR -- Very first bit (lowest significant)
+        ghc = 1;
+        StorPortWriteRegisterUlong(adapterExtension, &abar->GHC, ghc);
+
+        for (ticks = 0; (ticks < 50) &&
+                                        (StorPortReadRegisterUlong(adapterExtension, &abar->GHC) == 1);
+                                        StorPortStallExecution(20000), ticks++);
+
+        if (ticks == 50)//1 second
+               return FALSE;
+
+        return TRUE;
+}// -- AhciAdapterReset();
diff --git a/drivers/storage/storahci/storahci.h b/drivers/storage/storahci/storahci.h
new file mode 100644 (file)
index 0000000..33c7966
--- /dev/null
@@ -0,0 +1,74 @@
+#include "miniport.h"
+#include "storport.h"
+
+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;
+
+typedef struct _AHCI_MEMORY_REGISTERS
+{
+       // 0x00 - 0x2B, Generic Host Control
+       ULONG CAP;                                              // 0x00, Host capability
+       ULONG GHC;                                              // 0x04, Global host control
+       ULONG IS;                                               // 0x08, Interrupt status
+       ULONG PI;                                               // 0x0C, Port implemented
+       ULONG VS;                                               // 0x10, Version
+       ULONG CCC_CTL;                                  // 0x14, Command completion coalescing control
+       ULONG CCC_PTS;                                  // 0x18, Command completion coalescing ports
+       ULONG EM_LOC;                                   // 0x1C, Enclosure management location
+       ULONG EM_CTL;                                   // 0x20, Enclosure management control
+       ULONG CAP2;                                             // 0x24, Host capabilities extended
+       ULONG BOHC;                                             // 0x28, BIOS/OS handoff control and status
+
+       // 0x2C - 0x9F, Reserved
+       ULONG Reserved[0xA0-0x2C];
+
+       // 0xA0 - 0xFF, Vendor specific registers
+       ULONG VendorSpecific[0x100-0xA0];
+
+       AHCI_PORT PortList[32];//1~32
+
+} AHCI_MEMORY_REGISTERS, *PAHCI_MEMORY_REGISTERS;
+
+typedef struct _AHCI_ADAPTER_EXTENSION
+{
+       ULONG   AdapterNumber;
+       ULONG   SystemIoBusNumber;
+       ULONG   SlotNumber;
+       ULONG   AhciBaseAddress;
+       ULONG   IS;                                     // Interrupt status
+       ULONG   PortImplemented;
+
+       USHORT  VendorID;
+       USHORT  DeviceID;
+       USHORT  RevisionID;
+
+       ULONG   Version;
+       ULONG   CAP;
+       ULONG   CAP2;
+       PAHCI_MEMORY_REGISTERS ABAR_Address;
+} AHCI_ADAPTER_EXTENSION, *PAHCI_ADAPTER_EXTENSION;
+
+typedef struct _AHCI_SRB_EXTENSION
+{
+       ULONG AdapterNumber;
+} AHCI_SRB_EXTENSION;
\ No newline at end of file