msahci代码调试备份

  

  一、代码路径以及断点

  在winddk的例子里面有msahci代码, 编译成功之后, 替换系统的msahci.sys.重启下断点进行分析.

  简单的看下代码在DriverEntry中调用IDE_CONTROLLER_INTERFACE结构,并且调用AtaPortInitializeEx向PCIIDEX创建controller的FDO, 其中包含了AhciChannelInitRoutine、AhciChannelEnabled、AhciAdapterControl函数。对这几个函数下断点,查看调用来源,并且分析函数的作用.

ULONG    //REMOVE: 1PCIIDEX to driver entry
DriverEntry (       //  DriverEntry(
    PVOID Argument1,//    IN PDRIVER_OBJECT  DriverObject, 
    PVOID Argument2 //    IN PUNICODE_STRING  RegistryPath 
    )               //    )
/*++
The only goal of DriverEntry is to create an IDE_CONTROLLER_INTERFACE, populate and 
send it to AtaPortInitializeEx.

It assumes:
    DriverEntry is the first function called in msahci.sys
    The OS-specific port driver allocates a controller extension initializes it and sends it to AtaPortInitializeEx. 
    AtaPortInitializeEx initializes the miniport driver抯 dispatch tables and allocates an extension for the driver object. 
    It stores the pointer to the AtaControllerInitialize entry point and the ControllerExtensionSize in the driver object extension for later use.

Called by:                              
    external

It performs:
    (overview)
    1. Initialization of the Ide Controller Interface
    2. Calling into PCIIDEX through AtaPortInitializeEx.
    (details)
    1.1 Initialize IDE_CONTROLLER_INTERFACE to 0s
    1.2 The miniport driver indicates the support for the channel interface by setting the ChannelExtensionSize and the AtaChannelInitRoutine entry point in the controller interface structure.
    1.3 Add mini driver entry points
    1.4 add pointers to data structures and IO alignment
    2.1 The miniport must call AtaPortInitializeEx from its DriverEntry routine. 

Affected Variables/Registers:
    none

Return Values:
    The miniport driver must return TRUE if the initialization succeeded. If the miniport driver fails to initialize it must return FALSE.
    Initialization success is dependant on AtaPortInitializeEx's Return Value

--*/
{                                        //used to initialize the IDE Controller Interface
    IDE_CONTROLLER_INTERFACE IdeControllerInterface;
    PUCHAR pIdeControllerInterface  = (PUCHAR) &IdeControllerInterface;
    int i=0;

  //1.1 initialize IDE_CONTROLLER_INTERFACE to 0s
    for (i= 0; i<sizeof(IDE_CONTROLLER_INTERFACE); i++) {
        (*(pIdeControllerInterface))=0;
        pIdeControllerInterface++; 
    }
  //1.2 The miniport driver indicates the support
    IdeControllerInterface.ChannelExtensionSize= sizeof(AHCI_CHANNEL_EXTENSION); 
    IdeControllerInterface.AtaChannelInitRoutine= AhciChannelInitRoutine;
  //1.3 Add mini driver entry points 
    IdeControllerInterface.AtaControllerChannelEnabled = AhciChannelEnabled;
    IdeControllerInterface.AtaControllerTransferModeSelect = NULL;
    IdeControllerInterface.AtaAdapterControl= AhciAdapterControl;
  //1.4 add pointers to data structures and IO alignment
    IdeControllerInterface.Version= sizeof(IDE_CONTROLLER_INTERFACE);
    IdeControllerInterface.ControllerExtensionSize= sizeof(AHCI_CONTROLLER_EXTENSION);
    IdeControllerInterface.AlignmentMask = 1; // The PRDT DBA must be word aligned.

  //2.1 call into PCIIDEX where it will handle creating the controller's FDO
    return AtaPortInitializeEx( Argument1, //DriverObject,
                                Argument2, //RegistryPath,
                                &IdeControllerInterface);
}

  二、调试分析

  在msahci!AhciAdapterControl断下来之后, 可以看到调用来源是PCIIDEX!CallAdapterControl函数

  

  我们再看下msahci!AhciAdapterControl函数的实现,该函数是一个中转函数, 处理control的Start、Stop、PowerUp、PowerDown事件。

  当前堆栈看到ControlAction为0, 是IdeStart事件, 之后再次中断下来看到的是IdePowerUp事件.

BOOLEAN  
  AhciAdapterControl(
    PVOID ControllerExtension,
    IN IDE_CONTROL_ACTION ControlAction,
    IN PVOID Parameters //when ControlAction is IdeStart, this is a pointer to a IDE_CONTROLLER_CONFIGURATION
    )
