支持单组件设备呈现单个或多个功能性电源状态

单组件设备的 KMDF 驱动程序可以为组件定义一个或多个功能电源状态,并注册电源管理框架(PoFx)在组件更改或其活动/空闲条件更改时调用的回调函数。 从 UMDF 版本 2.0 开始,单组件设备的 UMDF 驱动程序可以定义单个功能电源状态(F0)。

有关 PoFx 的详细信息,请参阅 Power Management Framework 概述

若要为单组件设备实现 Fx 状态支持,必须在设备首次启动时按顺序执行以下作。

  1. 此步骤仅适用于 KMDF 驱动程序。 调用 WdfDeviceWdmAssignPowerFrameworkSettings 以指定 WDF 在注册 PoFx 时使用的 Power Framework 设置。 在驱动程序调用 WdfDeviceWdmAssignPowerFrameworkSettings 时提供的WDF_POWER_FRAMEWORK_SETTINGS结构中,驱动程序可以提供指向多个回调函数的指针。 如果驱动程序仅支持单个功能电源状态(F0),则此步骤是可选的。

  2. 此步骤适用于 KMDF 驱动程序和 UMDF 驱动程序。 调用 WdfDeviceAssignS0IdleSettings,并将WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS结构的 IdleTimeoutType 字段设置为 SystemManagedIdleTimeoutSystemManagedIdleTimeoutWithHint。 这样做会导致 WDF 向 PoFx 注册。

    对于 KMDF 驱动程序,当注册 PoFx 时,框架会使用驱动程序在调用 WdfDeviceWdmAssignPowerFrameworkSettings 时提供的 WDF_POWER_FRAMEWORK_SETTINGS 中的信息。

由于设备可以多次启动,例如在资源重新均衡时,驱动程序可能会在 EvtDeviceSelfManagedIoInit 回调函数中执行前面的步骤。 如果驱动程序注册了 EvtDeviceSelfManagedIoInit 回调函数,则框架在框架首次调用驱动程序的 EvtDeviceD0Entry 回调函数后,为每个设备调用一次。

本主题中的其余信息仅适用于 KMDF 驱动程序。

启动中

当驱动程序调用 WdfDeviceWdmAssignPowerFrameworkSettings 时,它可以提供指向 EvtDeviceWdmPostPoFxRegisterDevice 回调函数的指针。

框架在框架注册到 PoFx 后调用驱动程序的 EvtDeviceWdmPostPoFxRegisterDevice 回调函数。 下面是典型启动序列的示例:

  1. EvtDevicePrepareHardware
  2. EvtDeviceD0EntryPrevState = WdfPowerDeviceD3Final
  3. EvtInterruptEnable
  4. EvtDeviceWdmPostPoFxRegisterDevice // PoFx 句柄可用

驱动程序提供 EvtDeviceWdmPostPoFxRegisterDevice 回调(如果必须通过电源框架注册的 POHANDLE 执行任何其他操作)。 例如,它可以指定延迟、驻留和唤醒要求。 有关使用 POHANDLE 的例程的详细信息,请参阅 设备电源管理例程

驱动程序还可以使用 POHANDLE 与 PoFx 交换电源控制请求:

关闭电源

WDF 先调用 EvtDeviceWdmPrePoFxUnregisterDevice 回调函数,然后再删除 PoFx 的指定注册。

驱动程序可以在它提供给 WdfDeviceWdmAssignPowerFrameworkSettingsWDF_POWER_FRAMEWORK_SETTINGS 结构中提供一个指向 ComponentIdleStateCallback 例程的指针。 PoFx 调用此例程来通知驱动程序,指定组件的 Fx 电源状态即将发生更改。 在此回调例程中,驱动程序可以执行与功能状态更改相关的特定于硬件的操作。

例如,在将组件转换为低功率 Fx 状态之前,驱动程序可能会保存硬件状态并禁用中断和 DMA。 驱动程序调用 WdfInterruptReportInactive 以通知系统中断不再处于活动状态。 在 F 状态转换期间关闭系统中断可能会降低系统的整体能耗。

驱动程序还可以在其WDF_POWER_FRAMEWORK_SETTINGS结构中提供指向 ComponentIdleConditionCallback 例程的指针。 PoFx 调用此例程以通知驱动程序组件已空闲。 在此例程中,驱动程序开始停止其电源管理队列和自我管理的I/O操作。

  1. 为每个设备的电源管理队列调用WdfIoQueueStop一次。 必须在每次调用 WdfIoQueueStop 时,提供 EvtIoQueueState 回调函数。 通常,驱动程序从 ComponentIdleConditionCallback 调用 WdfIoQueueStop

  2. 确保从每个电源管理的队列中调度到驱动程序的请求能够快速完成。 根据驱动程序,这可能涉及以下部分或全部内容:

    • 如果驱动程序没有长时间持有请求,也没有将其转发给这样做的 I/O 目标,请继续执行步骤 3。
    • 如果驱动程序长时间持有某些请求,则将这些请求重新排队到手动队列中。 在其 ComponentActiveConditionCallback 例程中,驱动程序随后可以检索请求。
    • 如果驱动程序将某些请求转发到 I/O 目标,而这些请求被长时间保留,则应取消这些请求。 在 ComponentActiveConditionCallback 中重新提交请求。
  3. 每个队列都停止后,框架将调用 EvtIoQueueState。 如果驱动程序正在停止多个电源管理的队列,则框架会针对每个队列多次调用 EvtIoQueueState

    在调用最后一个 EvtIoQueueState 函数后,驱动程序必须调用 PoFxCompleteIdleCondition。 例如,驱动程序可以从最后一个 EvtIoQueueState 中进行此调用。

    为了确定最后调用,驱动程序可以使用计数器跟踪框架调用 EvtIoQueueState 的次数。 Singlecomp 示例演示了此方法。 此示例从 Windows 8 WDK 开始提供。

下面是典型关闭电源序列的示例:

  1. ComponentIdleConditionCallback
  2. ComponentIdleStateCallback
  3. EvtInterruptDisable
  4. EvtDeviceD0Exit

ComponentActiveConditionCallback 中重启电源管理的队列和自管理的 I/O 操作。

如果驱动程序以前调用了 WdfInterruptReportInactive,则通过从 ComponentActiveConditionCallbackComponentIdleStateCallback 调用 WdfInterruptReportActive 重新启用已报告为非活动的中断。