WDF驱动开发-电源策略(二)

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

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

若要实现对单组件设备的 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 字段设置为 SystemManagedIdleTimeout 或 SystemManagedIdleTimeoutWithHint。 这样做会导致 WDF 注册到 PoFx。对于 KMDF 驱动程序,在注册到 PoFx 时,框架使用驱动程序在调用 WdfDeviceWdmAssignPowerFrameworkSettings 时WDF_POWER_FRAMEWORK_SETTINGS提供的信息;

由于设备可以多次启动(例如,在资源重新均衡的情况下),因此驱动程序可能会在 EvtDeviceSelfManagedIoInit 回调函数中执行上述步骤。 如果驱动程序已注册 EvtDeviceSelfManagedIoInit 回调函数,则框架在框架首次调用驱动程序的 EvtDeviceD0Entry 回调函数后,为每个设备调用一次该回调函数。

本文其余信息仅适用于 KMDF 驱动程序。

通电

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

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

  • EvtDevicePrepareHardware  //驱动程序提供 EvtDeviceWdmPostPoFxRegisterDevice 回调,如果它必须使用 POHANDLE 执行任何其他操作进行 Power Framework 注册。 例如,它可以指定延迟、驻留和唤醒要求。
  • EvtDeviceD0Entry (PrevState = WdfPowerDeviceD3Final)
  • EvtInterruptEnable
  • EvtDeviceWdmPostPoFxRegisterDevice // PoFx 句柄可用

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

  • 若要向 PoFx 发送电源控制请求,驱动程序提供 EvtDeviceWdmPostPoFxRegisterDevice 回调函数,然后使用生成的 POHANDLE 调用 PoFxPowerControl;
  • 为了执行 PoFx 请求的电源控制操作,驱动程序在其WDF_POWER_FRAMEWORK_SETTINGS结构中提供 PowerControlCallback 回调例程;
关机

WDF 在删除 PoFx 的指定注册之前,调用 EvtDeviceWdmPrePoFxUnregisterDevice 回调函数。

驱动程序可以在它提供给 WdfDeviceWdmAssignPowerFrameworkSettings 的 WDF_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 的次数。 下面是典型关机序列的示例:

  • ComponentIdleConditionCallback
  • ComponentIdleStateCallback
  • EvtInterruptDisable
  • EvtDeviceD0Exit

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

如果驱动程序以前名为 WdfInterruptReportInactive,则通过从 ComponentActiveConditionCallback 或 ComponentIdleStateCallback 调用 WdfInterruptReportActive 重新启用非活动中断。

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

多组件设备的 KMDF 驱动程序可以为每个组件定义一个或多个功能电源状态。

在这种情况下,驱动程序直接注册到电源管理框架 (PoFx) 。 若要指定 WDF 不应注册到 PoFx,驱动程序调用 WdfDeviceAssignS0IdleSettings,并将 WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS 结构的 IdleTimeoutType 成员设置为 DriverManagedIdleTimeout。 通常,驱动程序从其 EvtDriverDeviceAdd 回调函数调用此方法。

接下来,驱动程序必须注册到 PoFx。 为此,驱动程序调用 PoFxRegisterDevice ,然后 调用 PoFxStartDevicePowerManagement。 首次启动设备时,驱动程序只能向 PoFx 注册一次。 执行此操作的一种方法是从驱动程序提供的 EvtDeviceSelfManagedIoInit 函数调用这些例程。 EvtDeviceSelfManagedIoInit 仅在首次启动设备时调用。

删除设备后,驱动程序必须调用 PoFxUnregisterDevice 才能从 PoFx 注销设备。 若要仅注销一次,建议驱动程序从驱动程序提供的 EvtDeviceSelfManagedIoFlush 函数调用此例程。 仅在删除设备时调用 EvtDeviceSelfManagedIoFlush。 通过在 EvtDeviceSelfManagedIoFlush 中注销,驱动程序在睡眠和重新平衡转换期间保留电源注册,并且不必为在这些转换期间保持挂起的 I/O 请求的电源引用。