/*++
This is a CONTROLLER dispatch routine for for notifications the miniport driver receives about the various PNP and power events in the system. 
This function is a function dispatcher for the IDE_CONTROL_ACTIONS: Start, Stop, PowerUp, and PowerDown

It assumes:
    The port driver ensures that there is no outstanding I/O on the adapter before invoking this routine. 

Called by:    
    external

It performs:
    Dispatch based on the IDE_CONTROL_ACTIONS for the Controller

Affected Variables/Registers:
    none

Return Values:
    The miniport driver must return TRUE to acknowledge the completion of the requested action. 
    A return value of FALSE indicates that the miniport was not able to complete the action successfully. 
    A return value of FALSE for certain actions might cause the device installation to fail.

    FALSE is only valid if the IDE_CONTROLLER_CONFIGURATION structure is not the right version.
    This causes the PCIIDEX driver to return from IRP_MJ_PnP with a STATUS_REVISION_MISMATCH
--*/
{                    //Used to perform dispatch
    BOOLEAN retVal;
    PIDE_CONTROLLER_CONFIGURATION controllerConfiguration;

    switch (ControlAction) {
    case IdeStart:

        controllerConfiguration = Parameters;
        retVal = AhciAdapterControlIdeStart(ControllerExtension, controllerConfiguration);
        break;     

    case IdeStop:

        retVal = AhciAdapterControlIdeStop(ControllerExtension);
        break;

    case IdePowerUp:

        retVal = AhciAdapterControlIdePowerUp(ControllerExtension);
        break;

    case IdePowerDown:
        retVal = AhciAdapterControlIdePowerDown(ControllerExtension);
        break;

    default:        
        retVal = FALSE;
        break;
    }
    return retVal;
}

  在msahci!AhciChannelEnabled中断下来后, 看到堆栈情况如下:

  

  我们看下这个函数的代码实现,这个函数是给每个通道创建PDO. 一旦PDO创建, 这时就会加载ataport去开启通道并且在每个通道上枚举设备。

ATA_CHANNEL_STATE  
  AhciChannelEnabled(
    IN PVOID ControllerExtension,
    IN ULONG Channel
    )
/*++
AtaControllerChannelEnabled is an optional routine.   This is an optional routine and should not have controller critical steps in it.
This function is not called in the case of a channel restart, only on QueryDeviceRelations
If the miniport driver does not implement this routine a default handler will be loaded, and all channels are assumed to be enabled.  

PCIIDEX uses this function to help it build PDOs for each channel.  
Once the PDOs are created, it is time to load ATAport who will start the channels and do enumeration for the device(s) on the channel(s).

It assumes:
    This function will be called with 'ULONG Channel' valuse from 0 to (ControllerConfiguration->NumberOfChannels - 1) which was given to PCIIDEX in AhciAdapterControl (IdeStart).

Called by:    
    external

It performs:
    (overview)
    1. Verification of channel's existance

    (details)
    1.1 Initialize variables
    1.2 Verify the channel's existance
        Ataport doesn't support sparse channels explicitly.  It is possible this channel doesn't exist.

Affected Variables/Registers:

Return Values:
    ChannelStateEnabled = Channel is ready to be used by time this function finishes
    ChannelStateDisabled= If previously enabled, this state causes the port driver to mark the channel dead
    ChannelStateUnKnown = use only if you want the port driver to assert.
--*/
{
    ATA_CHANNEL_STATE state;
    PAHCI_CONTROLLER_EXTENSION controllerExtension;
                             //structures to get information from the Controller
    PAHCI_MEMORY_REGISTERS abar;
    ULONG pi;
  
  //this is an optional routine and should not have controller critical steps in it.
  //this is not called in the case of a channel restart, only on QueryDeviceRelations

  //1.1 Initialize variables
    state = ChannelStateUnKnown;
    controllerExtension = (PAHCI_CONTROLLER_EXTENSION) ControllerExtension;
    abar = (PAHCI_MEMORY_REGISTERS) controllerExtension->ABAR_Address;
    pi = AtaPortReadRegisterUlong(&abar->PI);
  //1.2 Verify the channel's existance
    if ( (pi & (1 << Channel) ) == 0){
        return ChannelStateDisabled;
    }

    return ChannelStateEnabled;
}

  以上初始化步骤完成之后,ataport就会调用msahci!AhciChannelInitRoutine对通道上的每个设备进行初始化。

  

  我们来看看这个函数的代码实现,msahci!AhciChannelInitRoutine就将ataport初始化一部分的Channel interface进行初始化.该函数是在ataport的AddDevice创建通道的FDO扩展时调用.

