- Handled DET = 03h case.
authorAman Priyadarshi <aman.eureka@gmail.com>
Tue, 5 Jul 2016 16:51:17 +0000 (16:51 +0000)
committerAman Priyadarshi <aman.eureka@gmail.com>
Tue, 5 Jul 2016 16:51:17 +0000 (16:51 +0000)
- Registered (Interrupt enable and SERR clear) working port.
Everything is working now! :D

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

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

index b262a4e..5f81b4a 100644 (file)
@@ -209,6 +209,8 @@ AhciStartPort (
 {
     ULONG index;
     AHCI_PORT_CMD cmd;
+    AHCI_TASK_FILE_DATA tfd;
+    AHCI_INTERRUPT_ENABLE ie;
     AHCI_SERIAL_ATA_STATUS ssts;
     AHCI_SERIAL_ATA_CONTROL sctl;
     PAHCI_ADAPTER_EXTENSION AdapterExtension;
@@ -268,13 +270,104 @@ AhciStartPort (
     }
 
     ssts.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->SSTS);
-    if (ssts.DET == 0x4)
+    switch (ssts.DET)
     {
-        // no device found
-        return FALSE;
+        case 0x0:
+        case 0x1:
+        case 0x2:
+        default:
+            // unhandled case
+            DebugPrint("\tDET == %x Unsupported\n", ssts.DET);
+            return FALSE;
+        case 0x3:
+            {
+                NT_ASSERT(cmd.ST == 0);
+
+                // make sure FIS Recieve is enabled (cmd.FRE)
+                index = 0;
+                do
+                {
+                    StorPortStallExecution(10000);
+                    cmd.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->CMD);
+                    cmd.FRE = 1;
+                    StorPortWriteRegisterUlong(AdapterExtension, &PortExtension->Port->CMD, cmd.Status);
+                    index++;
+                }
+                while((cmd.FR != 1) && (index < 3));
+
+                if (cmd.FR != 1)
+                {
+                    // failed to start FIS DMA engine
+                    // it can crash the driver later
+                    return FALSE;
+                }
+
+                // start port channel
+                // set cmd.ST
+
+                NT_ASSERT(cmd.FRE == 1);
+                NT_ASSERT(cmd.CR == 0);
+
+                // why assert? well If we face such condition on DET = 0x3
+                // then we don't have port in idle state and hence before executing this part of code
+                // we must have restarted it.
+                tfd.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->TFD);
+
+                if ((tfd.STS.BSY) || (tfd.STS.DRQ))
+                {
+                    DebugPrint("\tUnhandled Case BSY-DRQ\n");
+                }
+
+                // clear pending interrupts
+                StorPortWriteRegisterUlong(AdapterExtension, &PortExtension->Port->SERR, (ULONG)~0);
+                StorPortWriteRegisterUlong(AdapterExtension, &PortExtension->Port->IS, (ULONG)~0);
+                StorPortWriteRegisterUlong(AdapterExtension, AdapterExtension->IS, (1 << PortExtension->PortNumber));
+
+                // set IE
+                ie.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->IE);
+                ie.DHRE = 1;
+                ie.PSE = 1;
+                ie.DSE = 1;
+                ie.SDBE = 1;
+
+                ie.UFE = 0;
+                ie.DPE = 0;
+                ie.PCE = 1;
+
+                ie.DMPE = 0;
+
+                ie.PRCE = 1;
+                ie.IPME = 0;
+                ie.OFE = 1;
+                ie.INFE = 1;
+                ie.IFE = 1;
+                ie.HBDE = 1;
+                ie.HBFE = 1;
+                ie.TFEE = 1;
+
+                cmd.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->CMD);
+                ie.CPDE = cmd.CPD;
+
+                StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->IE, ie.Status);
+
+                cmd.ST = 1;
+                StorPortWriteRegisterUlong(AdapterExtension, &PortExtension->Port->CMD, cmd.Status);
+                cmd.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->CMD);
+
+                if (cmd.ST != 1)
+                {
+                    DebugPrint("\tFailed to start Port\n");
+                    return FALSE;
+                }
+
+                return TRUE;
+            }
+        case 0x4:
+            // no device found
+            return FALSE;
     }
 
