⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 power.c

📁 本压缩包为作者截取的PCI9054的WDM官方驱动源码。欢迎下载。
💻 C
📖 第 1 页 / 共 2 页
字号:
               );
}




/******************************************************************************
 *
 * Function   :  OnFinishPowerUp
 *
 * Description:  Completion routine for IRP_MN_SET_POWER
 *
 ******************************************************************************/
NTSTATUS
OnFinishPowerUp(
    PDEVICE_OBJECT fdo,
    PIRP           pIrp,
    PVOID          junk
    )
{
    NTSTATUS           status;
    POWER_STATE        state;
    POWER_STATE_TYPE   type;
    PIO_STACK_LOCATION stack;
    DEVICE_POWER_STATE devstate;


    DebugPrintf(("in OnFinishPowerUp\n"));

    if (pIrp->PendingReturned)
    {
        // Lower-level pended this IRP
        IoMarkIrpPending(
            pIrp
            );
    }

    status = pIrp->IoStatus.Status;
    if (!NT_SUCCESS(status))
    {
        DebugPrintf(("OnFinishPowerUp: IRP failed\n"));
        return status;
    }

    stack = IoGetCurrentIrpStackLocation(pIrp);
    type  = stack->Parameters.Power.Type;
    state = stack->Parameters.Power.State;

    /* If we just handled a request to restore power to the system, we
     * want to send ourselves a device power IRP. But don't do it unless
     * there's actually a request pending right now (we may immediately get
     * another system IRP to go to a different sleep state than we were in
     * to start with).
     */
    if (type == SystemPowerState)
    {
        // Restoring power to the system
        if (state.SystemState <= PowerSystemWorking)
            devstate = PowerDeviceD0;
        else
            devstate = PowerDeviceD3;

        status =
            SendDeviceSetPower(
                fdo,
                devstate,
                stack->Parameters.Power.SystemContext
                );
    }
    else
    {
        /* For a device re-power request, first restore power to the actual
         * device and then call PoSetPowerState to tell the Power Manager we
         * did so.
         */

        // Restoring power to the device
        SetPowerState(
            fdo,
            state.DeviceState
            );

        PoSetPowerState(
            fdo,
            type,
            state
            ); // after we power up
    }

    PoStartNextPowerIrp(
        pIrp
        );

    return status;
}




/******************************************************************************
 *
 * Function   :  OnPowerRequestComplete
 *
 * Description:  Completion routine for SendSelfSetPowerRequest
 *
 ******************************************************************************/
VOID
OnPowerRequestComplete(
    PDEVICE_OBJECT   DeviceObject,
    U8               MinorFunction,
    POWER_STATE      PowerState,
    PVOID            context,
    PIO_STATUS_BLOCK ioStatus
    )
{
    DebugPrintf(("in OnPowerRequestComplete\n"));

    // Set event
    if ((PKEVENT)context != NULL)
    {
        KeSetEvent(
            (PKEVENT)context,
            1,
            FALSE
            );
    }
}




/******************************************************************************
 *
 * Function   :  SendDeviceSetPower
 *
 * Description:  Send ourselves an IRP_MN_SET_POWER request
 *
 ******************************************************************************/
