Exemplo n.º 1
0
VOID
Set_PxIE(
    PAHCI_CHANNEL_EXTENSION ChannelExtension,
    PAHCI_INTERRUPT_ENABLE IE
    )
/*++
    This is just a space saver function that makes the interrupt configuration more readable

Called by:

--*/
{
    AHCI_INTERRUPT_ENABLE ie;
    AHCI_COMMAND cmd;
    PAHCI_ADAPTER_EXTENSION adapterExtension = ChannelExtension->AdapterExtension;

    ie.AsUlong = StorPortReadRegisterUlong(adapterExtension, &IE->AsUlong);
    ie.DHRE = 1; //Device to Host Register FIS Interrupt (DHRS):  A D2H Register FIS has been received with the 'I' bit set, and has been copied into system memory.
    ie.PSE  = 1; //PIO Setup FIS Interrupt (PSS):  A PIO Setup FIS has been received with the 'I' bit set, it has been copied into system memory, and the data related to that FIS has been transferred.  This bit shall be set even if the data transfer resulted in an error.
    ie.DSE  = 1; //DMA Setup FIS Interrupt (DSS):  A DMA Setup FIS has been received with the 'I' bit set and has been copied into system memory.
    ie.SDBE = 1; //Set Device Bits Interrupt (SDBS):  A Set Device Bits FIS has been received with the 'I' bit set and has been copied into system memory.

    ie.UFE  = 0; //Unknown FIS Interrupt (UFS): When set to '1', indicates that an unknown FIS was received and has been copied into system memory.  This bit is cleared to '0' by software clearing the PxSERR.DIAG.F bit to '0'.  Note that this bit does not directly reflect the PxSERR.DIAG.F bit.  PxSERR.DIAG.F is set immediately when an unknown FIS is detected, whereas this bit is set when that FIS is posted to memory.  Software should wait to act on an unknown FIS until this bit is set to '1' or the two bits may become out of sync.
    ie.DPE  = 0; //Descriptor Processed (DPS):  A PRD with the 'I' bit set has transferred all of its data.  Refer to section 5.4.2.
    ie.PCE  = 1; //Port Connect Change Status (PCS): 1=Change in Current Connect Status. 0=No change in Current Connect Status.  This bit reflects the state of PxSERR.DIAG.X.  This bit is only cleared when PxSERR.DIAG.X is cleared.
    if(adapterExtension->CAP.SMPS) {
        ie.DMPE  = 1; //Device Mechanical Presence Status (DMPS): When set, indicates that a mechanical presence switch attached to this port has been opened or closed, which may lead to a change in the connection state of the device.  This bit is only valid if both CAP.SMPS and P0CMD.MPSP are set to '1'.
    } else {
        ie.DMPE  = 0;
    }

    //Reserved :14;
    ie.PRCE = 1; //PhyRdy Change Status (PRCS): When set to '1' indicates the internal PhyRdy signal changed state.  This bit reflects the state of P0SERR.DIAG.N.  To clear this bit, software must clear P0SERR.DIAG.N to '0'.
    ie.IPME = 0; //Incorrect Port Multiplier Status (IPMS):  Indicates that the HBA received a FIS from a device whose Port Multiplier field did not match what was expected.  The IPMS bit may be set during enumeration of devices on a Port Multiplier due to the normal Port Multiplier enumeration process.  It is recommended that IPMS only be used after enumeration is complete on the Port Multiplier.

    ie.OFE  = 1; //Overflow Status (OFS):  Indicates that the HBA received more bytes from a device than was specified in the PRD table for the command.
    //Reserved2 :1;
    ie.INFE = 1; //Interface Non-fatal Error Status (INFS):  Indicates that the HBA encountered an error on the Serial ATA interface but was able to continue operation.  Refer to section 6.1.2.
    ie.IFE  = 1; //Interface Fatal Error Status (IFS):  Indicates that the HBA encountered an error on the Serial ATA interface which caused the transfer to stop.  Refer to section 6.1.2.

    ie.HBDE = 1; //Host Bus Data Error Status (HBDS):  Indicates that the HBA encountered a data error (uncorrectable ECC / parity) when reading from or writing to system memory.
    ie.HBFE = 1; //Host Bus Fatal Error Status (HBFS):  Indicates that the HBA encountered a host bus error that it cannot recover from, such as a bad software pointer.  In PCI, such an indication would be a target or master abort.
    ie.TFEE = 1; //Task File Error Status (TFES):  This bit is set whenever the status register is updated by the device and the error bit (bit 0) is set.
    cmd.AsUlong = StorPortReadRegisterUlong(adapterExtension, &ChannelExtension->Px->CMD.AsUlong);
    if(cmd.CPD) {    //check for PxCMD.CPD set to '1' before setting CPDE
        ie.CPDE = 1; //Cold Port Detect Status (CPDS): When set, a device status has changed as detected by the cold presence detect logic.  This bit can either be set due to a non-connected port receiving a device, or a connected port having its device removed.  This bit is only valid if the port supports cold presence detect as indicated by PxCMD.CPD set to '1'.
    } else {
        ie.CPDE = 0;
    }
    StorPortWriteRegisterUlong(adapterExtension, &IE->AsUlong, ie.AsUlong);
}
Exemplo n.º 2
0
VOID
PortBusChangeProcess (
    _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension
    )
{
    AHCI_SERIAL_ATA_CONTROL sctl;
    STOR_LOCK_HANDLE        lockhandle = {0};

  //1 if link speed was limited, restore the supported value.
    sctl.AsUlong = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SCTL.AsUlong);
    if ( (sctl.SPD != 0) &&
         (sctl.SPD != ChannelExtension->AdapterExtension->CAP.ISS) ) {

        sctl.SPD = 0;   //AHCI 3.3.11 --- 0h  No speed negotiation restrictions
        StorPortWriteRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SCTL.AsUlong, sctl.AsUlong);
    }

  //2 Kicks off the Start Channel state machine
    StorPortAcquireSpinLock(ChannelExtension->AdapterExtension, InterruptLock, NULL, &lockhandle);
    AhciPortReset(ChannelExtension, TRUE);    // all requests should be completed
    StorPortReleaseSpinLock(ChannelExtension->AdapterExtension, &lockhandle);

  //3 Requests rescan on this port, ignore the return status of this API. Using STATE_CHANGE_TARGET to make sure a REPORT LUNS command coming from Storport.
    StorPortStateChangeDetected(ChannelExtension->AdapterExtension,
                                STATE_CHANGE_TARGET,
                                (PSTOR_ADDRESS)&ChannelExtension->DeviceExtension[0].DeviceAddress,
                                0,
                                AhciBusChangeCallback,
                                NULL);

    PortReleaseActiveReference(ChannelExtension, NULL);
}
Exemplo n.º 3
0
static u32 ReadVirtIODeviceRegister(ULONG_PTR ulRegister)
{
    if (ulRegister & ~PORT_MASK) {
        return StorPortReadRegisterUlong(NULL, (PULONG)(ulRegister));
    } else {
        return StorPortReadPortUlong(NULL, (PULONG)(ulRegister));
    }
}
Exemplo n.º 4
0
VOID
ReleaseSlottedCommand(
    _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
    _In_ UCHAR SlotNumber,
    _In_ BOOLEAN AtDIRQL
    )