-    DebugPrint("\tDET: %d %d\n", ssts.DET, cmd.ST);
+    DebugPrint("\tInvalid DET value: %x\n", ssts.DET);
     return FALSE;
 }// -- AhciStartPort();
 
@@ -322,10 +415,6 @@ AhciHwInitialize (
         {
             PortExtension = &adapterExtension->PortExtension[index];
             PortExtension->IsActive = AhciStartPort(PortExtension);
-            if (PortExtension->IsActive == FALSE)
-            {
-                DebugPrint("\tPort Disabled: %d\n", index);
-            }
         }
     }
 
@@ -516,6 +605,7 @@ AhciHwInterrupt(
     portPending = StorPortReadRegisterUlong(AdapterExtension, AdapterExtension->IS);
     // we process interrupt for implemented ports only
     portCount = AdapterExtension->PortCount;
+    DebugPrint("\tPortPending: %d\n", portPending);
     portPending = portPending & AdapterExtension->PortImplemented;
 
     if (portPending == 0)
@@ -1207,7 +1297,9 @@ AhciActivatePort (
     cmd.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->CMD);
 
     if (cmd.ST == 0) // PxCMD.ST == 0
+    {
         return;
+    }
 
     // get the lowest set bit
     tmp = QueueSlots & (QueueSlots - 1);
@@ -1224,6 +1316,8 @@ AhciActivatePort (
     // to validate in completeIssuedCommand
     PortExtension->CommandIssuedSlots |= slotToActivate;
 
+    DebugPrint("\tslotToActivate: %d\n", slotToActivate);
+
     // tell the HBA to issue this Command Slot to the given port
     StorPortWriteRegisterUlong(AdapterExtension, &PortExtension->Port->CI, slotToActivate);
 
index 97144ad..2e73678 100644 (file)
@@ -66,7 +66,7 @@
 #define AHCI_Global_Port_CAP_NCS(x)            (((x) & 0xF00) >> 8)
 
 #define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
-#if DEBUG
+#ifdef DBG
     #define DebugPrint(format, ...) StorPortDebugPrint(0, format, __VA_ARGS__)
 #endif
 
@@ -295,6 +295,25 @@ typedef union _AHCI_SERIAL_ATA_STATUS
     ULONG Status;
 }  AHCI_SERIAL_ATA_STATUS;
 
+typedef union _AHCI_TASK_FILE_DATA
+{
+    struct
+    {
+        struct _STS
+        {
+            UCHAR ERR : 1;
+            UCHAR CS1 : 2;
+            UCHAR DRQ : 1;
+            UCHAR CS2 : 3;
+            UCHAR BSY : 1;
+        } STS;
+        UCHAR ERR;
+        USHORT RSV;
+    };
+
+    ULONG Status;
+} AHCI_TASK_FILE_DATA;
+
 typedef struct _AHCI_PRDT
 {
     ULONG DBA;
@@ -365,27 +384,32 @@ typedef struct _AHCI_PORT
     ULONG   Vendor[4];                          // 0x70 ~ 0x7F, vendor specific
 } AHCI_PORT, *PAHCI_PORT;
 
-#ifdef DEBUG
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, CLB) == 0x00);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, CLBU) == 0x04);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, FB) == 0x08);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, FBU) == 0x0C);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, IS) == 0x10);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, IE) == 0x14);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, CMD) == 0x18);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, RSV0) == 0x1C);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, TFD) == 0x20);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, SIG) == 0x24);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, SSTS) == 0x28);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, SCTL) == 0x2C);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, SERR) == 0x30);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, SACT) == 0x34);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, CI) == 0x38);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, SNTF) == 0x3C);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, FBS) == 0x40);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, RSV1) == 0x44);
-    C_ASSERT(FIELD_OFFSET(AHCI_PORT, Vendor) == 0x70);
-#endif
+typedef struct _AHCI_INTERRUPT_ENABLE
+{
+    struct
+    {
+        ULONG DHRE :1;
+        ULONG PSE :1;
+        ULONG DSE :1;
+        ULONG SDBE :1;
+        ULONG UFE :1;
+        ULONG DPE :1;
+        ULONG PCE :1;
+        ULONG DMPE :1;
+        ULONG DW5_Reserved :14;
+        ULONG PRCE :1;
+        ULONG IPME :1;
+        ULONG OFE :1;
+        ULONG DW5_Reserved2 :1;
+        ULONG INFE :1;
+        ULONG IFE :1;
+        ULONG HBDE :1;
+        ULONG HBFE :1;
+        ULONG TFEE :1;
+        ULONG CPDE :1;
+    };
+    ULONG Status;
+} AHCI_INTERRUPT_ENABLE;
 
 typedef struct _AHCI_MEMORY_REGISTERS
 {
@@ -406,22 +430,6 @@ typedef struct _AHCI_MEMORY_REGISTERS
     AHCI_PORT PortList[MAXIMUM_AHCI_PORT_COUNT];
 } AHCI_MEMORY_REGISTERS, *PAHCI_MEMORY_REGISTERS;
 