BOOLEAN     
  AhciChannelInitRoutine(
    IN PVOID ChannelExtension,
    OUT PIDE_CHANNEL_INTERFACE ChannelInterface,
    IN PVOID ControllerExtension
    )
{
/*++
This is the first time that we see the Channel Interface.  Ataport has initialized some of it,  we have to initialize the rest. 
This is the first time that we see the Channel Extension whose size was specified in IdeControllerInterface.ChannelExtensionSize at DriverEntry. 
Time to start initializing the Channel Extension.

It assumes:
    The ChannelInitialize routine is called when Ataport's AddDevice is creating the Channel's FDO Extension.

Called by:    
    external

It performs:
    (overview)
    1. Start with some defensive structure checking
    2. Fill in ControllerExtension
    3. Initialization of the Channel Extension
    4. Initialization of the Channel Interface
    (details)
    1.1 Initialize Variables
    1.2 Verify the Channel Interface is the version we are expecting.
    2.1 Fill in ControllerExtension
    3.1 Initialize Channel Extension
    3.2 Check for controller matched accomodations
    3.3 Keep a copy of the Controller's Capabilities
    3.4 Finally, Intialize the Command and Interrupt logging
    4.1 Initialization of the Channel Interface

Affected Variables/Registers:
    ControllerExtension
    ChannelExtension
    ChannelInterface

Return Values:
    FALSE is only valid if the IDE_CONTROLLER_CONFIGURATION structure is not the right version.
    This causes the AtaPort driver to return from IRP_MJ_PnP, IRP_MN_START with a STATUS_REVISION_MISMATCH
    True if the function excecuted entirely.
*/
    PAHCI_CHANNEL_EXTENSION channelExtension;
    PAHCI_CONTROLLER_EXTENSION controllerExtension;


  //1.1 Initialize Variables
    channelExtension = (PAHCI_CHANNEL_EXTENSION) ChannelExtension;
    controllerExtension = (PAHCI_CONTROLLER_EXTENSION) ControllerExtension;


#ifdef ENABLE_HISTORY_LOG
    RecordExecutionHistory(channelExtension, 0x00000001);//AhciChannelInitRoutine
#endif

  //1.2 Verify the Channel Interface
    if (ChannelInterface->Version != sizeof(IDE_CHANNEL_INTERFACE) ){
        RecordExecutionHistory(channelExtension, 0x10ff0001);//AhciChannelInitRoutine failed. Structure version mismatch.
        return FALSE;
    }

  //2.1 Fill in ControllerExtension
    controllerExtension->ExtensionOnSlot[ChannelInterface->ChannelNumber] = channelExtension;
    channelExtension->ControllerExtension = (PVOID) controllerExtension;

  //3.1    Initialize Channel Extension
    channelExtension->ChannelNumber = ChannelInterface->ChannelNumber;                
    
    channelExtension->StateFlags.StartCapable = FALSE;
    channelExtension->StateFlags.Crashing = FALSE;
    channelExtension->StateFlags.IgnoreHotplugDueToResetInProgress = TRUE;
    channelExtension->StateFlags.QueuePaused = FALSE;

    channelExtension->StateFlags.NCQ_Disallowed  = FALSE;
    channelExtension->StateFlags.NCQ_Activated = FALSE;
    channelExtension->StateFlags.NCQ_Succeeded = FALSE;
    channelExtension->StateFlags.NCQ_NeverNonQueuedErrorRecovery = FALSE;
        
    channelExtension->StateFlags.CallAhciReset = FALSE;
    channelExtension->StateFlags.CallAhciNonQueuedErrorRecovery = FALSE;
    channelExtension->StateFlags.CallAhciReportBusChange = FALSE;
    channelExtension->StateFlags.IgnoreHotPlug = FALSE;

    channelExtension->StateFlags.SingleIo = FALSE;
    channelExtension->StateFlags.ResetInInit = FALSE;
    channelExtension->StateFlags.CallAhciAutoPartialToSlumber = FALSE;

    channelExtension->StateFlags.AN_Enabled = FALSE;
    channelExtension->SendGesnToDevice = FALSE;

    channelExtension->StateFlags.CLOReset_Enable = FALSE;

  //3.2 Check for controller matched accomodations

    channelExtension->SlotManager.CommandsIssued = 0;
    channelExtension->SlotManager.CommandsToComplete = 0;
    channelExtension->SlotManager.HighPriorityAttribute = 0;
    channelExtension->SlotManager.NCQueueSlice = 0;
    channelExtension->SlotManager.NormalQueueSlice = 0;
    channelExtension->SlotManager.SingleIoSlice = 0;
    channelExtension->CCS = 1;
  //3.3 Keep a copy of the Controller's Capabilities
    channelExtension->CAP = controllerExtension->CAP;
    channelExtension->CAP2 = controllerExtension->CAP2;

  //3.4 Finally, Intialize the Command and Interrupt logging
    channelExtension->CommandHistoryNextAvailableIndex = 0;
    channelExtension->ExecutionHistoryNextAvailableIndex = 0;
    
  //4.1 Initialization of the Channel Interface
    ChannelInterface->IdeHwInitialize = AhciHwInitialize;
    ChannelInterface->IdeHwBuildIo = AhciHwBuildIo;
    ChannelInterface->IdeHwStartIo = AhciHwStartIo;
    ChannelInterface->IdeHwInterrupt = AhciHwInterrupt;
    ChannelInterface->IdeHwReset = AhciHwReset;
    ChannelInterface->IdeHwControl = AhciHwControl;

    RecordExecutionHistory(channelExtension, 0x10000001);//Exit AhciChannelInitRoutine

    return TRUE;
}

  

原文地址:https://www.cnblogs.com/aliflycoris/p/10021066.html