/*++
    Performs Completion Data marshaling back into the SRB
It assumes:
    SRB STATUS has already been filled out
    ATA status from the AHCI registers is valid for this command
    SlotNumber points to a fully filled out Slot entry
Called by:
    AhciHwStartIo
    AhciNonQueuedErrorRecovery
    AhciCompleteIssuedSRBs

It performs:
    (overview)
    1 Initialize
    2 Marshal completion data
    3 Complete the Command
    (details)
    1.1 Keep track of the completion for our debugging records
    2.1 Handle Request Sense marshaling
    2.2.1 Handle everything else's marshaling
    2.2.2 If this was marked as needing return data, fill in the return Task File
    3.1 Make the slot available again
    3.2 Perform the Slot's last request, if there was one
    3.3.1 IO is completing, that IO may have paused the queue so unpause the queue
    3.3.2  Complete the command
Affected Variables/Registers:
    SRB
--*/
{
    PSLOT_CONTENT           slotContent;
    PAHCI_SRB_EXTENSION     srbExtension;
    PSTORAGE_REQUEST_BLOCK  srbToRelease;
    BOOLEAN                 isSenseSrb;
    BOOLEAN                 retrySrb = FALSE;

    slotContent = &ChannelExtension->Slot[SlotNumber];
    if (slotContent->Srb == NULL) {
        return;
    }

    srbExtension = GetSrbExtension(slotContent->Srb);
    isSenseSrb = IsRequestSenseSrb(srbExtension->AtaFunction);

    if (LogExecuteFullDetail(ChannelExtension->AdapterExtension->LogFlags)) {
        RecordExecutionHistory(ChannelExtension, 0x10000053);//ReleaseSlottedCommand
    }

  //2/2 Log command completion part for our debugging records
    if (LogCommand(ChannelExtension->AdapterExtension->LogFlags)) {
        PCOMMAND_HISTORY         cmdHistory;
        slotContent->CommandHistoryIndex %= 64; // should not be 64 or bigger. do it anyway to make sure we are safe

        cmdHistory = &ChannelExtension->CommandHistory[slotContent->CommandHistoryIndex];
        StorPortCopyMemory((PVOID)&cmdHistory->CompletionFIS, (PVOID)&ChannelExtension->ReceivedFIS->D2hRegisterFis, sizeof(AHCI_D2H_REGISTER_FIS));

        cmdHistory->CompletionPx[0] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->CLB.AsUlong);
        cmdHistory->CompletionPx[1] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->CLBU);
        cmdHistory->CompletionPx[2] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->FB.AsUlong);
        cmdHistory->CompletionPx[3] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->FBU);

        cmdHistory->CompletionPx[4] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->IS.AsUlong);
        cmdHistory->CompletionPx[5] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->IE.AsUlong);
        cmdHistory->CompletionPx[6] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->CMD.AsUlong);
        cmdHistory->CompletionPx[7] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->DW7_Reserved);

        cmdHistory->CompletionPx[8] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->TFD.AsUlong);
        cmdHistory->CompletionPx[9] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SIG.AsUlong);
        cmdHistory->CompletionPx[10] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SSTS.AsUlong);
        cmdHistory->CompletionPx[11] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SCTL.AsUlong);

        cmdHistory->CompletionPx[12] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SERR.AsUlong);
        cmdHistory->CompletionPx[13] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SACT);
        cmdHistory->CompletionPx[14] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->CI);
        cmdHistory->CompletionPx[15] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SNTF.AsUlong);

        cmdHistory->SrbStatus = slotContent->Srb->SrbStatus;

    }

  //2. Then complete the command
    if (isSenseSrb) {
      //2.1 Handle Request Sense marshaling
        srbToRelease = (PSTORAGE_REQUEST_BLOCK)SrbGetOriginalRequest(slotContent->Srb);

        //that original SRB must have SRB_STATUS_AUTOSENSE_VALID set appropriately
        if (slotContent->Srb->SrbStatus == SRB_STATUS_SUCCESS) {
            srbToRelease->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
            SrbSetScsiStatus(srbToRelease, SCSISTAT_CHECK_CONDITION);
        } else {
            srbToRelease->SrbStatus &= ~SRB_STATUS_AUTOSENSE_VALID;
        }

        //finish use of Sense.Srb
        srbExtension->AtaFunction = 0;
    } else {
      //2.2.1 Handle everything else's marshaling
        srbToRelease = slotContent->Srb;

        if ((srbExtension->Flags & ATA_FLAGS_SENSEDATA_SET) == 0) {
           //Record error and status
            srbExtension->AtaStatus = ChannelExtension->TaskFileData.STS.AsUchar;
            srbExtension->AtaError = ChannelExtension->TaskFileData.ERR;

          //2.2.2 If this was marked as needing return data, fill in the return Task File.
            if( IsReturnResults(srbExtension->Flags) ) {
                SetReturnRegisterValues(ChannelExtension, srbToRelease, NULL);
            }

            // interpret ATA error to be SCSI error and fill SenseBuffer
            // also log IO Record
            if (IsAtaCommand(srbExtension->AtaFunction) ||
                IsAtaCfisPayload(srbExtension->AtaFunction)) {
                // IO Record for ATA device is logged in AtaMapError()
                AtaMapError(ChannelExtension, srbToRelease, slotContent->StateFlags.FUA);
            } else {
                if (SRB_STATUS(srbToRelease->SrbStatus) == SRB_STATUS_SUCCESS) {
                    ChannelExtension->DeviceExtension[0].IoRecord.SuccessCount++;
                } else {
                    ChannelExtension->DeviceExtension[0].IoRecord.OtherErrorCount++;
                }
            }
        }
    }


  //3.1 Make the slot available again
    slotContent->CmdHeader = NULL;
    slotContent->CommandHistoryIndex = 0;
    slotContent->Srb = NULL;
    slotContent->StateFlags.FUA = FALSE;

    //Clear the CommandsToComplete bit
    ChannelExtension->SlotManager.CommandsToComplete &= ~(1 << SlotNumber);
    ChannelExtension->SlotManager.HighPriorityAttribute &= ~(1 << SlotNumber);

  //3.3.1 IO is completing, that IO may have paused the queue so unpause the queue
  //      During NCQ Error Recovery process, this flag will be reset in the error recovery completion process, either through reset or through slot release again.
    if (ChannelExtension->StateFlags.NcqErrorRecoveryInProcess == 0) {
        ChannelExtension->StateFlags.QueuePaused = FALSE;
    }

  //3.3.2 Complete the command
    if ( (srbToRelease->SrbStatus != SRB_STATUS_SUCCESS) && !isSenseSrb && (srbExtension->RetryCount == 0) ) {
        if ( (ChannelExtension->StateFlags.HybridInfoEnabledOnHiberFile == 1) && 
             IsNCQWriteCommand(srbExtension) ) {
            // NCQ WRITE with Hybrid Information failed, retry once without Hybrid Information.
            ChannelExtension->StateFlags.HybridInfoEnabledOnHiberFile = 0;
            retrySrb = TRUE;
        } else if (srbToRelease->SrbStatus == SRB_STATUS_PARITY_ERROR) {
            // if a command encounters CRC error, retry once
            retrySrb = TRUE;
        }
    }

    if (retrySrb) {
        srbToRelease->SrbStatus = SRB_STATUS_PENDING;
        srbExtension->RetryCount++;
        AhciProcessIo(ChannelExtension, srbToRelease, AtDIRQL);
    } else {
        // otherwise, complete it.
        AhciCompleteRequest(ChannelExtension, srbToRelease, AtDIRQL);
    }
}
Exemplo n.º 5
0
VOID
PortBusChangeProcess (
    _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension
    )
{
    AHCI_SERIAL_ATA_CONTROL sctl;
    STOR_LOCK_HANDLE        lockhandle = {0};
    ULONG                   status     = STOR_STATUS_UNSUCCESSFUL;

  //1 if link speed was limited, restore the supported value.
    sctl.AsUlong = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SCTL.AsUlong);
    if ( (sctl.SPD != 0) &&
         (sctl.SPD != ChannelExtension->AdapterExtension->CAP.ISS) ) {

        sctl.SPD = 0;   //AHCI 3.3.11 --- 0h  No speed negotiation restrictions
        StorPortWriteRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SCTL.AsUlong, sctl.AsUlong);
    }

  //2 Kicks off the Start Channel state machine
    AhciInterruptSpinlockAcquire(ChannelExtension->AdapterExtension, ChannelExtension->PortNumber, &lockhandle);
    AhciPortReset(ChannelExtension, TRUE);    // all requests should be completed
    AhciInterruptSpinlockRelease(ChannelExtension->AdapterExtension, ChannelExtension->PortNumber, &lockhandle);

  //3 Requests rescan on this port. Using STATE_CHANGE_TARGET to make sure a REPORT LUNS command coming from Storport.
    status = StorPortStateChangeDetected(ChannelExtension->AdapterExtension,
                                        STATE_CHANGE_TARGET,
                                        (PSTOR_ADDRESS)&ChannelExtension->DeviceExtension[0].DeviceAddress,
                                        0,
                                        AhciBusChangeCallback,
                                        NULL);

    // if the state change notification fails, set a timer to retry the notification after a delay
    if (status == STOR_STATUS_UNSUCCESSFUL) {

        if (ChannelExtension->BusChangeTimer == NULL) {

            StorPortInitializeTimer(ChannelExtension->AdapterExtension, &ChannelExtension->BusChangeTimer);
        }
        status = StorPortRequestTimer(ChannelExtension->AdapterExtension, 
                                     ChannelExtension->BusChangeTimer, 
                                     AhciBusChangeTimerCallback,
                                     ChannelExtension, 
                                     100000, // 100 milliseconds
                                     0);

        if ( status != STOR_STATUS_SUCCESS ) {
            PortReleaseActiveReference(ChannelExtension, NULL);
        }
 
    } else {

        if (ChannelExtension->BusChangeTimer != NULL) {

            StorPortFreeTimer(ChannelExtension->AdapterExtension, ChannelExtension->BusChangeTimer);
            ChannelExtension->BusChangeTimer = NULL;
        }    
       
        PortReleaseActiveReference(ChannelExtension, NULL);
   
    }

}
Exemplo n.º 6
0
PAHCI_MEMORY_REGISTERS
GetABARAddress(
    _In_ PAHCI_ADAPTER_EXTENSION AdapterExtension,
    _In_ PPORT_CONFIGURATION_INFORMATION ConfigInfo
    )
