处理设备通电 IRP

设备通电 IRP 指定 IRP_MN_SET_POWER 和需要比当前设备电源状态更多的电源的设备电源状态。 通常,上电 IRP 指定设备工作状态 PowerDeviceD0

启动设备的请求必须首先由设备的基础总线驱动程序处理,然后由每个连续的驱动程序处理,以备份堆栈。

下图显示了处理启动 IRP 所涉及的步骤。

说明处理设备启动请求的示意图。

处理 IRP_MN_SET_POWER 启动请求时,函数或筛选器驱动程序必须:

  • 调用 IoAcquireRemoveLock 以确保驱动程序在处理启动 IRP 时不会收到 IRP_MN_REMOVE_DEVICE 请求。

    如果 IoAcquireRemoveLock 返回失败状态,驱动程序不应继续处理 IRP。 相反,从 Windows Vista 开始,驱动程序应调用 IoCompleteRequest 来完成 IRP,然后返回失败状态。 在 Windows Server 2003、Windows XP 和 Windows 2000 中,驱动程序应调用 IoCompleteRequest 以完成 IRP,然后调用 PoStartNextPowerIrp 以启动下一个电源 IRP,然后返回失败状态。

  • 调用 IoMarkIrpPending 以将 IRP 标记为挂起。

  • 调用 IoCopyCurrentIrpStackLocationToNext 以设置 IRP 堆栈位置。 如果驱动程序设置了 IoCompletion 例程,则不得调用 IoSkipCurrentIrpStackLocation

  • 调用 IoSetCompletionRoutine 以设置启动 IoCompletion 例程。

    处理设备通电 IRP 时,驱动程序应设置 IoCompletion 例程,以还原上下文、释放删除锁,并在 IRP 完成后执行其他所需任务,并且设备通电。 在 IRP 完成之前,驱动程序不应还原上下文。 有关详细信息,请参阅 设备电源 IRP 的 IoCompletion 例程

  • 在 Windows 7 和 Windows Vista) 或 PoCallDriver (Windows Server 2003、Windows XP 和 Windows 2000) 调用 IoCallDriver (,将 IRP 传递到下一个较低的驱动程序。 IRP 必须一直沿着设备堆栈到达总线驱动程序。 仅允许总线驱动程序完成 IRP。

  • 返回STATUS_PENDING。

当总线驱动程序收到 IRP 时,它应首先检查,以确保设备仍然存在,并且未在睡眠时被移除或更换。 如果设备不再存在,总线驱动程序应在父设备上调用 IoInvalidateDeviceRelations,以通知即插即用管理器设备已消失。 在这种情况下,总线驱动程序可能会使设备启动 IRP 失败。

如果设备仍然存在,则总线驱动程序将执行将设备恢复到运行条件所需的任务,调用 PoSetPowerState 以通知电源管理器新的设备电源状态,并完成 IRP (IoCompleteRequest) 。 如果驱动程序在设备处于睡眠状态时已排队 I/O,或者设备需要浪涌电源,则总线驱动程序会将电源应用于设备。 否则,总线驱动程序在必须与设备通信时立即通电。

有关实现从关机、待机和休眠状态快速启动的最佳做法列表,请参阅 提高系统启动性能