mirror of
https://github.com/reactos/reactos.git
synced 2025-01-06 06:20:13 +00:00
Implemented Dpc Routine, managed Srb functions and some code fixes!
svn path=/branches/GSoC_2016/AHCI/; revision=71969
This commit is contained in:
parent
b86b9221d4
commit
93ea028360
2 changed files with 440 additions and 187 deletions
|
@ -132,6 +132,7 @@ AhciAllocateResourceForAdapter (
|
|||
PCHAR nonCachedExtension, tmp;
|
||||
ULONG index, NCS, AlignedNCS;
|
||||
ULONG portCount, portImplemented, nonCachedExtensionSize;
|
||||
PAHCI_PORT_EXTENSION PortExtension;
|
||||
|
||||
DebugPrint("AhciAllocateResourceForAdapter()\n");
|
||||
|
||||
|
@ -173,18 +174,21 @@ AhciAllocateResourceForAdapter (
|
|||
|
||||
for (index = 0; index < portCount; index++)
|
||||
{
|
||||
AdapterExtension->PortExtension[index].IsActive = FALSE;
|
||||
PortExtension = &AdapterExtension->PortExtension[index];
|
||||
|
||||
PortExtension->DeviceParams.IsActive = FALSE;
|
||||
if ((AdapterExtension->PortImplemented & (1 << index)) != 0)
|
||||
{
|
||||
AdapterExtension->PortExtension[index].PortNumber = index;
|
||||
AdapterExtension->PortExtension[index].IsActive = TRUE;
|
||||
AdapterExtension->PortExtension[index].AdapterExtension = AdapterExtension;
|
||||
AdapterExtension->PortExtension[index].CommandList = (PAHCI_COMMAND_HEADER)nonCachedExtension;
|
||||
PortExtension->PortNumber = index;
|
||||
PortExtension->DeviceParams.IsActive = TRUE;
|
||||
PortExtension->AdapterExtension = AdapterExtension;
|
||||
PortExtension->CommandList = (PAHCI_COMMAND_HEADER)nonCachedExtension;
|
||||
|
||||
tmp = (PCHAR)(nonCachedExtension + sizeof(AHCI_COMMAND_HEADER) * AlignedNCS);
|
||||
|
||||
AdapterExtension->PortExtension[index].ReceivedFIS = (PAHCI_RECEIVED_FIS)tmp;
|
||||
AdapterExtension->PortExtension[index].IdentifyDeviceData = (PIDENTIFY_DEVICE_DATA)(tmp + sizeof(AHCI_RECEIVED_FIS));
|
||||
PortExtension->ReceivedFIS = (PAHCI_RECEIVED_FIS)tmp;
|
||||
PortExtension->IdentifyDeviceData = (PIDENTIFY_DEVICE_DATA)(tmp + sizeof(AHCI_RECEIVED_FIS));
|
||||
PortExtension->MaxPortQueueDepth = NCS;
|
||||
nonCachedExtension += nonCachedExtensionSize;
|
||||
}
|
||||
}
|
||||
|
@ -272,13 +276,6 @@ AhciStartPort (
|
|||
ssts.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->SSTS);
|
||||
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);
|
||||
|
@ -299,6 +296,7 @@ AhciStartPort (
|
|||
{
|
||||
// failed to start FIS DMA engine
|
||||
// it can crash the driver later
|
||||
// so better to turn this port off
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -325,30 +323,51 @@ AhciStartPort (
|
|||
|
||||
// set IE
|
||||
ie.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->IE);
|
||||
/* Device to Host Register FIS Interrupt Enable */
|
||||
ie.DHRE = 1;
|
||||
/* PIO Setup FIS Interrupt Enable */
|
||||
ie.PSE = 1;
|
||||
/* DMA Setup FIS Interrupt Enable */
|
||||
ie.DSE = 1;
|
||||
/* Set Device Bits FIS Interrupt Enable */
|
||||
ie.SDBE = 1;
|
||||
|
||||
/* Unknown FIS Interrupt Enable */
|
||||
ie.UFE = 0;
|
||||
/* Descriptor Processed Interrupt Enable */
|
||||
ie.DPE = 0;
|
||||
/* Port Change Interrupt Enable */
|
||||
ie.PCE = 1;
|
||||
|
||||
/* Device Mechanical Presence Enable */
|
||||
ie.DMPE = 0;
|
||||
|
||||
/* PhyRdy Change Interrupt Enable */
|
||||
ie.PRCE = 1;
|
||||
/* Incorrect Port Multiplier Enable */
|
||||
ie.IPME = 0;
|
||||
/* Overflow Enable */
|
||||
ie.OFE = 1;
|
||||
/* Interface Non-fatal Error Enable */
|
||||
ie.INFE = 1;
|
||||
/* Interface Fatal Error Enable */
|
||||
ie.IFE = 1;
|
||||
/* Host Bus Data Error Enable */
|
||||
ie.HBDE = 1;
|
||||
/* Host Bus Fatal Error Enable */
|
||||
ie.HBFE = 1;
|
||||
/* Task File Error Enable */
|
||||
ie.TFEE = 1;
|
||||
|
||||
cmd.Status = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->CMD);
|
||||
ie.CPDE = cmd.CPD;
|
||||
/* Cold Presence Detect Enable */
|
||||
if (cmd.CPD) // does it support CPD?
|
||||
{
|
||||
// disable it for now
|
||||
ie.CPDE = 0;
|
||||
}
|
||||
|
||||
StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->IE, ie.Status);
|
||||
// should I replace this to single line?
|
||||
// by directly setting ie.Status?
|
||||
|
||||
StorPortWriteRegisterUlong(AdapterExtension, &PortExtension->Port->IE, ie.Status);
|
||||
|
||||
cmd.ST = 1;
|
||||
StorPortWriteRegisterUlong(AdapterExtension, &PortExtension->Port->CMD, cmd.Status);
|
||||
|
@ -362,15 +381,107 @@ AhciStartPort (
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
case 0x4:
|
||||
// no device found
|
||||
default:
|
||||
// unhandled case
|
||||
DebugPrint("\tDET == %x Unsupported\n", ssts.DET);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DebugPrint("\tInvalid DET value: %x\n", ssts.DET);
|
||||
return FALSE;
|
||||
}// -- AhciStartPort();
|
||||
|
||||
/**
|
||||
* @name AhciCommandCompletionDpcRoutine
|
||||
* @implemented
|
||||
*
|
||||
* Handles Completed Commands
|
||||
*
|
||||
* @param Dpc
|
||||
* @param AdapterExtension
|
||||
* @param SystemArgument1
|
||||
* @param SystemArgument2
|
||||
*/
|
||||
VOID
|
||||
AhciCommandCompletionDpcRoutine (
|
||||
__in PSTOR_DPC Dpc,
|
||||
__in PAHCI_ADAPTER_EXTENSION AdapterExtension,
|
||||
__in PAHCI_PORT_EXTENSION PortExtension,
|
||||
__in PVOID SystemArgument2
|
||||
)
|
||||
{
|
||||
PSCSI_REQUEST_BLOCK Srb;
|
||||
STOR_LOCK_HANDLE lockhandle;
|
||||
PAHCI_SRB_EXTENSION SrbExtension;
|
||||
PAHCI_COMPLETION_ROUTINE CompletionRoutine;
|
||||
|
||||
UNREFERENCED_PARAMETER(Dpc);
|
||||
UNREFERENCED_PARAMETER(SystemArgument2);
|
||||
|
||||
DebugPrint("AhciCommandCompletionDpcRoutine()\n");
|
||||
|
||||
AhciZeroMemory(&lockhandle, sizeof(lockhandle));
|
||||
|
||||
StorPortAcquireSpinLock(AdapterExtension, InterruptLock, NULL, &lockhandle);
|
||||
Srb = RemoveQueue(&PortExtension->CompletionQueue);
|
||||
|
||||
NT_ASSERT(Srb != NULL);
|
||||
|
||||
if (Srb->SrbStatus == SRB_STATUS_PENDING)
|
||||
{
|
||||
Srb->SrbStatus = SRB_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SrbExtension = GetSrbExtension(Srb);
|
||||
CompletionRoutine = SrbExtension->CompletionRoutine;
|
||||
|
||||
if (CompletionRoutine != NULL)
|
||||
{
|
||||
// now it's completion routine responsibility to set SrbStatus
|
||||
CompletionRoutine(PortExtension, Srb);
|
||||
}
|
||||
else
|
||||
{
|
||||
Srb->SrbStatus = SRB_STATUS_SUCCESS;
|
||||
StorPortNotification(RequestComplete, AdapterExtension, Srb);
|
||||
}
|
||||
|
||||
StorPortReleaseSpinLock(AdapterExtension, &lockhandle);
|
||||
return;
|
||||
}// -- AhciCommandCompletionDpcRoutine();
|
||||
|
||||
/**
|
||||
* @name AhciHwPassiveInitialize
|
||||
* @implemented
|
||||
*
|
||||
* initializes the HBA and finds all devices that are of interest to the miniport driver. (at PASSIVE LEVEL)
|
||||
*
|
||||
* @param adapterExtension
|
||||
*
|
||||
* @return
|
||||
* return TRUE if intialization was successful
|
||||
*/
|
||||
BOOLEAN
|
||||
AhciHwPassiveInitialize (
|
||||
__in PAHCI_ADAPTER_EXTENSION AdapterExtension
|
||||
)
|
||||
{
|
||||
ULONG index;
|
||||
PAHCI_PORT_EXTENSION PortExtension;
|
||||
|
||||
DebugPrint("AhciHwPassiveInitialize()\n");
|
||||
|
||||
for (index = 0; index < AdapterExtension->PortCount; index++)
|
||||
{
|
||||
if ((AdapterExtension->PortImplemented & (0x1 << index)) != 0)
|
||||
{
|
||||
PortExtension = &AdapterExtension->PortExtension[index];
|
||||
PortExtension->DeviceParams.IsActive = AhciStartPort(PortExtension);
|
||||
StorPortInitializeDpc(AdapterExtension, &PortExtension->CommandCompletion, AhciCommandCompletionDpcRoutine);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}// -- AhciHwPassiveInitialize();
|
||||
|
||||
/**
|
||||
* @name AhciHwInitialize
|
||||
* @implemented
|
||||
|
@ -384,39 +495,30 @@ AhciStartPort (
|
|||
*/
|
||||
BOOLEAN
|
||||
AhciHwInitialize (
|
||||
__in PVOID AdapterExtension
|
||||
__in PAHCI_ADAPTER_EXTENSION AdapterExtension
|
||||
)
|
||||
{
|
||||
ULONG ghc, index;
|
||||
PAHCI_PORT_EXTENSION PortExtension;
|
||||
PAHCI_ADAPTER_EXTENSION adapterExtension;
|
||||
AHCI_GHC ghc;
|
||||
MESSAGE_INTERRUPT_INFORMATION messageInfo;
|
||||
|
||||
DebugPrint("AhciHwInitialize()\n");
|
||||
|
||||
adapterExtension = AdapterExtension;
|
||||
adapterExtension->StateFlags.MessagePerPort = FALSE;
|
||||
AdapterExtension->StateFlags.MessagePerPort = FALSE;
|
||||
|
||||
// First check what type of interrupt/synchronization device is using
|
||||
ghc = StorPortReadRegisterUlong(adapterExtension, &adapterExtension->ABAR_Address->GHC);
|
||||
ghc.Status = StorPortReadRegisterUlong(AdapterExtension, &AdapterExtension->ABAR_Address->GHC);
|
||||
|
||||
// When set to ‘1’ by hardware, indicates that the HBA requested more than one MSI vector
|
||||
// but has reverted to using the first vector only. When this bit is cleared to ‘0’,
|
||||
// the HBA has not reverted to single MSI mode (i.e. hardware is already in single MSI mode,
|
||||
// software has allocated the number of messages requested
|
||||
if ((ghc & AHCI_Global_HBA_CONTROL_MRSM) == 0)
|
||||
if (ghc.MRSM == 0)
|
||||
{
|
||||
adapterExtension->StateFlags.MessagePerPort = TRUE;
|
||||
AdapterExtension->StateFlags.MessagePerPort = TRUE;
|
||||
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);
|
||||
}
|
||||
}
|
||||
StorPortEnablePassiveInitialization(AdapterExtension, AhciHwPassiveInitialize);
|
||||
|
||||
return TRUE;
|
||||
}// -- AhciHwInitialize();
|
||||
|
@ -438,9 +540,7 @@ AhciCompleteIssuedSrb (
|
|||
{
|
||||
ULONG NCS, i;
|
||||
PSCSI_REQUEST_BLOCK Srb;
|
||||
PAHCI_SRB_EXTENSION SrbExtension;
|
||||
PAHCI_ADAPTER_EXTENSION AdapterExtension;
|
||||
PAHCI_COMPLETION_ROUTINE CompletionRoutine;
|
||||
|
||||
DebugPrint("AhciCompleteIssuedSrb()\n");
|
||||
|
||||
|
@ -458,24 +558,8 @@ AhciCompleteIssuedSrb (
|
|||
Srb = PortExtension->Slot[i];
|
||||
NT_ASSERT(Srb != NULL);
|
||||
|
||||
if (Srb->SrbStatus == SRB_STATUS_PENDING)
|
||||
{
|
||||
Srb->SrbStatus = SRB_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
SrbExtension = GetSrbExtension(Srb);
|
||||
CompletionRoutine = SrbExtension->CompletionRoutine;
|
||||
|
||||
if (CompletionRoutine != NULL)
|
||||
{
|
||||
// now it's completion routine responsibility to set SrbStatus
|
||||
CompletionRoutine(AdapterExtension, PortExtension, Srb);
|
||||
}
|
||||
else
|
||||
{
|
||||
Srb->SrbStatus = SRB_STATUS_SUCCESS;
|
||||
StorPortNotification(RequestComplete, AdapterExtension, Srb);
|
||||
}
|
||||
AddQueue(&PortExtension->CompletionQueue, Srb);
|
||||
StorPortIssueDpc(AdapterExtension, &PortExtension->CommandCompletion, PortExtension, Srb);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -589,23 +673,21 @@ AhciInterruptHandler (
|
|||
* return FALSE Indicates the interrupt was not ours.
|
||||
*/
|
||||
BOOLEAN
|
||||
AhciHwInterrupt(
|
||||
AhciHwInterrupt (
|
||||
__in PAHCI_ADAPTER_EXTENSION AdapterExtension
|
||||
)
|
||||
{
|
||||
ULONG portPending, nextPort, i, portCount;
|
||||
|
||||
DebugPrint("AhciHwInterrupt()\n");
|
||||
|
||||
if (AdapterExtension->StateFlags.Removed)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -616,18 +698,12 @@ AhciHwInterrupt(
|
|||
for (i = 1; i <= portCount; i++)
|
||||
{
|
||||
nextPort = (AdapterExtension->LastInterruptPort + i) % portCount;
|
||||
|
||||
if ((portPending & (0x1 << nextPort)) == 0)
|
||||
continue;
|
||||
|
||||
NT_ASSERT(IsPortValid(AdapterExtension, nextPort));
|
||||
|
||||
if (nextPort == AdapterExtension->LastInterruptPort)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (AdapterExtension->PortExtension[nextPort].IsActive == FALSE)
|
||||
if (AdapterExtension->PortExtension[nextPort].DeviceParams.IsActive == FALSE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -636,6 +712,8 @@ AhciHwInterrupt(
|
|||
AdapterExtension->LastInterruptPort = nextPort;
|
||||
AhciInterruptHandler(&AdapterExtension->PortExtension[nextPort]);
|
||||
|
||||
portPending &= ~(1 << nextPort);
|
||||
|
||||
// interrupt belongs to this device
|
||||
// should always return TRUE
|
||||
return TRUE;
|
||||
|
@ -673,6 +751,8 @@ AhciHwStartIo (
|
|||
function = Srb->Function;
|
||||
adapterExtension = AdapterExtension;
|
||||
|
||||
DebugPrint("\tFunction: %x\n", function);
|
||||
|
||||
if (!IsPortValid(adapterExtension, pathId))
|
||||
{
|
||||
Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
|
||||
|
@ -714,6 +794,7 @@ AhciHwStartIo (
|
|||
|
||||
if (function == SRB_FUNCTION_EXECUTE_SCSI)
|
||||
{
|
||||
DebugPrint("\tSRB_FUNCTION_EXECUTE_SCSI\n");
|
||||
// https://msdn.microsoft.com/en-us/windows/hardware/drivers/storage/handling-srb-function-execute-scsi
|
||||
// On receipt of an SRB_FUNCTION_EXECUTE_SCSI request, a miniport driver's HwScsiStartIo
|
||||
// routine does the following:
|
||||
|
@ -732,13 +813,22 @@ AhciHwStartIo (
|
|||
if (Srb->CdbLength > 0)
|
||||
{
|
||||
PCDB cdb = (PCDB)&Srb->Cdb;
|
||||
if (cdb->CDB10.OperationCode == SCSIOP_INQUIRY)
|
||||
NT_ASSERT(cdb != NULL);
|
||||
|
||||
switch(cdb->CDB10.OperationCode)
|
||||
{
|
||||
Srb->SrbStatus = DeviceInquiryRequest(adapterExtension, Srb, cdb);
|
||||
}
|
||||
else
|
||||
{
|
||||
Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
|
||||
case SCSIOP_INQUIRY:
|
||||
Srb->SrbStatus = DeviceInquiryRequest(adapterExtension, Srb, cdb, TRUE);
|
||||
break;
|
||||
case SCSIOP_REPORT_LUNS:
|
||||
Srb->SrbStatus = DeviceInquiryRequest(adapterExtension, Srb, cdb, FALSE);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
DebugPrint("\tOperationCode: %d\n", cdb->CDB10.OperationCode);
|
||||
Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -751,7 +841,7 @@ AhciHwStartIo (
|
|||
}
|
||||
|
||||
DebugPrint("\tUnknown function code recieved: %x\n", function);
|
||||
Srb->SrbStatus = SRB_STATUS_BAD_FUNCTION;
|
||||
Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
|
||||
StorPortNotification(RequestComplete, adapterExtension, Srb);
|
||||
return TRUE;
|
||||
}// -- AhciHwStartIo();
|
||||
|
@ -839,9 +929,10 @@ AhciHwFindAdapter (
|
|||
__in PBOOLEAN Reserved3
|
||||
)
|
||||
{
|
||||
ULONG ghc, index, pci_cfg_len;
|
||||
UCHAR pci_cfg_buf[sizeof(PCI_COMMON_CONFIG)];
|
||||
AHCI_GHC ghc;
|
||||
ULONG index, pci_cfg_len;
|
||||
PACCESS_RANGE accessRange;
|
||||
UCHAR pci_cfg_buf[sizeof(PCI_COMMON_CONFIG)];
|
||||
|
||||
PAHCI_MEMORY_REGISTERS abar;
|
||||
PPCI_COMMON_CONFIG pciConfigData;
|
||||
|
@ -919,9 +1010,9 @@ AhciHwFindAdapter (
|
|||
// 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);
|
||||
ghc.Status = StorPortReadRegisterUlong(adapterExtension, &abar->GHC);
|
||||
// AE := Highest Significant bit of GHC
|
||||
if ((ghc & AHCI_Global_HBA_CONTROL_AE) != 0)// Hmm, controller was already in power state
|
||||
if (ghc.AE != 0)// Hmm, controller was already in power state
|
||||
{
|
||||
// reset controller to have it in known state
|
||||
DebugPrint("\tAE Already set, Reset()\n");
|
||||
|
@ -932,9 +1023,10 @@ AhciHwFindAdapter (
|
|||
}
|
||||
}
|
||||
|
||||
ghc = AHCI_Global_HBA_CONTROL_AE;// only AE=1
|
||||
ghc.Status = 0;
|
||||
ghc.AE = 1;// only AE=1
|
||||
// tell the controller that we know about AHCI
|
||||
StorPortWriteRegisterUlong(adapterExtension, &abar->GHC, ghc);
|
||||
StorPortWriteRegisterUlong(adapterExtension, &abar->GHC, ghc.Status);
|
||||
|
||||
adapterExtension->IS = &abar->IS;
|
||||
adapterExtension->PortImplemented = StorPortReadRegisterUlong(adapterExtension, &abar->PI);
|
||||
|
@ -954,6 +1046,11 @@ AhciHwFindAdapter (
|
|||
ConfigInfo->SynchronizationModel = StorSynchronizeFullDuplex;
|
||||
ConfigInfo->ScatterGather = TRUE;
|
||||
|
||||
// Turn IE -- Interrupt Enabled
|
||||
ghc.Status = StorPortReadRegisterUlong(adapterExtension, &abar->GHC);
|
||||
ghc.IE = 1;
|
||||
StorPortWriteRegisterUlong(adapterExtension, &abar->GHC, ghc.Status);
|
||||
|
||||
// allocate necessary resource for each port
|
||||
if (!AhciAllocateResourceForAdapter(adapterExtension, ConfigInfo))
|
||||
{
|
||||
|
@ -967,11 +1064,6 @@ 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();
|
||||
|
||||
|
@ -1044,8 +1136,10 @@ DriverEntry (
|
|||
* @param PortExtension
|
||||
* @param Srb
|
||||
*
|
||||
* @return
|
||||
* Number of CFIS fields used in DWORD
|
||||
*/
|
||||
VOID
|
||||
ULONG
|
||||
AhciATA_CFIS (
|
||||
__in PAHCI_PORT_EXTENSION PortExtension,
|
||||
__in PAHCI_SRB_EXTENSION SrbExtension
|
||||
|
@ -1059,12 +1153,10 @@ AhciATA_CFIS (
|
|||
|
||||
cmdTable = (PAHCI_COMMAND_TABLE)SrbExtension;
|
||||
|
||||
NT_ASSERT(sizeof(cmdTable->CFIS) == 64);
|
||||
|
||||
AhciZeroMemory(&cmdTable->CFIS, sizeof(cmdTable->CFIS));
|
||||
|
||||
cmdTable->CFIS[AHCI_ATA_CFIS_FisType] = 0x27; // FIS Type
|
||||
cmdTable->CFIS[AHCI_ATA_CFIS_PMPort_C] = (1 << 7); // PM Port & C
|
||||
cmdTable->CFIS[AHCI_ATA_CFIS_FisType] = FIS_TYPE_REG_H2D; // FIS Type
|
||||
cmdTable->CFIS[AHCI_ATA_CFIS_PMPort_C] = (1 << 7); // PM Port & C
|
||||
cmdTable->CFIS[AHCI_ATA_CFIS_CommandReg] = SrbExtension->CommandReg;
|
||||
|
||||
cmdTable->CFIS[AHCI_ATA_CFIS_FeaturesLow] = SrbExtension->FeaturesLow;
|
||||
|
@ -1079,7 +1171,7 @@ AhciATA_CFIS (
|
|||
cmdTable->CFIS[AHCI_ATA_CFIS_SectorCountLow] = SrbExtension->SectorCountLow;
|
||||
cmdTable->CFIS[AHCI_ATA_CFIS_SectorCountHigh] = SrbExtension->SectorCountHigh;
|
||||
|
||||
return;
|
||||
return 5;
|
||||
}// -- AhciATA_CFIS();
|
||||
|
||||
/**
|
||||
|
@ -1091,8 +1183,10 @@ AhciATA_CFIS (
|
|||
* @param PortExtension
|
||||
* @param Srb
|
||||
*
|
||||
* @return
|
||||
* Number of CFIS fields used in DWORD
|
||||
*/
|
||||
VOID
|
||||
ULONG
|
||||
AhciATAPI_CFIS (
|
||||
__in PAHCI_PORT_EXTENSION PortExtension,
|
||||
__in PAHCI_SRB_EXTENSION SrbExtension
|
||||
|
@ -1103,7 +1197,7 @@ AhciATAPI_CFIS (
|
|||
|
||||
DebugPrint("AhciATAPI_CFIS()\n");
|
||||
|
||||
return;
|
||||
return 2;
|
||||
}// -- AhciATAPI_CFIS();
|
||||
|
||||
/**
|
||||
|
@ -1147,6 +1241,11 @@ AhciBuild_PRDT (
|
|||
{
|
||||
cmdTable->PRDT[index].DBAU = sgl->List[index].PhysicalAddress.HighPart;
|
||||
}
|
||||
|
||||
// Data Byte Count (DBC): A ‘0’ based value that Indicates the length, in bytes, of the data block.
|
||||
// A maximum of length of 4MB may exist for any entry. Bit ‘0’ of this field must always be ‘1’ to
|
||||
// indicate an even byte count. A value of ‘1’ indicates 2 bytes, ‘3’ indicates 4 bytes, etc.
|
||||
cmdTable->PRDT[index].DBC = sgl->List[index].Length - 1;
|
||||
}
|
||||
|
||||
return sgl->NumberOfElements;
|
||||
|
@ -1170,7 +1269,7 @@ AhciProcessSrb (
|
|||
__in ULONG SlotIndex
|
||||
)
|
||||
{
|
||||
ULONG prdtlen, sig, length;
|
||||
ULONG prdtlen, sig, length, cfl;
|
||||
PAHCI_SRB_EXTENSION SrbExtension;
|
||||
PAHCI_COMMAND_HEADER CommandHeader;
|
||||
PAHCI_ADAPTER_EXTENSION AdapterExtension;
|
||||
|
@ -1193,10 +1292,12 @@ AhciProcessSrb (
|
|||
sig = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->SIG);
|
||||
if (sig == 0x101)
|
||||
{
|
||||
DebugPrint("\tATA Device Found!\n");
|
||||
SrbExtension->CommandReg = IDE_COMMAND_IDENTIFY;
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugPrint("\tATAPI Device Found!\n");
|
||||
SrbExtension->CommandReg = IDE_COMMAND_ATAPI_IDENTIFY;
|
||||
}
|
||||
}
|
||||
|
@ -1207,13 +1308,14 @@ AhciProcessSrb (
|
|||
// program the CFIS in the CommandTable
|
||||
CommandHeader = &PortExtension->CommandList[SlotIndex];
|
||||
|
||||
cfl = 0;
|
||||
if (IsAtaCommand(SrbExtension->AtaFunction))
|
||||
{
|
||||
AhciATA_CFIS(PortExtension, SrbExtension);
|
||||
cfl = AhciATA_CFIS(PortExtension, SrbExtension);
|
||||
}
|
||||
else if (IsAtapiCommand(SrbExtension->AtaFunction))
|
||||
{
|
||||
AhciATAPI_CFIS(PortExtension, SrbExtension);
|
||||
cfl = AhciATAPI_CFIS(PortExtension, SrbExtension);
|
||||
}
|
||||
|
||||
prdtlen = 0;
|
||||
|
@ -1225,7 +1327,8 @@ AhciProcessSrb (
|
|||
|
||||
// Program the command header
|
||||
CommandHeader->DI.PRDTL = prdtlen; // number of entries in PRD table
|
||||
CommandHeader->DI.CFL = 5;
|
||||
CommandHeader->DI.CFL = cfl;
|
||||
CommandHeader->DI.A = (SrbExtension->AtaFunction & ATA_FUNCTION_ATAPI_COMMAND) ? 1 : 0;
|
||||
CommandHeader->DI.W = (SrbExtension->Flags & ATA_FLAGS_DATA_OUT) ? 1 : 0;
|
||||
CommandHeader->DI.P = 0; // ATA Specifications says so
|
||||
CommandHeader->DI.PMP = 0; // Port Multiplier
|
||||
|
@ -1243,21 +1346,21 @@ AhciProcessSrb (
|
|||
CommandHeader->Reserved[3] = 0;
|
||||
|
||||
// set CommandHeader CTBA
|
||||
// I am really not sure if SrbExtension is 128 byte aligned or not
|
||||
// Command FIS will not work if it is not so.
|
||||
CommandTablePhysicalAddress = StorPortGetPhysicalAddress(AdapterExtension,
|
||||
NULL,
|
||||
SrbExtension,
|
||||
&length);
|
||||
|
||||
NT_ASSERT(length != 0);
|
||||
|
||||
// command table alignment
|
||||
NT_ASSERT((CommandTablePhysicalAddress.LowPart % 128) == 0);
|
||||
|
||||
CommandHeader->CTBA0 = CommandTablePhysicalAddress.LowPart;
|
||||
CommandHeader->CTBA = CommandTablePhysicalAddress.LowPart;
|
||||
|
||||
if (IsAdapterCAPS64(AdapterExtension->CAP))
|
||||
{
|
||||
CommandHeader->CTBA_U0 = CommandTablePhysicalAddress.HighPart;
|
||||
CommandHeader->CTBA_U = CommandTablePhysicalAddress.HighPart;
|
||||
}
|
||||
|
||||
// mark this slot
|
||||
|
@ -1281,6 +1384,7 @@ AhciActivatePort (
|
|||
)
|
||||
{
|
||||
AHCI_PORT_CMD cmd;
|
||||
ULONG sact, ci;
|
||||
ULONG QueueSlots, slotToActivate, tmp;
|
||||
PAHCI_ADAPTER_EXTENSION AdapterExtension;
|
||||
|
||||
|
@ -1290,7 +1394,9 @@ AhciActivatePort (
|
|||
QueueSlots = PortExtension->QueueSlots;
|
||||
|
||||
if (QueueSlots == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// section 3.3.14
|
||||
// Bits in this field shall only be set to ‘1’ by software when PxCMD.ST is set to ‘1’
|
||||
|
@ -1301,6 +1407,9 @@ AhciActivatePort (
|
|||
return;
|
||||
}
|
||||
|
||||
sact = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->SACT);
|
||||
ci = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->CI);
|
||||
|
||||
// get the lowest set bit
|
||||
tmp = QueueSlots & (QueueSlots - 1);
|
||||
|
||||
|
@ -1316,8 +1425,6 @@ 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);
|
||||
|
||||
|
@ -1355,17 +1462,21 @@ AhciProcessIO (
|
|||
|
||||
NT_ASSERT(PathId < AdapterExtension->PortCount);
|
||||
|
||||
// add Srb to queue
|
||||
AddQueue(&PortExtension->SrbQueue, Srb);
|
||||
|
||||
if (PortExtension->IsActive == FALSE)
|
||||
return; // we should wait for device to get active
|
||||
|
||||
AhciZeroMemory(&lockhandle, sizeof(lockhandle));
|
||||
|
||||
// Acquire Lock
|
||||
StorPortAcquireSpinLock(AdapterExtension, InterruptLock, NULL, &lockhandle);
|
||||
|
||||
// add Srb to queue
|
||||
AddQueue(&PortExtension->SrbQueue, Srb);
|
||||
|
||||
if (PortExtension->DeviceParams.IsActive == FALSE)
|
||||
{
|
||||
// Release Lock
|
||||
StorPortReleaseSpinLock(AdapterExtension, &lockhandle);
|
||||
return; // we should wait for device to get active
|
||||
}
|
||||
|
||||
occupiedSlots = (PortExtension->QueueSlots | PortExtension->CommandIssuedSlots); // Busy command slots for given port
|
||||
NCS = AHCI_Global_Port_CAP_NCS(AdapterExtension->CAP);
|
||||
commandSlotMask = (1 << NCS) - 1; // available slots mask
|
||||
|
@ -1419,46 +1530,107 @@ AhciProcessIO (
|
|||
*/
|
||||
VOID
|
||||
InquiryCompletion (
|
||||
__in PAHCI_ADAPTER_EXTENSION AdapterExtension,
|
||||
__in PAHCI_PORT_EXTENSION PortExtension,
|
||||
__in PSCSI_REQUEST_BLOCK Srb
|
||||
)
|
||||
{
|
||||
ULONG SrbStatus;
|
||||
PCDB cdb;
|
||||
PLUN_LIST LunList;
|
||||
PAHCI_SRB_EXTENSION SrbExtension;
|
||||
PIDENTIFY_DEVICE_DATA IdentifyDeviceData;
|
||||
ULONG SrbStatus, LunCount, DataBufferLength;
|
||||
|
||||
DebugPrint("InquiryCompletion()\n");
|
||||
|
||||
NT_ASSERT(PortExtension != NULL);
|
||||
NT_ASSERT(Srb != NULL);
|
||||
|
||||
cdb = (PCDB)&Srb->Cdb;
|
||||
SrbStatus = Srb->SrbStatus;
|
||||
SrbExtension = GetSrbExtension(Srb);
|
||||
|
||||
if (SrbStatus == SRB_STATUS_SUCCESS)
|
||||
{
|
||||
IdentifyDeviceData = PortExtension->IdentifyDeviceData;
|
||||
|
||||
if (SrbExtension->CommandReg == IDE_COMMAND_IDENTIFY)
|
||||
{
|
||||
DebugPrint("Device: ATA\n");
|
||||
AdapterExtension->DeviceParams.DeviceType = AHCI_DEVICE_TYPE_ATA;
|
||||
PortExtension->DeviceParams.DeviceType = AHCI_DEVICE_TYPE_ATA;
|
||||
if (IdentifyDeviceData->GeneralConfiguration.RemovableMedia)
|
||||
{
|
||||
PortExtension->DeviceParams.RemovableDevice = 1;
|
||||
}
|
||||
|
||||
if (IdentifyDeviceData->CommandSetSupport.BigLba && IdentifyDeviceData->CommandSetActive.BigLba)
|
||||
{
|
||||
PortExtension->DeviceParams.Lba48BitMode = 1;
|
||||
}
|
||||
|
||||
PortExtension->DeviceParams.AccessType = DIRECT_ACCESS_DEVICE;
|
||||
|
||||
// TODO: Add other device params
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugPrint("Device: ATAPI\n");
|
||||
AdapterExtension->DeviceParams.DeviceType = AHCI_DEVICE_TYPE_ATAPI;
|
||||
PortExtension->DeviceParams.DeviceType = AHCI_DEVICE_TYPE_ATAPI;
|
||||
|
||||
PortExtension->DeviceParams.AccessType = READ_ONLY_DIRECT_ACCESS_DEVICE;
|
||||
}
|
||||
// TODO: Set Device Paramters
|
||||
}
|
||||
else if (SrbStatus == SRB_STATUS_NO_DEVICE)
|
||||
{
|
||||
DebugPrint("Device: No Device\n");
|
||||
AdapterExtension->DeviceParams.DeviceType = AHCI_DEVICE_TYPE_NODEVICE;
|
||||
PortExtension->DeviceParams.DeviceType = AHCI_DEVICE_TYPE_NODEVICE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((cdb != NULL) && (cdb->CDB10.OperationCode == SCSIOP_REPORT_LUNS))
|
||||
{
|
||||
Srb->SrbStatus = SRB_STATUS_SUCCESS;
|
||||
Srb->ScsiStatus = SCSISTAT_GOOD;
|
||||
|
||||
SrbExtension->AtaFunction = 0;
|
||||
DataBufferLength = Srb->DataTransferLength;
|
||||
|
||||
LunList = (PLUN_LIST)Srb->DataBuffer;
|
||||
if (PortExtension->DeviceParams.DeviceType == AHCI_DEVICE_TYPE_NODEVICE)
|
||||
{
|
||||
LunCount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
LunCount = 1;
|
||||
}
|
||||
|
||||
if (DataBufferLength < sizeof(LUN_LIST))
|
||||
{
|
||||
DebugPrint("\tSRB_STATUS_DATA_OVERRUN\n");
|
||||
Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
|
||||
}
|
||||
else
|
||||
{
|
||||
LunList->LunListLength[0] = 0;
|
||||
LunList->LunListLength[1] = 0;
|
||||
LunList->LunListLength[2] = 0;
|
||||
LunList->LunListLength[3] = 8;
|
||||
|
||||
// followed by 8 entries
|
||||
LunList->Lun[0][0] = 0;
|
||||
LunList->Lun[0][1] = 0;
|
||||
LunList->Lun[0][2] = 0;
|
||||
LunList->Lun[0][3] = 0;
|
||||
LunList->Lun[0][4] = 0;
|
||||
LunList->Lun[0][5] = 0;
|
||||
LunList->Lun[0][6] = 0;
|
||||
LunList->Lun[0][7] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}// -- InquiryCompletion();
|
||||
|
||||
|
@ -1482,13 +1654,15 @@ UCHAR
|
|||
DeviceInquiryRequest (
|
||||
__in PAHCI_ADAPTER_EXTENSION AdapterExtension,
|
||||
__in PSCSI_REQUEST_BLOCK Srb,
|
||||
__in PCDB Cdb
|
||||
__in PCDB Cdb,
|
||||
__in BOOLEAN HasProductDataRequest
|
||||
)
|
||||
{
|
||||
PVOID DataBuffer;
|
||||
ULONG DataBufferLength;
|
||||
PAHCI_PORT_EXTENSION PortExtension;
|
||||
PAHCI_SRB_EXTENSION SrbExtension;
|
||||
PVPD_SUPPORTED_PAGES_PAGE VpdOutputBuffer;
|
||||
ULONG DataBufferLength, RequiredDataBufferLength;
|
||||
|
||||
DebugPrint("DeviceInquiryRequest()\n");
|
||||
|
||||
|
@ -1497,10 +1671,14 @@ DeviceInquiryRequest (
|
|||
SrbExtension = GetSrbExtension(Srb);
|
||||
PortExtension = &AdapterExtension->PortExtension[Srb->PathId];
|
||||
|
||||
// 3.6.1
|
||||
// If the EVPD bit is set to zero, the device server shall return the standard INQUIRY data
|
||||
if (Cdb->CDB6INQUIRY3.EnableVitalProductData == 0)
|
||||
if (Srb->Lun != 0)
|
||||
{
|
||||
return SRB_STATUS_SELECTION_TIMEOUT;
|
||||
}
|
||||
else if ((HasProductDataRequest == FALSE) || (Cdb->CDB6INQUIRY3.EnableVitalProductData == 0))
|
||||
{
|
||||
// 3.6.1
|
||||
// If the EVPD bit is set to zero, the device server shall return the standard INQUIRY data
|
||||
DebugPrint("\tEVPD Inquired\n");
|
||||
NT_ASSERT(SrbExtension != NULL);
|
||||
|
||||
|
@ -1514,7 +1692,7 @@ DeviceInquiryRequest (
|
|||
SrbExtension->LBA0 = 0;
|
||||
SrbExtension->LBA1 = 0;
|
||||
SrbExtension->LBA2 = 0;
|
||||
SrbExtension->Device = 0;
|
||||
SrbExtension->Device = 0xA0;
|
||||
SrbExtension->LBA3 = 0;
|
||||
SrbExtension->LBA4 = 0;
|
||||
SrbExtension->LBA5 = 0;
|
||||
|
@ -1526,8 +1704,11 @@ DeviceInquiryRequest (
|
|||
SrbExtension->Sgl.List[0].PhysicalAddress.LowPart = PortExtension->IdentifyDeviceDataPhysicalAddress.LowPart;
|
||||
SrbExtension->Sgl.List[0].PhysicalAddress.HighPart = PortExtension->IdentifyDeviceDataPhysicalAddress.HighPart;
|
||||
SrbExtension->Sgl.List[0].Length = sizeof(IDENTIFY_DEVICE_DATA);
|
||||
|
||||
AhciProcessIO(AdapterExtension, Srb->PathId, Srb);
|
||||
return SRB_STATUS_PENDING;
|
||||
}
|
||||
else
|
||||
else if (HasProductDataRequest == TRUE)
|
||||
{
|
||||
DebugPrint("\tVPD Inquired\n");
|
||||
|
||||
|
@ -1541,12 +1722,37 @@ DeviceInquiryRequest (
|
|||
|
||||
AhciZeroMemory(DataBuffer, DataBufferLength);
|
||||
|
||||
// not supported
|
||||
return SRB_STATUS_BAD_FUNCTION;
|
||||
switch(Cdb->CDB6INQUIRY3.PageCode)
|
||||
{
|
||||
case VPD_SUPPORTED_PAGES:
|
||||
{
|
||||
DebugPrint("\tVPD_SUPPORTED_PAGES\n");
|
||||
RequiredDataBufferLength = sizeof(VPD_SUPPORTED_PAGES_PAGE);
|
||||
if (DataBufferLength < RequiredDataBufferLength)
|
||||
{
|
||||
DebugPrint("\tDataBufferLength: %d Required: %d\n", DataBufferLength, RequiredDataBufferLength);
|
||||
return SRB_STATUS_INVALID_REQUEST;
|
||||
}
|
||||
else
|
||||
{
|
||||
VpdOutputBuffer = (PVPD_SUPPORTED_PAGES_PAGE)DataBuffer;
|
||||
VpdOutputBuffer->DeviceType = PortExtension->DeviceParams.DeviceType;
|
||||
VpdOutputBuffer->DeviceTypeQualifier = 0;
|
||||
VpdOutputBuffer->PageCode = VPD_SUPPORTED_PAGES;
|
||||
VpdOutputBuffer->PageLength = 1;
|
||||
VpdOutputBuffer->SupportedPageList[0] = VPD_SUPPORTED_PAGES;
|
||||
|
||||
return SRB_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DebugPrint("\tPageCode: %x\n", Cdb->CDB6INQUIRY3.PageCode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
AhciProcessIO(AdapterExtension, Srb->PathId, Srb);
|
||||
return SRB_STATUS_PENDING;
|
||||
return SRB_STATUS_INVALID_REQUEST;
|
||||
}// -- DeviceInquiryRequest();
|
||||
|
||||
/**
|
||||
|
@ -1573,7 +1779,8 @@ AhciAdapterReset (
|
|||
__in PAHCI_ADAPTER_EXTENSION AdapterExtension
|
||||
)
|
||||
{
|
||||
ULONG ghc, ticks, ghcStatus;
|
||||
ULONG ticks;
|
||||
AHCI_GHC ghc;
|
||||
PAHCI_MEMORY_REGISTERS abar = NULL;
|
||||
|
||||
DebugPrint("AhciAdapterReset()\n");
|
||||
|
@ -1585,13 +1792,13 @@ AhciAdapterReset (
|
|||
}
|
||||
|
||||
// HR -- Very first bit (lowest significant)
|
||||
ghc = AHCI_Global_HBA_CONTROL_HR;
|
||||
StorPortWriteRegisterUlong(AdapterExtension, &abar->GHC, ghc);
|
||||
ghc.HR = 1;
|
||||
StorPortWriteRegisterUlong(AdapterExtension, &abar->GHC, ghc.Status);
|
||||
|
||||
for (ticks = 0; ticks < 50; ++ticks)
|
||||
{
|
||||
ghcStatus = StorPortReadRegisterUlong(AdapterExtension, &abar->GHC);
|
||||
if ((ghcStatus & AHCI_Global_HBA_CONTROL_HR) == 0)
|
||||
ghc.Status = StorPortReadRegisterUlong(AdapterExtension, &abar->GHC);
|
||||
if (ghc.HR == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@ -1658,7 +1865,7 @@ IsPortValid (
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
return AdapterExtension->PortExtension[pathId].IsActive;
|
||||
return AdapterExtension->PortExtension[pathId].DeviceParams.IsActive;
|
||||
}// -- IsPortValid()
|
||||
|
||||
/**
|
||||
|
|
|
@ -25,12 +25,17 @@
|
|||
#define AHCI_DEVICE_TYPE_NODEVICE 3
|
||||
|
||||
// section 3.1.2
|
||||
#define AHCI_Global_HBA_CONTROL_HR (1 << 0)
|
||||
#define AHCI_Global_HBA_CONTROL_IE (1 << 1)
|
||||
#define AHCI_Global_HBA_CONTROL_MRSM (1 << 2)
|
||||
#define AHCI_Global_HBA_CONTROL_AE (1 << 31)
|
||||
#define AHCI_Global_HBA_CAP_S64A (1 << 31)
|
||||
|
||||
// FIS Types : http://wiki.osdev.org/AHCI
|
||||
#define FIS_TYPE_REG_H2D 0x27 // Register FIS - host to device
|
||||
#define FIS_TYPE_REG_D2H 0x34 // Register FIS - device to host
|
||||
#define FIS_TYPE_DMA_ACT 0x39 // DMA activate FIS - device to host
|
||||
#define FIS_TYPE_DMA_SETUP 0x41 // DMA setup FIS - bidirectional
|
||||
#define FIS_TYPE_BIST 0x58 // BIST activate FIS - bidirectional
|
||||
#define FIS_TYPE_PIO_SETUP 0x5F // PIO setup FIS - device to host
|
||||
#define FIS_TYPE_DEV_BITS 0xA1 // Set device bits FIS - device to host
|
||||
|
||||
#define AHCI_ATA_CFIS_FisType 0
|
||||
#define AHCI_ATA_CFIS_PMPort_C 1
|
||||
#define AHCI_ATA_CFIS_CommandReg 2
|
||||
|
@ -73,7 +78,6 @@
|
|||
typedef
|
||||
VOID
|
||||
(*PAHCI_COMPLETION_ROUTINE) (
|
||||
__in PVOID AdapterExtension,
|
||||
__in PVOID PortExtension,
|
||||
__in PVOID Srb
|
||||
);
|
||||
|
@ -225,7 +229,7 @@ typedef union _AHCI_COMMAND_HEADER_DESCRIPTION
|
|||
ULONG R : 1; // Reset
|
||||
ULONG B : 1; // BIST
|
||||
ULONG C : 1; //Clear Busy upon R_OK
|
||||
ULONG DW0_Reserved : 1;
|
||||
ULONG RSV : 1;
|
||||
ULONG PMP : 4; //Port Multiplier Port
|
||||
|
||||
ULONG PRDTL : 16; //Physical Region Descriptor Table Length
|
||||
|
@ -234,6 +238,20 @@ typedef union _AHCI_COMMAND_HEADER_DESCRIPTION
|
|||
ULONG Status;
|
||||
} AHCI_COMMAND_HEADER_DESCRIPTION;
|
||||
|
||||
typedef union _AHCI_GHC
|
||||
{
|
||||
struct
|
||||
{
|
||||
ULONG HR : 1;
|
||||
ULONG IE : 1;
|
||||
ULONG MRSM : 1;
|
||||
ULONG RSV0 : 28;
|
||||
ULONG AE : 1;
|
||||
};
|
||||
|
||||
ULONG Status;
|
||||
} AHCI_GHC;
|
||||
|
||||
// section 3.3.7
|
||||
typedef union _AHCI_PORT_CMD
|
||||
{
|
||||
|
@ -340,10 +358,10 @@ typedef struct _AHCI_COMMAND_TABLE
|
|||
typedef struct _AHCI_COMMAND_HEADER
|
||||
{
|
||||
AHCI_COMMAND_HEADER_DESCRIPTION DI; // DW 0
|
||||
ULONG PRDBC; // DW 1
|
||||
ULONG CTBA0; // DW 2
|
||||
ULONG CTBA_U0; // DW 3
|
||||
ULONG Reserved[4]; // DW 4-7
|
||||
ULONG PRDBC; // DW 1
|
||||
ULONG CTBA; // DW 2
|
||||
ULONG CTBA_U; // DW 3
|
||||
ULONG Reserved[4]; // DW 4-7
|
||||
} AHCI_COMMAND_HEADER, *PAHCI_COMMAND_HEADER;
|
||||
|
||||
// Received FIS
|
||||
|
@ -384,7 +402,7 @@ typedef struct _AHCI_PORT
|
|||
ULONG Vendor[4]; // 0x70 ~ 0x7F, vendor specific
|
||||
} AHCI_PORT, *PAHCI_PORT;
|
||||
|
||||
typedef struct _AHCI_INTERRUPT_ENABLE
|
||||
typedef union _AHCI_INTERRUPT_ENABLE
|
||||
{
|
||||
struct
|
||||
{
|
||||
|
@ -408,6 +426,7 @@ typedef struct _AHCI_INTERRUPT_ENABLE
|
|||
ULONG TFEE :1;
|
||||
ULONG CPDE :1;
|
||||
};
|
||||
|
||||
ULONG Status;
|
||||
} AHCI_INTERRUPT_ENABLE;
|
||||
|
||||
|
@ -436,9 +455,21 @@ typedef struct _AHCI_PORT_EXTENSION
|
|||
ULONG PortNumber;
|
||||
ULONG QueueSlots; // slots which we have already assigned task (Slot)
|
||||
ULONG CommandIssuedSlots; // slots which has been programmed
|
||||
BOOLEAN IsActive;
|
||||
ULONG MaxPortQueueDepth;
|
||||
|
||||
struct
|
||||
{
|
||||
UCHAR RemovableDevice;
|
||||
UCHAR Lba48BitMode;
|
||||
UCHAR AccessType;
|
||||
UCHAR DeviceType;
|
||||
UCHAR IsActive;
|
||||
} DeviceParams;
|
||||
|
||||
STOR_DPC CommandCompletion;
|
||||
PAHCI_PORT Port; // AHCI Port Infomation
|
||||
AHCI_QUEUE SrbQueue; // pending Srbs
|
||||
AHCI_QUEUE CompletionQueue;
|
||||
PSCSI_REQUEST_BLOCK Slot[MAXIMUM_AHCI_PORT_NCS]; // Srbs which has been alloted a port
|
||||
PAHCI_RECEIVED_FIS ReceivedFIS;
|
||||
PAHCI_COMMAND_HEADER CommandList;
|
||||
|
@ -470,11 +501,6 @@ typedef struct _AHCI_ADAPTER_EXTENSION
|
|||
|
||||
PVOID NonCachedExtension; // holds virtual address to noncached buffer allocated for Port Extension
|
||||
|
||||
struct
|
||||
{
|
||||
UCHAR DeviceType;
|
||||
} DeviceParams;
|
||||
|
||||
struct
|
||||
{
|
||||
// Message per port or shared port?
|
||||
|
@ -546,7 +572,8 @@ UCHAR
|
|||
DeviceInquiryRequest (
|
||||
__in PAHCI_ADAPTER_EXTENSION AdapterExtension,
|
||||
__in PSCSI_REQUEST_BLOCK Srb,
|
||||
__in PCDB Cdb
|
||||
__in PCDB Cdb,
|
||||
__in BOOLEAN HasProductDataRequest
|
||||
);
|
||||
|
||||
__inline
|
||||
|
@ -572,37 +599,56 @@ GetSrbExtension(
|
|||
// 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);
|
||||
// I assert every silly mistake I can do while coding
|
||||
// because god never help me debugging the code
|
||||
// but these asserts do :')
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
C_ASSERT((sizeof(AHCI_COMMAND_TABLE) % 128) == 0);
|
||||
|
||||
C_ASSERT(sizeof(AHCI_GHC) == sizeof(ULONG));
|
||||
C_ASSERT(sizeof(AHCI_PORT_CMD) == sizeof(ULONG));
|
||||
C_ASSERT(sizeof(AHCI_TASK_FILE_DATA) == sizeof(ULONG));
|
||||
C_ASSERT(sizeof(AHCI_INTERRUPT_ENABLE) == sizeof(ULONG));
|
||||
C_ASSERT(sizeof(AHCI_SERIAL_ATA_STATUS) == sizeof(ULONG));
|
||||
C_ASSERT(sizeof(AHCI_SERIAL_ATA_CONTROL) == sizeof(ULONG));
|
||||
C_ASSERT(sizeof(AHCI_COMMAND_HEADER_DESCRIPTION) == sizeof(ULONG));
|
||||
|
||||
C_ASSERT(FIELD_OFFSET(AHCI_COMMAND_TABLE, CFIS) == 0x00);
|
||||
C_ASSERT(FIELD_OFFSET(AHCI_COMMAND_TABLE, ACMD) == 0x40);
|
||||
C_ASSERT(FIELD_OFFSET(AHCI_COMMAND_TABLE, RSV0) == 0x50);
|
||||
C_ASSERT(FIELD_OFFSET(AHCI_COMMAND_TABLE, PRDT) == 0x80);
|
||||
|
|
Loading…
Reference in a new issue