/*++
    Search a set of resources (I/O and memory) for an entry corresponding to an AHCI ABAR address.

It assumes:
    AdapterExtension->AhciBaseAddress has been set
Called by:
    AhciHwFindAdapter
It performs:
    1. If any resources are defined, loop over all resource entries, looking for the AHCI ABAR address. If found, return it.
    2. If this point is reached, ABAR was not found. Return NULL.
Affected Variables/Registers:
    none
ReturnValue:
    Address of AHCI controller memory registers if found, NULL otherwise

--*/
{
    PAHCI_MEMORY_REGISTERS  abar;
    ULONG i;

    abar = NULL;

  // loop over resource entries
    if (ConfigInfo->NumberOfAccessRanges > 0) {
        for (i = 0; i < ConfigInfo->NumberOfAccessRanges; i++) {
#if defined (_ARM_) || defined (_ARM64_)
            if ((*(ConfigInfo->AccessRanges))[i].RangeStart.QuadPart != 0) {
#else
            if ((*(ConfigInfo->AccessRanges))[i].RangeStart.QuadPart == AdapterExtension->AhciBaseAddress) {
#endif
                abar = (PAHCI_MEMORY_REGISTERS)StorPortGetDeviceBase(AdapterExtension,
                                                                     ConfigInfo->AdapterInterfaceType,
                                                                     ConfigInfo->SystemIoBusNumber,
                                                                     (*(ConfigInfo->AccessRanges))[i].RangeStart,
                                                                     (*(ConfigInfo->AccessRanges))[i].RangeLength,
                                                                     (BOOLEAN)!(*(ConfigInfo->AccessRanges))[i].RangeInMemory);
                break;
            }
        }
    }

    return abar;
}


VOID
RecordExecutionHistory(
    PAHCI_CHANNEL_EXTENSION ChannelExtension,
    ULONG Function
  )
/*++
    Takes a snapshot of the AHCI registers for debugging
It assumes:
    nothing
Called by:
    Everything

It performs:
    (overview)
    1 Select the next available index
    2 Take the snapshot
    (details)
    1.1 Select the next available index
    2.1 Copy over the Channel Extension header
    2.2 Copy over the AHCI registers
Affected Variables/Registers:
    none
Return Value:
    none
--*/
{
    int i;

  //1.1 Select the next available index
    // Actually, ExecutionHistoryNextAvailableIndex is used for current index.
    if (ChannelExtension->ExecutionHistoryNextAvailableIndex >= (MAX_EXECUTION_HISTORY_ENTRY_COUNT - 1)) {
        ChannelExtension->ExecutionHistoryNextAvailableIndex = 0;
    } else {
        ChannelExtension->ExecutionHistoryNextAvailableIndex++;
    }

  //2.1 Copy over the Channel Extension header
    ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].Function = Function;

    if(ChannelExtension->AdapterExtension->IS) {
        // Keep using the old field "IS" to save StateFlags information.
        StorPortCopyMemory(&ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].IS, &ChannelExtension->StateFlags, sizeof(ULONG));
    } else {
        ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].IS = (ULONG)~0;
    }

    StorPortCopyMemory(&ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].SlotManager, &ChannelExtension->SlotManager, sizeof(SLOT_MANAGER));

  //2.2 Copy over the AHCI registers
    if(ChannelExtension->Px) {
        ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].Px[0] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->CLB.AsUlong);
        ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].Px[1] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->CLBU);
        ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].Px[2] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->FB.AsUlong);
        ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].Px[3] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->FBU);

        ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].Px[4] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->IS.AsUlong);
        ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].Px[5] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->IE.AsUlong);
        ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].Px[6] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->CMD.AsUlong);
        ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].Px[7] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->DW7_Reserved);

        ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].Px[8] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->TFD.AsUlong);
        ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].Px[9] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SIG.AsUlong);
        ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].Px[10] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SSTS.AsUlong);
        ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].Px[11] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SCTL.AsUlong);

        ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].Px[12] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SERR.AsUlong);
        ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].Px[13] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SACT);
        ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].Px[14] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->CI);
        ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].Px[15] = StorPortReadRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SNTF.AsUlong);

    } else {
        for(i=0; i<0x10; i++) {
            ChannelExtension->ExecutionHistory[ChannelExtension->ExecutionHistoryNextAvailableIndex].Px[i] = (ULONG)~0;
        }
    }
}