From a60737f997ccdc6e77fc8e9e5b5fd30374d1d2d1 Mon Sep 17 00:00:00 2001 From: Aman Priyadarshi Date: Thu, 2 Jun 2016 14:13:06 +0000 Subject: [PATCH] == Storahci driver - 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 | 3 + drivers/storage/storahci/sources | 8 + drivers/storage/storahci/storahci.c | 231 ++++++++++++++++++++++++++++ drivers/storage/storahci/storahci.h | 74 +++++++++ 4 files changed, 316 insertions(+) create mode 100644 drivers/storage/storahci/makefile create mode 100644 drivers/storage/storahci/sources create mode 100644 drivers/storage/storahci/storahci.c create mode 100644 drivers/storage/storahci/storahci.h diff --git a/drivers/storage/storahci/makefile b/drivers/storage/storahci/makefile new file mode 100644 index 00000000000..e9acee28a29 --- /dev/null +++ b/drivers/storage/storahci/makefile @@ -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 index 00000000000..a0c63d5bbe5 --- /dev/null +++ b/drivers/storage/storahci/sources @@ -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 index 00000000000..f6912e253b9 --- /dev/null +++ b/drivers/storage/storahci/storahci.c @@ -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 index 00000000000..33c7966c042 --- /dev/null +++ b/drivers/storage/storahci/storahci.h @@ -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 -- 2.17.1