NTSTATUS
SendDeviceSetPower(
    PDEVICE_OBJECT     fdo,
    DEVICE_POWER_STATE state,
    U32                context
    )
{
    PIRP               pIrp;
    KEVENT             event;
    NTSTATUS           status;
    PIO_STACK_LOCATION stack;


    DebugPrintf(("in SendDeviceSetPower\n"));

    // Skip request if we are already at the desired Power level
    if (state == ((DEVICE_EXTENSION *)fdo->DeviceExtension)->PowerState)
        return STATUS_SUCCESS;

    pIrp =
        IoAllocateIrp(
            fdo->StackSize,
            FALSE
            );

    if (pIrp == NULL)
    {
        DebugPrintf(("ERROR - Unable to allocate IRP for Power request\n"));
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    // IRP status must be initialized
    pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;

    stack                                     = IoGetNextIrpStackLocation(pIrp);
    stack->MajorFunction                      = IRP_MJ_POWER;
    stack->MinorFunction                      = IRP_MN_SET_POWER;
    stack->Parameters.Power.SystemContext     = context;
    stack->Parameters.Power.Type              = DevicePowerState;
    stack->Parameters.Power.State.DeviceState = state;

    KeInitializeEvent(
        &event,
        NotificationEvent,
        FALSE
        );

    IoSetCompletionRoutine(
        pIrp,
        (PIO_COMPLETION_ROUTINE) OnRequestComplete,
        (PVOID) &event,
        TRUE,
        TRUE,
        TRUE
        );

    status =
        PoCallDriver(
            fdo,
            pIrp
            );

    if (status == STATUS_PENDING)
    {
        // Wait for completion
        KeWaitForSingleObject(
            &event,
            Executive,
            KernelMode,
            FALSE,
            NULL
            );

        status = pIrp->IoStatus.Status;
    }

    IoFreeIrp(
        pIrp
        );

    return status;
}




/******************************************************************************
 *
 * Function   :  SetPowerState
 *
 * Description:  Set the new power state
 *
 ******************************************************************************/
VOID
SetPowerState(
    PDEVICE_OBJECT     fdo,
    DEVICE_POWER_STATE state
    )
{
    POWER_INFO pPowerInfo;


    pPowerInfo.pdx   = fdo->DeviceExtension;
    pPowerInfo.state = state;

    EmpowerDevice(
        &pPowerInfo
        );
}




/******************************************************************************
 *
 * Function   :  EmpowerDevice
 *
 * Description:  Empower device
 *
 ******************************************************************************/
BOOLEAN
EmpowerDevice(
    POWER_INFO *pPowerInfo
    )
{
    // If already in the requested state, do nothing
    if (pPowerInfo->state == pPowerInfo->pdx->PowerState)
        return TRUE;

    DebugPrintf(("Putting device into state ==> "));

    switch (pPowerInfo->state)
    {
        case D0Uninitialized:
            DebugPrintf_NoInfo(("D0Uninitialized\n"));
            break;

        case D0:
            DebugPrintf_NoInfo(("D0\n"));
            break;

        case D1:
            DebugPrintf_NoInfo(("D1\n"));
            break;

        case D2:
            DebugPrintf_NoInfo(("D2\n"));
            break;

        case D3Hot:
            DebugPrintf_NoInfo(("D3Hot\n"));
            break;

        case D3Cold:
            DebugPrintf_NoInfo(("D3Cold\n"));
            break;
    }

    /*
        A real device would interpret the new state relative to the old state
        and save (or restore) some context information, send control information
        to the device, etc. This fake device just records the power state in the
        device extension.
    */

    // Set the new power state
    PlxPciPowerLevelSet(
        pPowerInfo->pdx,
        pPowerInfo->state - PowerDeviceD0 + D0
        );

    // Record the new power state
    pPowerInfo->pdx->PowerState = pPowerInfo->state;

    return TRUE;
}




/******************************************************************************
 *
 * Function   :  SendSelfSetPowerRequest
 *
 * Description:  Change the power level of the device. Note that this is not
 *               the way Microsoft recommends.
 *
 ******************************************************************************/
NTSTATUS
SendSelfSetPowerRequest(
    PDEVICE_OBJECT     fdo,
    DEVICE_POWER_STATE state
    )
{
    NTSTATUS          status;
    POWER_STATE       power;
    DEVICE_EXTENSION *pdx;


    DebugPrintf(("in SendSelfSetPowerRequest\n"));

    // Get the device extension
    if (fdo->DeviceExtension == NULL)
    {
        DebugPrintf(("ERROR - NULL extension\n"));
        return STATUS_NOT_SUPPORTED;
    }

    pdx = fdo->DeviceExtension;

    // Compare new and old power states
    if (state == pdx->PowerState)
        return STATUS_SUCCESS;

    // PoSetPowerState needs a POWER_STATE instead of a DEVICE_POWER_STATE
    power.DeviceState = state;

    if (state > pdx->PowerState)
    {
        // Removing power, process first
        PoSetPowerState(
            fdo,
            DevicePowerState,
            power
            );

        SetPowerState(
            fdo,
            state
            );
    }

    /*
        Normally, here we would create an IRP and send it down to the PCI bus
        driver. However, this crashes Win98. So, we do not do it. Note that
        the consequence of that is that the PCI bus driver does not know that
        we are changing the power level of the device.
    */

    if (state < pdx->PowerState)
    {
        // adding power, process request after
        SetPowerState(
            fdo,
            state
            );

        PoSetPowerState(
            fdo,
            DevicePowerState,
            power
            );
    }

    return STATUS_SUCCESS;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -