From f7890a371a2871509e82777b467abe373a488f92 Mon Sep 17 00:00:00 2001 From: Aman Priyadarshi Date: Fri, 3 Jun 2016 15:54:21 +0000 Subject: [PATCH] AhciFindAdapter Completed - Added AhciZeroMemory - Added AhciAllocateResourceForAdapter - Added AhciPortInitialize Compile Status : OK svn path=/branches/GSoC_2016/AHCI/; revision=71506 --- drivers/storage/storahci/storahci.c | 184 +++++++++++++++++++++++++--- drivers/storage/storahci/storahci.h | 142 ++++++++++++++++++++- 2 files changed, 305 insertions(+), 21 deletions(-) diff --git a/drivers/storage/storahci/storahci.c b/drivers/storage/storahci/storahci.c index df7d1b76841..6e21584b24a 100644 --- a/drivers/storage/storahci/storahci.c +++ b/drivers/storage/storahci/storahci.c @@ -8,9 +8,136 @@ #include "storahci.h" BOOLEAN AhciAdapterReset( - __in PAHCI_ADAPTER_EXTENSION adapterExtension + __in PAHCI_ADAPTER_EXTENSION adapterExtension ); +VOID AhciZeroMemory( + __in PCHAR buffer, + __in ULONG bufferSize +); + +/** + * @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 +) +{ + ULONG mappedLength; + PAHCI_MEMORY_REGISTERS abar; + PAHCI_ADAPTER_EXTENSION adapterExtension; + STOR_PHYSICAL_ADDRESS commandListPhysical, receivedFISPhysical; + + adapterExtension = portExtension->AdapterExtension; + abar = adapterExtension->ABAR_Address; + portExtension->Port = &abar->PortList[portExtension->PortNumber]; + + commandListPhysical = StorPortGetPhysicalAddress(adapterExtension, NULL, portExtension->CommandList, &mappedLength); + if (mappedLength == 0 || (commandListPhysical.LowPart % 1024) != 0) + return FALSE; + + receivedFISPhysical = StorPortGetPhysicalAddress(adapterExtension, NULL, portExtension->ReceivedFIS, &mappedLength); + if (mappedLength == 0 || (commandListPhysical.LowPart % 256) != 0) + return FALSE; + + // 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); + StorPortWriteRegisterUlong(adapterExtension, &portExtension->Port->FB, receivedFISPhysical.LowPart); + + 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 +) +{ + PVOID portsExtension = NULL; + PCHAR nonCachedExtension; + ULONG portCount, portImplemented, status, index, NCS, AlignedNCS, nonCachedExtensionSize, currentCount; + + // 3.1.1 NCS = CAP[12:08] -> Align + NCS = (adapterExtension->CAP & 0xF00) >> 8; + AlignedNCS = ((NCS/8) + 1) * 8; + + // get port count -- Number of set bits in `adapterExtension->PortImplemented` + portCount = 0; + portImplemented = adapterExtension->PortImplemented; + while(portImplemented > 0) + { + portCount++; + portImplemented &= (portImplemented-1); + } + + nonCachedExtensionSize = sizeof(AHCI_COMMAND_HEADER) * AlignedNCS + //should be 1K aligned + sizeof(AHCI_RECEIVED_FIS); + //align nonCachedExtensionSize to 1K + nonCachedExtensionSize = (((nonCachedExtensionSize - 1) / 0x400) + 1) * 0x400; + nonCachedExtensionSize *= portCount; + + adapterExtension->NonCachedExtension = StorPortGetUncachedExtension(adapterExtension, ConfigInfo, nonCachedExtensionSize); + if (adapterExtension->NonCachedExtension == NULL) + return FALSE; + + nonCachedExtension = (PCHAR)adapterExtension->NonCachedExtension; + + AhciZeroMemory(nonCachedExtension, nonCachedExtensionSize); + + + // allocate memory for port extension + status = StorPortAllocatePool( + adapterExtension, + portCount * sizeof(AHCI_PORT_EXTENSION), + AHCI_POOL_TAG, + (PVOID*)&portsExtension); + + if (status != STOR_STATUS_SUCCESS) + return FALSE; + + AhciZeroMemory((PCHAR)portsExtension, portCount * sizeof(AHCI_PORT_EXTENSION)); + + nonCachedExtensionSize /= portCount; + currentCount = 0; + for (index = 0; index < 32; index++) + { + if ((adapterExtension->PortImplemented & (1<PortExtension[index] = (PAHCI_PORT_EXTENSION)((PCHAR)portsExtension + sizeof(AHCI_PORT_EXTENSION) * currentCount); + + adapterExtension->PortExtension[index]->PortNumber = index; + adapterExtension->PortExtension[index]->AdapterExtension = adapterExtension; + adapterExtension->PortExtension[index]->CommandList = (PAHCI_COMMAND_HEADER)(nonCachedExtension + (currentCount*nonCachedExtensionSize)); + adapterExtension->PortExtension[index]->ReceivedFIS = (PAHCI_RECEIVED_FIS)((PCHAR)adapterExtension->PortExtension[index]->CommandList + sizeof(AHCI_COMMAND_HEADER) * AlignedNCS); + currentCount++; + } + } + + return TRUE; +}// -- AhciAllocateResourceForAdapter(); + /** * @name AhciFindAdapter * @implemented @@ -53,6 +180,7 @@ ULONG AhciFindAdapter( ) { ULONG ghc; + ULONG index; ULONG portCount, portImplemented; ULONG pci_cfg_len; UCHAR pci_cfg_buf[0x30]; @@ -88,18 +216,17 @@ ULONG AhciFindAdapter( abar = NULL; if (ConfigInfo->NumberOfAccessRanges > 0) { - ULONG accessIndex; - for (accessIndex = 0; accessIndex < ConfigInfo->NumberOfAccessRanges; accessIndex++) + for (index = 0; index < ConfigInfo->NumberOfAccessRanges; index++) { - if ((*(ConfigInfo->AccessRanges))[accessIndex].RangeStart.QuadPart == adapterExtension->AhciBaseAddress) + if ((*(ConfigInfo->AccessRanges))[index].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); + (*(ConfigInfo->AccessRanges))[index].RangeStart, + (*(ConfigInfo->AccessRanges))[index].RangeLength, + (BOOLEAN)!(*(ConfigInfo->AccessRanges))[index].RangeInMemory); break; } } @@ -115,6 +242,7 @@ ULONG AhciFindAdapter( // 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 = StorPortReadRegisterUlong(adapterExtension, &abar->GHC); // AE := Highest Significant bit of GHC if ((ghc & (0x1<<31)) == 1)//Hmm, controller was already in power state @@ -134,15 +262,6 @@ ULONG AhciFindAdapter( 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; @@ -152,12 +271,20 @@ ULONG AhciFindAdapter( ConfigInfo->SynchronizationModel = StorSynchronizeFullDuplex; ConfigInfo->ScatterGather = TRUE; + // allocate necessary resource for each port + if (!AhciAllocateResourceForAdapter(adapterExtension, ConfigInfo)) + return SP_RETURN_ERROR; + + for (index = 0; index < 32; index++) + { + if ((adapterExtension->PortImplemented & (1<PortExtension[index]); + } + // Turn IE -- Interrupt Enabled ghc |= 0x2; StorPortWriteRegisterUlong(adapterExtension, &abar->GHC, ghc); - - return SP_RETURN_FOUND; }// -- AhciFindAdapter(); @@ -184,8 +311,7 @@ ULONG DriverEntry( DebugPrint("Storahci -> DriverEntry()\n"); // initialize the hardware data structure - for (i = 0; i < sizeof(HW_INITIALIZATION_DATA); i++) - ((PUCHAR)&hwInitializationData)[i] = 0; + AhciZeroMemory((PCHAR)&hwInitializationData, sizeof(HW_INITIALIZATION_DATA)); // set size of hardware initialization structure hwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA); @@ -261,3 +387,21 @@ BOOLEAN AhciAdapterReset( return TRUE; }// -- AhciAdapterReset(); + +/** + * @name AhciZeroMemory + * @implemented + * + * Clear buffer by filling zeros + * + * @param buffer + */ +VOID AhciZeroMemory( + __in PCHAR buffer, + __in ULONG bufferSize +) +{ + ULONG i; + for (i = 0; i < bufferSize; i++) + buffer[i] = 0; +}// -- AhciZeroMemory(); diff --git a/drivers/storage/storahci/storahci.h b/drivers/storage/storahci/storahci.h index 79030c578f0..3413703d928 100644 --- a/drivers/storage/storahci/storahci.h +++ b/drivers/storage/storahci/storahci.h @@ -1,6 +1,131 @@ +/* + * 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 "miniport.h" #include "storport.h" +#define AHCI_POOL_TAG 'ahci' + +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; //0x5F + UCHAR Reserved1 :5; + UCHAR D :1; // 1 is write (device to host) + 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; // 0x34 + 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; //0xA1 + + 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; + +// 4.2.2 +typedef struct _AHCI_COMMAND_HEADER +{ + ULONG HEADER_DESCRIPTION; // DW 0 + ULONG PRDBC; // DW 1 + ULONG CTBA0; // DW 2 + ULONG CTBA_U0; // DW 3 + ULONG Reserved[4]; // DW 4-7 +} AHCI_COMMAND_HEADER, *PAHCI_COMMAND_HEADER; + +// Received FIS +typedef struct _AHCI_RECEIVED_FIS +{ + AHCI_FIS_DMA_SETUP DmaSetupFIS; // 0x00 -- DMA Setup FIS + ULONG pad0; // 4 BYTE padding + AHCI_PIO_SETUP_FIS PioSetupFIS; // 0x20 -- PIO Setup FIS + ULONG pad1[3]; // 12 BYTE padding + AHCI_D2H_REGISTER_FIS RegisterFIS; // 0x40 -- Register – Device to Host FIS + ULONG pad2; // 4 BYTE padding + AHCI_SET_DEVICE_BITS_FIS SetDeviceFIS; // 0x58 -- Set Device Bit FIS + ULONG UnknowFIS[16]; // 0x60 -- Unknown FIS + ULONG Reserved[24]; // 0xA0 -- Reserved +} AHCI_RECEIVED_FIS, *PAHCI_RECEIVED_FIS; + typedef struct _AHCI_PORT { ULONG CLB; // 0x00, command list base address, 1K-byte aligned @@ -22,7 +147,7 @@ typedef struct _AHCI_PORT ULONG FBS; // 0x40, FIS-based switch control ULONG RSV1[11]; // 0x44 ~ 0x6F, Reserved ULONG Vendor[4]; // 0x70 ~ 0x7F, vendor specific -} AHCI_PORT; +} AHCI_PORT, *PAHCI_PORT; typedef struct _AHCI_MEMORY_REGISTERS { @@ -49,6 +174,17 @@ typedef struct _AHCI_MEMORY_REGISTERS } AHCI_MEMORY_REGISTERS, *PAHCI_MEMORY_REGISTERS; +struct _AHCI_ADAPTER_EXTENSION; + +typedef struct _AHCI_PORT_EXTENSION +{ + ULONG PortNumber; + struct _AHCI_ADAPTER_EXTENSION* AdapterExtension; + PAHCI_COMMAND_HEADER CommandList; + PAHCI_RECEIVED_FIS ReceivedFIS; + PAHCI_PORT Port; +} AHCI_PORT_EXTENSION, *PAHCI_PORT_EXTENSION; + typedef struct _AHCI_ADAPTER_EXTENSION { ULONG AdapterNumber; @@ -65,7 +201,11 @@ typedef struct _AHCI_ADAPTER_EXTENSION ULONG Version; ULONG CAP; ULONG CAP2; + + PVOID NonCachedExtension; + PAHCI_MEMORY_REGISTERS ABAR_Address; + PAHCI_PORT_EXTENSION PortExtension[32]; } AHCI_ADAPTER_EXTENSION, *PAHCI_ADAPTER_EXTENSION; typedef struct _AHCI_SRB_EXTENSION -- 2.17.1