意外唤醒

意外唤醒是意外过渡到 D0。 设备进入 D3cold 后,当同一电源轨上的另一个设备的驱动程序请求从 D3cold 转换到 D0 时,它可能会遇到意外唤醒作为副作用。 第一个设备的驱动程序必须收到意外唤醒通知,以防止设备保持未初始化的 D0 状态。

当设备从 D3hot 移动到 D3cold 时,它可能会这样做,因为它与某些其他设备共享的电源已关闭。 在这些设备进入 D3cold 一段时间后,其中一个设备的驱动程序可能会请求转换到 D0。 为了响应此请求,父总线驱动程序或 ACPI 筛选器驱动程序会打开电源,并且共享电源的所有设备都进入其默认的开机硬件状态。

唯一需要此电源状态更改的设备驱动程序是请求更改的驱动程序。 其他设备的驱动程序必须收到有关此更改的通知,以便它们能够正确初始化其设备以在 D0 中运行。 只有能够接收此通知的驱动程序才应允许其设备进入 D3cold。 否则,驱动程序将不知道设备何时进入 D0。

设备打开后,会进入默认的未初始化硬件状态。 例如, PCI Express Base 3.0 规范 定义了设备首次接通电源时进入的 D0 未初始化 状态。 此状态的定义特定于 PCI 和 PCI Express 设备,但连接到其他总线的设备在打开时会进入类似的硬件状态。

对于实现多个功能的 PCI 或 PCI Express 设备,这些设备功能可能共享相同的电源轨。 但是,每个函数可能都有一个单独的驱动程序,并且这些函数的驱动程序不太可能彼此直接通信。 当其中一个函数的驱动程序请求将电源状态从 D3cold 更改为 D0 时,其他函数的驱动程序预计不会发生此更改。 当这些其他函数接通电源时,必须通知其驱动程序,以便它们能够将函数配置为在 D0 中正常运行。

总线驱动程序检测何时打开子设备的电源。 如果此设备的函数驱动程序未请求转换到 D0,则总线驱动程序会提示设备驱动程序向自己发送 D0 电源 IRP, (目标状态为 PowerDeviceD0) IRP_MN_SET_POWER请求,以初始化设备以在 D0 中运行。 在此初始化的 D0 状态中,设备驱动程序随后可以启动设备到 D3hot 的转换。 设备驱动程序可以通过以下方式接收从总线驱动程序意外转换到 D0 的通知:

  • 直接或间接注册为 运行时电源管理框架 客户端的设备驱动程序 (PoFx) 接收通知回调。
  • 为设备提供唤醒设备的驱动程序具有由总线驱动程序完成的挂起 IRP_MN_WAIT_WAKE 请求。

从 Windows 8 开始,作为电源策略所有者的设备功能驱动程序可以将自身注册为 PoFx 的客户端。 当总线驱动程序通知 PoFx 设备意外过渡到 D0 时,PoFx 可帮助设备移动到初始化的 D0 状态,然后切换到 D3hot。 首先,PoFx 调用驱动程序的 DevicePowerRequiredCallback 例程,以提示设备驱动程序在设备堆栈中向下发送 D0 电源 IRP。 接下来,PoFx 调用驱动程序的 DevicePowerNotRequiredCallback 例程,以通知设备驱动程序不需要设备保持 D0 状态。

从 Kernel-Mode Driver Framework (KMDF) 版本 1.11 开始,单组件设备的 KMDF 驱动程序可以通过调用 WdfDeviceWdmAssignPowerFrameworkSettings 方法间接注册到 PoFx。 在此调用中,驱动程序提供指向回调例程的指针,这些例程通知驱动程序意外转换到 D0。 有关详细信息,请参阅 支持功能电源状态

如果设备已准备好唤醒,则未将其设备注册到 PoFx 的驱动程序仍会收到意外转换到 D0 的通知。 当总线驱动程序打开设备的电源时,它们将完成驱动程序的 IRP_MN_WAIT_WAKE 请求。 作为响应,驱动程序初始化其设备以在 D0 中运行。 设备可能处于空闲状态,在这种情况下,驱动程序会在一段时间后将此设备移动到 D3hot。

未注册到 PoFx 且不为其设备进行唤醒的函数驱动程序不会收到从 D3cold 到 D0 的意外转换的通知。 设备可能会在未初始化的 D0 状态下花费大量时间。 在此状态下,设备中的所有组件通常都处于打开状态。 为了减少空闲设备的能耗,驱动程序应仅当能够收到意外转换到 D0 的通知时,才允许进入 D3cold。