Debugging Port Device Status Check

svn path=/branches/GSoC_2016/AHCI/; revision=71809
This commit is contained in:
Aman Priyadarshi 2016-07-04 19:01:07 +00:00
parent 68e6647b7f
commit b6081b04fc
2 changed files with 216 additions and 29 deletions

View file

@ -23,6 +23,7 @@ AhciPortInitialize (
__in PAHCI_PORT_EXTENSION PortExtension
)
{
AHCI_PORT_CMD cmd;
ULONG mappedLength, portNumber;
PAHCI_MEMORY_REGISTERS abar;
PAHCI_ADAPTER_EXTENSION adapterExtension;
@ -61,6 +62,23 @@ AhciPortInitialize (
return FALSE;
}
// Ensure that the controller is not in the running state by reading and examining each
// implemented ports PxCMD register. If PxCMD.ST, PxCMD.CR, PxCMD.FRE and
// PxCMD.FR are all cleared, the port is in an idle state. Otherwise, the port is not idle and
// should be placed in the idle state prior to manipulating HBA and port specific registers.
// System software places a port into the idle state by clearing PxCMD.ST and waiting for
// PxCMD.CR to return 0 when read. Software should wait at least 500 milliseconds for
// this to occur. If PxCMD.FRE is set to 1, software should clear it to 0 and wait at least
// 500 milliseconds for PxCMD.FR to return 0 when read. If PxCMD.CR or PxCMD.FR do
// not clear to 0 correctly, then software may attempt a port reset or a full HBA reset to recove
// TODO: Check if port is in idle state or not, if not then restart port
cmd.Status = StorPortReadRegisterUlong(adapterExtension, &PortExtension->Port->CMD);
if ((cmd.FR != 0) || (cmd.CR != 0) || (cmd.FRE != 0) || (cmd.ST != 0))
{
DebugPrint("\tPort is not idle: %x\n", cmd);
}
// 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)
@ -82,15 +100,13 @@ AhciPortInitialize (
PortExtension->IdentifyDeviceData,
&mappedLength);
NT_ASSERT(mappedLength == sizeof(IDENTIFY_DEVICE_DATA));
// set device power state flag to D0
PortExtension->DevicePowerState = StorPowerDeviceD0;
// clear pending interrupts
StorPortWriteRegisterUlong(adapterExtension, &PortExtension->Port->SERR, (ULONG)-1);
StorPortWriteRegisterUlong(adapterExtension, &PortExtension->Port->IS, (ULONG)-1);
StorPortWriteRegisterUlong(adapterExtension, PortExtension->AdapterExtension->IS, (1 << PortExtension->PortNumber));
StorPortWriteRegisterUlong(adapterExtension, &PortExtension->Port->SERR, (ULONG)~0);
StorPortWriteRegisterUlong(adapterExtension, &PortExtension->Port->IS, (ULONG)~0);
StorPortWriteRegisterUlong(adapterExtension, adapterExtension->IS, (1 << PortExtension->PortNumber));
return TRUE;
}// -- AhciPortInitialize();
@ -113,7 +129,6 @@ AhciAllocateResourceForAdapter (
__in PPORT_CONFIGURATION_INFORMATION ConfigInfo
)
{
PVOID portsExtension = NULL;
PCHAR nonCachedExtension, tmp;
ULONG status, index, NCS, AlignedNCS;
ULONG portCount, portImplemented, nonCachedExtensionSize;
@ -177,6 +192,92 @@ AhciAllocateResourceForAdapter (
return TRUE;
}// -- AhciAllocateResourceForAdapter();
/**
* @name AhciStartPort
* @implemented
*
* Try to start the port device
*
* @param AdapterExtension
* @param PortExtension
*
*/
BOOLEAN
AhciStartPort (
__in PAHCI_PORT_EXTENSION PortExtension
)
{
ULONG index;
AHCI_PORT_CMD cmd;
AHCI_SERIAL_ATA_STATUS ssts;
AHCI_SERIAL_ATA_CONTROL sctl;
PAHCI_ADAPTER_EXTENSION AdapterExtension;
DebugPrint("AhciStartPort()\n");
AdapterExtension = PortExtension->AdapterExtension;
cmd.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->CMD);
if ((cmd.FR == 1) && (cmd.CR == 1) && (cmd.FRE == 1) && (cmd.ST == 1))
{
// Already Running
return TRUE;
}
cmd.SUD = 1;
StorPortWriteRegisterUlong(AdapterExtension, &PortExtension->Port->CMD, cmd.Status);
if (((cmd.FR == 1) && (cmd.FRE == 0)) ||
((cmd.CR == 1) && (cmd.ST == 0)))
{
DebugPrint("\tCOMRESET\n");
// perform COMRESET
// section 10.4.2
// Software causes a port reset (COMRESET) by writing 1h to the PxSCTL.DET field to invoke a
// COMRESET on the interface and start a re-establishment of Phy layer communications. Software shall
// wait at least 1 millisecond before clearing PxSCTL.DET to 0h; this ensures that at least one COMRESET
// signal is sent over the interface. After clearing PxSCTL.DET to 0h, software should wait for
// communication to be re-established as indicated by PxSSTS.DET being set to 3h. Then software should
// write all 1s to the PxSERR register to clear any bits that were set as part of the port reset.
sctl.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->SCTL);
sctl.DET = 1;
StorPortWriteRegisterUlong(AdapterExtension, &PortExtension->Port->SCTL, sctl.Status);
StorPortStallExecution(1000);
sctl.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->SCTL);
sctl.DET = 0;
StorPortWriteRegisterUlong(AdapterExtension, &PortExtension->Port->SCTL, sctl.Status);
// Poll DET to verify if a device is attached to the port
index = 0;
do
{
StorPortStallExecution(1000);
ssts.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->SSTS);
index++;
if (ssts.DET != 0)
{
break;
}
}
while(index < 30);
}
ssts.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->SSTS);
if (ssts.DET == 0x4)
{
// no device found
return FALSE;
}
DebugPrint("\tDET: %d %x %x\n", ssts.DET, PortExtension->Port->CMD, PortExtension->Port->SSTS);
return FALSE;
}// -- AhciStartPort();
/**
* @name AhciHwInitialize
* @implemented
@ -193,8 +294,10 @@ AhciHwInitialize (
__in PVOID AdapterExtension
)
{
ULONG ghc, messageCount, status;
ULONG ghc, messageCount, status, cmd, index;
PAHCI_PORT_EXTENSION PortExtension;
PAHCI_ADAPTER_EXTENSION adapterExtension;
AHCI_SERIAL_ATA_STATUS ssts;
DebugPrint("AhciHwInitialize()\n");
@ -214,6 +317,19 @@ AhciHwInitialize (
DebugPrint("\tMultiple MSI based message not supported\n");
}
for (index = 0; index < adapterExtension->PortCount; index++)
{
if ((adapterExtension->PortImplemented & (0x1 << index)) != 0)
{
PortExtension = &adapterExtension->PortExtension[index];
PortExtension->IsActive = AhciStartPort(PortExtension);
if (PortExtension->IsActive == FALSE)
{
DebugPrint("\tPort Disabled: %d\n", index);
}
}
}
return TRUE;
}// -- AhciHwInitialize();
@ -251,7 +367,7 @@ AhciCompleteIssuedSrb (
{
if (((1 << i) & CommandsToComplete) != 0)
{
Srb = &PortExtension->Slot[i];
Srb = PortExtension->Slot[i];
NT_ASSERT(Srb != NULL);
if (Srb->SrbStatus == SRB_STATUS_PENDING)
@ -417,12 +533,16 @@ AhciHwInterrupt(
NT_ASSERT(IsPortValid(AdapterExtension, nextPort));
if ((nextPort == AdapterExtension->LastInterruptPort) ||
(AdapterExtension->PortExtension[nextPort].IsActive == FALSE))
if (nextPort == AdapterExtension->LastInterruptPort)
{
return FALSE;
}
if (AdapterExtension->PortExtension[nextPort].IsActive == FALSE)
{
continue;
}
// we can assign this interrupt to this port
AdapterExtension->LastInterruptPort = nextPort;
AhciInterruptHandler(&AdapterExtension->PortExtension[nextPort]);
@ -722,6 +842,7 @@ AhciHwFindAdapter (
}
ghc = AHCI_Global_HBA_CONTROL_AE;// only AE=1
// tell the controller that we know about AHCI
StorPortWriteRegisterUlong(adapterExtension, &abar->GHC, ghc);
adapterExtension->IS = &abar->IS;
@ -742,10 +863,6 @@ AhciHwFindAdapter (
ConfigInfo->SynchronizationModel = StorSynchronizeFullDuplex;
ConfigInfo->ScatterGather = TRUE;
// Turn IE -- Interrupt Enabled
ghc |= AHCI_Global_HBA_CONTROL_IE;
StorPortWriteRegisterUlong(adapterExtension, &abar->GHC, ghc);
// allocate necessary resource for each port
if (!AhciAllocateResourceForAdapter(adapterExtension, ConfigInfo))
{
@ -759,6 +876,11 @@ AhciHwFindAdapter (
AhciPortInitialize(&adapterExtension->PortExtension[index]);
}
// Turn IE -- Interrupt Enabled
ghc = StorPortReadRegisterUlong(adapterExtension, &abar->GHC);
ghc |= AHCI_Global_HBA_CONTROL_IE;
StorPortWriteRegisterUlong(adapterExtension, &abar->GHC, ghc);
return SP_RETURN_FOUND;
}// -- AhciHwFindAdapter();
@ -818,7 +940,7 @@ DriverEntry (
&hwInitializationData,
NULL);
DebugPrint("\tstatus:%x\n", status);
DebugPrint("\tstatus: %x\n", status);
return status;
}// -- DriverEntry();
@ -1043,7 +1165,7 @@ AhciProcessSrb (
// mark this slot
PortExtension->Slot[SlotIndex] = Srb;
PortExtension->QueueSlots |= SlotIndex;
PortExtension->QueueSlots |= 1 << SlotIndex;
return;
}// -- AhciProcessSrb();
@ -1061,7 +1183,8 @@ AhciActivatePort (
__in PAHCI_PORT_EXTENSION PortExtension
)
{
ULONG cmd, QueueSlots, slotToActivate, tmp;
AHCI_PORT_CMD cmd;
ULONG QueueSlots, slotToActivate, tmp;
PAHCI_ADAPTER_EXTENSION AdapterExtension;
DebugPrint("AhciActivatePort()\n");
@ -1074,9 +1197,9 @@ AhciActivatePort (
// section 3.3.14
// Bits in this field shall only be set to 1 by software when PxCMD.ST is set to 1
cmd = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->CMD);
cmd.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->CMD);
if ((cmd&1) == 0) // PxCMD.ST == 0
if (cmd.ST == 0) // PxCMD.ST == 0
return;
// get the lowest set bit
@ -1215,16 +1338,19 @@ InquiryCompletion (
{
if (SrbExtension->CommandReg == IDE_COMMAND_IDENTIFY)
{
DebugPrint("Device: ATA\n");
AdapterExtension->DeviceParams.DeviceType = AHCI_DEVICE_TYPE_ATA;
}
else
{
DebugPrint("Device: ATAPI\n");
AdapterExtension->DeviceParams.DeviceType = AHCI_DEVICE_TYPE_ATAPI;
}
// TODO: Set Device Paramters
}
else if (SrbStatus == SRB_STATUS_NO_DEVICE)
{
DebugPrint("Device: No Device\n");
AdapterExtension->DeviceParams.DeviceType = AHCI_DEVICE_TYPE_NODEVICE;
}
else

View file

@ -215,23 +215,84 @@ typedef union _AHCI_COMMAND_HEADER_DESCRIPTION
{
struct
{
ULONG CFL :5; // Command FIS Length
ULONG A :1; // IsATAPI
ULONG W :1; // Write
ULONG P :1; // Prefetchable
ULONG CFL : 5; // Command FIS Length
ULONG A : 1; // IsATAPI
ULONG W : 1; // Write
ULONG P : 1; // Prefetchable
ULONG R :1; // Reset
ULONG B :1; // BIST
ULONG C :1; //Clear Busy upon R_OK
ULONG DW0_Reserved :1;
ULONG PMP :4; //Port Multiplier Port
ULONG R : 1; // Reset
ULONG B : 1; // BIST
ULONG C : 1; //Clear Busy upon R_OK
ULONG DW0_Reserved : 1;
ULONG PMP : 4; //Port Multiplier Port
ULONG PRDTL :16; //Physical Region Descriptor Table Length
ULONG PRDTL : 16; //Physical Region Descriptor Table Length
};
ULONG Status;
} AHCI_COMMAND_HEADER_DESCRIPTION;
// section 3.3.7
typedef union _AHCI_PORT_CMD
{
struct
{
ULONG ST : 1;
ULONG SUD : 1;
ULONG POD : 1;
ULONG CLO : 1;
ULONG FRE : 1;
ULONG RSV0 : 3;
ULONG CCS : 5;
ULONG MPSS : 1;
ULONG FR : 1;
ULONG CR : 1;
ULONG CPS : 1;
ULONG PMA : 1;
ULONG HPCP : 1;
ULONG MPSP : 1;
ULONG CPD : 1;
ULONG ESP : 1;
ULONG FBSCP : 1;
ULONG APSTE : 1;
ULONG ATAPI : 1;
ULONG DLAE : 1;
ULONG ALPE : 1;
ULONG ASP : 1;
ULONG ICC : 4;
};
ULONG Status;
} AHCI_PORT_CMD;
typedef union _AHCI_SERIAL_ATA_CONTROL
{
struct
{
ULONG DET :4;
ULONG SPD :4;
ULONG IPM :4;
ULONG SPM :4;
ULONG PMP :4;
ULONG DW11_Reserved :12;
};
ULONG Status;
} AHCI_SERIAL_ATA_CONTROL;
typedef union _AHCI_SERIAL_ATA_STATUS
{
struct
{
ULONG DET :4;
ULONG SPD :4;
ULONG IPM :4;
ULONG RSV0 :20;
};
ULONG Status;
} AHCI_SERIAL_ATA_STATUS;
typedef struct _AHCI_PRDT
{
ULONG DBA;