等待/唤醒回调例程

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

由于此回调例程是代表发起 IRP 的驱动程序设置的,而不是为处理 IRP 的驱动程序设置的,因此它不得调用 PoStartNextPowerIrp;只有设置为驱动程序传递 IRP 的 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,请为其 PDO 请求另一个等待/唤醒 IRP (PoRequestPowerIrp) 。

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

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