AhciFindAdapter Completed
authorAman Priyadarshi <aman.eureka@gmail.com>
Fri, 3 Jun 2016 15:54:21 +0000 (15:54 +0000)
committerAman Priyadarshi <aman.eureka@gmail.com>
Fri, 3 Jun 2016 15:54:21 +0000 (15:54 +0000)
- Added AhciZeroMemory
- Added AhciAllocateResourceForAdapter
- Added AhciPortInitialize

Compile Status : OK

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

drivers/storage/storahci/storahci.c
drivers/storage/storahci/storahci.h

index df7d1b7..6e21584 100644 (file)
@@ -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<<index)) != 0)
+        {
+            adapterExtension->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<<index)) != 0)
+            AhciPortInitialize(adapterExtension->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();
index 79030c5..3413703 100644 (file)
@@ -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