当驱动程序调用 PoFxRegisterDevice 时,它会收到一个电源注册句柄 (POHANDLE) ,该句柄可用于直接与 PoFx 交互,如以下所述:

  • 对 I/O 请求与组件电源状态进行协调
  • 报告当系统回到 S0 状态时设备开机
  • 支持多组件设备空闲时关闭电源

 此外,驱动程序可以直接调用 电源框架例程 来发送电源控制请求,并指定延迟、驻留和唤醒要求。

报告当系统回到 S0 状态时设备开机

这部分讨论的内容仅适用于 KMDF,当系统从低功耗状态返回到其工作 (S0) 状态时,PnP 管理器会发送系统设置电源 IRP (IRP_MN_SET_POWER) ,以将设备返回到其工作 (D0) 状态。 WDF 处理系统设置电源 IRP。 但是,由于在多组件方案中,驱动程序已直接注册到电源管理框架 (PoFx) ,因此当设备在电源状态D0 完全转换时,驱动程序必须调用 PoFxReportDevicePoweredOn 。 驱动程序可以通过注册 WDM 预处理例程来实现此目的,以在系统设置电源 IRP 到达时接收通知。

驱动程序可以使用以下过程:

1. 调用 WdfDeviceInitAssignWdmIrpPreprocessCallback 为IRP_MN_SET_POWER注册 EvtDeviceWdmIrpPreprocess 回调函数。 在回调中,驱动程序在其设备扩展中设置一个标志,以指示它需要从其下一个 EvtDeviceD0Entry 回调调用 PoFxReportDevicePoweredOn;
2. 在 EvtDeviceD0Entry 中,如果设置了标志,驱动程序将清除标志并调用 PoFxReportDevicePoweredOn;
3. 驱动程序还会检查 EvtDeviceSelfManagedIoFlush 中的标志。 如果设置了标志,则设备无法返回到 D0,并且设备已被删除。 在这种情况下,驱动程序调用 PoFxReportDevicePoweredOn ,然后注销 Power Framework;

相关推荐

  1. WDF驱动开发-电源策略()

    2024-06-10 19:24:02       10 阅读
  2. WDF驱动开发-PNP和电源管理()

    2024-06-10 19:24:02       15 阅读
  3. WDF驱动开发-PNP和电源管理(一)

    2024-06-10 19:24:02       11 阅读
  4. WDF驱动开发-I/O请求的处理()

    2024-06-10 19:24:02       8 阅读
  5. WDF驱动开发-注册表项

    2024-06-10 19:24:02       8 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-10 19:24:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-10 19:24:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-10 19:24:02       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-10 19:24:02       20 阅读

热门阅读

  1. 最长最短单词【菜蛋题解】

    2024-06-10 19:24:02       10 阅读
  2. 嵌入式基础知识

    2024-06-10 19:24:02       6 阅读
  3. Web前端与前端:技术之巅的较量与探索

    2024-06-10 19:24:02       9 阅读
  4. 「前端+鸿蒙」鸿蒙应用开发-TS声明和数据类型

    2024-06-10 19:24:02       11 阅读
  5. python-数据分析-缺失值-函数-数据类型

    2024-06-10 19:24:02       10 阅读
  6. NLP--机器学习

    2024-06-10 19:24:02       9 阅读
  7. Spark MLlib 机器学习

    2024-06-10 19:24:02       11 阅读
  8. 牛客——送水

    2024-06-10 19:24:02       8 阅读
  9. SSR技术:让搜索引擎爱上你的网站

    2024-06-10 19:24:02       9 阅读
  10. mysql 小例子

    2024-06-10 19:24:02       11 阅读
  11. 服务部署:Ubuntu安装搭建docker

    2024-06-10 19:24:02       10 阅读
  12. 初识manim

    2024-06-10 19:24:02       11 阅读