Author: apriyadarshi Date: Tue Jul 5 16:51:17 2016 New Revision: 71822
URL: http://svn.reactos.org/svn/reactos?rev=71822&view=rev Log: - Handled DET = 03h case. - Registered (Interrupt enable and SERR clear) working port. Everything is working now! :D
Modified: branches/GSoC_2016/AHCI/drivers/storage/storahci/storahci.c branches/GSoC_2016/AHCI/drivers/storage/storahci/storahci.h
Modified: branches/GSoC_2016/AHCI/drivers/storage/storahci/storahci.c URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2016/AHCI/drivers/storage/s... ============================================================================== --- branches/GSoC_2016/AHCI/drivers/storage/storahci/storahci.c [iso-8859-1] (original) +++ branches/GSoC_2016/AHCI/drivers/storage/storahci/storahci.c [iso-8859-1] Tue Jul 5 16:51:17 2016 @@ -209,6 +209,8 @@ { 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 @@ }
ssts.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->SSTS); - if (ssts.DET == 0x4) - { - // no device found - return FALSE; - } - - DebugPrint("\tDET: %d %d\n", ssts.DET, cmd.ST); + switch (ssts.DET) + { + 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("\tInvalid DET value: %x\n", ssts.DET); return FALSE; }// -- AhciStartPort();
@@ -322,10 +415,6 @@ { PortExtension = &adapterExtension->PortExtension[index]; PortExtension->IsActive = AhciStartPort(PortExtension); - if (PortExtension->IsActive == FALSE) - { - DebugPrint("\tPort Disabled: %d\n", index); - } } }
@@ -516,6 +605,7 @@ 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 @@ cmd.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->CMD);
if (cmd.ST == 0) // PxCMD.ST == 0 + { return; + }
// get the lowest set bit tmp = QueueSlots & (QueueSlots - 1); @@ -1223,6 +1315,8 @@ // mark this CommandIssuedSlots // 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);
Modified: branches/GSoC_2016/AHCI/drivers/storage/storahci/storahci.h URL: http://svn.reactos.org/svn/reactos/branches/GSoC_2016/AHCI/drivers/storage/s... ============================================================================== --- branches/GSoC_2016/AHCI/drivers/storage/storahci/storahci.h [iso-8859-1] (original) +++ branches/GSoC_2016/AHCI/drivers/storage/storahci/storahci.h [iso-8859-1] Tue Jul 5 16:51:17 2016 @@ -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 @@ 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 @@ 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 @@ 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 @@ 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);