-#ifdef DEBUG
-    C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, CAP) == 0x00);
-    C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, GHC) == 0x04);
-    C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, IS) == 0x08);
-    C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, PI) == 0x0C);
-    C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, VS) == 0x10);
-    C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, CCC_CTL) == 0x14);
-    C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, CCC_PTS) == 0x18);
-    C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, EM_LOC) == 0x1C);
-    C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, EM_CTL) == 0x20);
-    C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, CAP2) == 0x24);
-    C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, BOHC) == 0x28);
-    C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, Reserved) == 0x2C);
-    C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, VendorSpecific) == 0xA0);
-#endif
-
 // Holds information for each attached attached port to a given adapter.
 typedef struct _AHCI_PORT_EXTENSION
 {
@@ -559,3 +567,42 @@ PAHCI_SRB_EXTENSION
 GetSrbExtension(
     __in PSCSI_REQUEST_BLOCK Srb
     );
+
+//////////////////////////////////////////////////////////////
+//                       Assertions                         //
+//////////////////////////////////////////////////////////////
+
+C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, CAP) == 0x00);
+C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, GHC) == 0x04);
+C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, IS) == 0x08);
+C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, PI) == 0x0C);
+C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, VS) == 0x10);
+C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, CCC_CTL) == 0x14);
+C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, CCC_PTS) == 0x18);
+C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, EM_LOC) == 0x1C);
+C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, EM_CTL) == 0x20);
+C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, CAP2) == 0x24);
+C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, BOHC) == 0x28);
+C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, Reserved) == 0x2C);
+C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, VendorSpecific) == 0xA0);
+C_ASSERT(FIELD_OFFSET(AHCI_MEMORY_REGISTERS, PortList) == 0x100);
+
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, CLB) == 0x00);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, CLBU) == 0x04);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, FB) == 0x08);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, FBU) == 0x0C);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, IS) == 0x10);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, IE) == 0x14);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, CMD) == 0x18);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, RSV0) == 0x1C);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, TFD) == 0x20);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, SIG) == 0x24);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, SSTS) == 0x28);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, SCTL) == 0x2C);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, SERR) == 0x30);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, SACT) == 0x34);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, CI) == 0x38);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, SNTF) == 0x3C);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, FBS) == 0x40);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, RSV1) == 0x44);
+C_ASSERT(FIELD_OFFSET(AHCI_PORT, Vendor) == 0x70);
\ No newline at end of file