等待/唤醒回调例程

当驱动程序请求等待/唤醒 IRP 时,它必须指定回调例程,以便它可以在发生唤醒事件时将设备返回到工作状态(D0)。 唤醒事件发生后,所有驱动程序完成了 IRP,系统将调用传递给 PoRequestPowerIrp 的回调例程。

由于此回调例程是代表发起 IRP 的驱动程序(而不是针对正在处理 IRP 的驱动程序)设置的,因此它不得调用 PoStartNextPowerIrp;只有设置为驱动程序的 IoCompletion 例程才能在堆栈下传递 IRP 来启动下一个电源 IRP。 请记住,除了在请求等待/唤醒 IRP 时设置回调例程外,策略所有者不仅会发送 IRP,而且还会处理它,因此,它可能会设置 IoCompletion 例程,因为它将 IRP 向下传递堆栈。

回调例程具有以下责任:

  1. 如果驱动程序控制多个设备,请确定其哪些设备发出唤醒信号。

  2. 为导致唤醒信号的事件提供服务。

  3. 通过调用 PoRequestPowerIrp 发送 PowerDeviceD0 请求,设置在 D0 状态下发出唤醒信号的设备。 驱动程序还必须调用 PoSetPowerState 以通知电源管理器新的设备电源状态。 有关详细信息,请参阅 发送 IRP_MN_QUERY_POWER 或 IRP_MN_SET_POWER 用于查询或设置设备的电源状态

  4. 如果驱动程序为 IRP 设置了 Cancel 例程,请调用 IoSetCancelRoutineCancel 例程重置为 NULL

  5. 如果驱动程序管理多个设备的电源策略,则递减其等待/唤醒引用计数。 如果计数为非零,表示另一个设备以前发送了等待/唤醒 IRP,请求另一个等待/唤醒 IRP(PoRequestPowerIrp)用于其 PDO。

    例如,PCI 设备可能同时为调制解调器和网络接口卡(NIC)启用了等待/唤醒。 如果 NIC 唤醒系统(从而完成 IRP),PCI FDO 必须向自身发送另一个等待/唤醒 IRP,以保证调制解调器仍然能够唤醒。

由于请求等待/唤醒 IRP 的驱动程序控制其设备堆栈的电源策略,因此它负责在 IRP 完成时将其设备返回到工作状态。 尽管较低的驱动程序可能已经对设备应用了物理电源,但策略所有者必须调用 PoRequestPowerIrp 来发送设备电源状态 D0 的 IRP_MN_SET_POWER 请求。 只有在设备堆栈中的所有驱动程序都处理了此启动 IRP 后,设备才会返回到工作状态。