== 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
This commit is contained in:
Aman Priyadarshi 2016-06-02 14:13:06 +00:00
parent 321bcc056d
commit a60737f997
4 changed files with 316 additions and 0 deletions

View file

@ -0,0 +1,3 @@
MINIMUM_NT_TARGET_VERSION=0x502
!INCLUDE $(NTMAKEENV)\makefile.def

View file

@ -0,0 +1,8 @@
TARGETNAME = storahci
TARGETTYPE = MINIPORT
TARGETLIBS=$(DDK_LIB_PATH)\storport.lib
INCLUDES = %BUILD%\inc
LIBS = %BUILD%\lib
SOURCES = storahci.c

View file

@ -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, its 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();

View file

@ -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;