+ SrbExtension = Srb->SrbExtension;
+ AdapterExtension = PortExtension->AdapterExtension;
+
+ NT_ASSERT(SrbExtension != NULL);
+ NT_ASSERT(SrbExtension->AtaFunction != 0);
+
+ if ((SrbExtension->AtaFunction == ATA_FUNCTION_ATA_IDENTIFY) &&
+ (SrbExtension->Task.CommandReg == IDE_COMMAND_NOT_VALID))
+ {
+ // Here we are safe to check SIG register
+ sig = StorPortReadRegisterUlong(AdapterExtension, &PortExtension->Port->SIG);
+ if (sig == 0x101)
+ {
+ SrbExtension->Task.CommandReg = IDE_COMMAND_IDENTIFY;
+ }
+ else
+ {
+ SrbExtension->Task.CommandReg = IDE_COMMAND_ATAPI_IDENTIFY;
+ }
+ }
+
+ NT_ASSERT(SlotIndex < AHCI_Global_Port_CAP_NCS(AdapterExtension->CAP));
+ SrbExtension->SlotIndex = SlotIndex;
+
+ // program the CFIS in the CommandTable
+ CommandHeader = &PortExtension->CommandList[SlotIndex];
+
+ if (IsAtaCommand(SrbExtension->AtaFunction))
+ {
+ AhciATA_CFIS(PortExtension, SrbExtension);
+ }
+ else if (IsAtapiCommand(SrbExtension->AtaFunction))
+ {
+ AhciATAPI_CFIS(PortExtension, SrbExtension);
+ }
+
+ prdtlen = 0;
+ if (IsDataTransferNeeded(SrbExtension))
+ {
+ prdtlen = AhciBuild_PRDT(PortExtension, SrbExtension);
+ NT_ASSERT(prdtlen != -1);
+ }
+
+ // Program the command header
+ CommandHeader->DI.PRDTL = prdtlen; // number of entries in PRD table
+ CommandHeader->DI.CFL = 5;
+ 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
+
+ // Reset -- Manual Configuation
+ CommandHeader->DI.R = 0;
+ CommandHeader->DI.B = 0;
+ CommandHeader->DI.C = 0;
+
+ CommandHeader->PRDBC = 0;
+
+ CommandHeader->Reserved[0] = 0;
+ CommandHeader->Reserved[1] = 0;
+ CommandHeader->Reserved[2] = 0;
+ 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);
+
+ // command table alignment
+ NT_ASSERT((CommandTablePhysicalAddress.LowPart % 128) == 0);
+
+ CommandHeader->CTBA0 = CommandTablePhysicalAddress.LowPart;
+
+ if (IsAdapterCAPS64(AdapterExtension->CAP))
+ {
+ CommandHeader->CTBA_U0 = CommandTablePhysicalAddress.HighPart;
+ }
+
+ // mark this slot
+ PortExtension->OccupiedSlots |= SlotIndex;