首页 > 其他分享 >WDF驱动开发-PNP和电源管理(一)

WDF驱动开发-PNP和电源管理(一)

时间:2024-06-09 13:58:37浏览次数:26  
标签:WDF 框架 队列 PNP 电源 请求 驱动程序 设备

默认情况下,WDF框架处理系统发送到基于框架的驱动程序的所有 PnP 和电源管理请求。 此外,默认情况下,仅当驱动程序的硬件可用且处于工作 (D0) 状态时,框架才会向函数驱动程序传递 I/O 请求。

编写基于WDF框架的驱动程序时,可以使用WDF框架的大部分默认行为轻松支持设备的 PnP 和电源管理功能。 但是,如果驱动程序堆栈中的所有驱动程序仅使用WDF框架的默认 PnP 和电源管理行为,则设备可能无法正常工作。 例如,当设备进入其工作 (D0) 状态时,设备的功能驱动程序可能必须启用设备。

因此,框架设备对象提供一组事件回调函数和一组对象方法,使基于框架的驱动程序能够参与 PnP 和电源管理操作。 这些回调函数和对象方法允许堆栈中的每个驱动程序仅提供所需的 PnP 和电源管理支持。

通常,驱动程序堆栈中的每个各种驱动程序都负责支持一些 PnP 和电源管理操作。 驱动程序必须支持的操作取决于你正在编写的驱动程序类型和设备提供的功能。

注意: 仅限软件的驱动程序 是无法访问任何硬件的驱动程序。 某些仅限软件的驱动程序驻留在无法访问硬件的驱动程序堆栈中。 由于这些驱动程序无法访问硬件,因此它们通常不必执行任何 PnP 或电源管理操作。

其他仅限软件的驱动程序是Filter驱动程序:它们驻留在访问硬件的驱动程序堆栈中,但Filter驱动程序不访问硬件。 当Filter驱动程序收到指定 PnP 或电源管理操作的 I/O 请求时,驱动程序通常只是将请求传递给下一个驱动程序。 框架截获并传递这些请求,因此基于框架的驱动程序永远不会看到这些请求。

如果要编写仅限软件的驱动程序,驱动程序 会创建设备对象 ,但通常不需要提供任何事件回调函数来处理 PnP 或电源管理事件。 如果驱动程序使用框架队列对象,则需要将队列WDF_IO_QUEUE_CONFIG结构的 PowerManaged 成员设置为 WdfFalse 或 WdfUseDefault。

一些仅限软件的驱动程序也是 功能驱动程序。 换句话说,单个驱动程序可以充当仅限软件的驱动程序来支持无法访问硬件的虚拟设备,并充当功能驱动程序来支持硬件设备。

功能驱动程序中进行 PnP 和电源管理

功能驱动程序 控制设备的操作,因此它们访问设备硬件。 这些驱动程序必须支持 PnP 和电源管理操作,并且通常在 创建设备对象时注册多个事件回调函数。

通常,功能驱动程序的 EvtDriverDeviceAdd 事件回调函数调用 WdfDeviceInitSetPnpPowerEventCallbacks 来注册以下回调函数:

  • EvtDevicePrepareHardware,它将设备的系统分配资源传送到驱动程序。 驱动程序可以执行一些操作,例如将设备的总线相对内存映射到处理器的虚拟地址空间,以便驱动程序可以访问硬件;
  • EvtDeviceD0Entry,执行驱动程序设备每次进入其工作状态时所需的操作,例如加载固件 (D0) 状态;
  • EvtDeviceD0Exit:每次驱动程序的设备离开其工作 (D0) 状态并进入低功耗状态时,执行所需的操作;
  • EvtDeviceReleaseHardware,用于释放 EvtDevicePrepareHardware 分配的任何系统资源;

与所有框架定义的回调函数一样,上述列表中的回调函数也是可选的。 仅当驱动程序需要时,才需要提供它们。

功能驱动程序可以调用 WdfDeviceSetPnpCapabilities 和 WdfDeviceSetPowerCapabilities ,以向操作系统报告设备的 PnP 和电源管理功能。

通常,将框架的 电源托管 I/O 队列 用于大多数 I/O 请求。 如果 I/O 队列由电源管理,则框架仅当其设备处于工作状态 (D0) 状态时,才会向驱动程序传递请求。 有关电源管理的 I/O 队列的详细信息,请参阅 I/O 队列的电源管理。

通常,设备的功能驱动程序是驱动程序堆栈的 电源策略所有者 。 电源策略所有者确定 设备的相应设备电源状态 ,并在设备的电源状态发生更改时向设备的驱动程序堆栈发送请求。 对于基于框架的驱动程序,框架负责处理此责任,因此无需在驱动程序中提供代码即可请求更改设备的电源状态。

电源策略所有者有两个额外的责任:它控制设备在空闲时进入低功耗状态的能力,以及系统保持 工作状态 (S0) 状态;控制设备在检测到来自低功耗状态的外部事件时生成唤醒信号的能力。 如果设备具有空闲或唤醒功能,则功能驱动程序可以提供其他回调函数。

I/O 队列的电源管理

当框架收到定向到驱动程序设备之一的 I/O 请求时,框架会将该请求置于 I/O 队列中。 驱动程序可以通过提供请求处理程序或轮询队列从 I/O 队列获取 I/O 请求。 

在设计驱动程序时,应将驱动程序收到的 I/O 请求分为两类:

1. 要求设备处于其工作 (D0) 状态的请求,包括:

  • 需要设备函数驱动程序从设备读取数据或向设备写入数据的读取或写入请求;
  • 设备控制请求函数或总线驱动程序在没有访问设备的情况下无法提供服务;

2. 不需要设备处于其工作状态的请求 (D0) 状态,包括:

  • 设备控制请求函数或总线驱动程序可以在不访问设备的情况下提供服务;
  • 可能是筛选器驱动程序接收的所有请求;
  • 驱动程序堆栈中所有驱动程序接收的所有请求,如果堆栈支持不与任何硬件通信的仅限软件的设备;

除非你正在为不与硬件通信的堆栈编写筛选器驱动程序,否则驱动程序可能会收到一些要求设备处于其工作状态的请求,以及一些不工作的请求。

为了支持这两种类型的请求,框架提供了两种类型的 I/O 队列:电源管理的队列和未 托管 的 I/O 队列。 当驱动程序创建其每个 I/O 队列时,它会将队列WDF_IO_QUEUE_CONFIG结构中的 PowerManaged 成员设置为 WdfTrue 或 WdfFalse 以指示以下其中一项:

1. 如果驱动程序将 PowerManaged 设置为 WdfTrue,则队列由电源管理。

当 I/O 请求在电源托管队列中可用时,框架仅当设备处于其工作 (D0) 状态时,才会将请求传送到驱动程序。 因此,每当驱动程序收到来自电源托管队列的请求时,框架都保证设备可用。 如果设备未处于工作状态,框架会将请求存储在队列中,直到设备可用。

如果设备由于处于空闲状态而处于低功耗状态,并且框架将 I/O 请求置于驱动程序的电源托管队列之一中,框架会要求驱动程序堆栈在将请求传递到驱动程序之前将设备还原到其工作状态。

如果设备由于系统不处于工作 (S0) 状态而处于低功耗状态,并且如果框架将 I/O 请求放入驱动程序的电源管理队列之一,框架将等待,直到设备返回到其工作 (D0) 状态,然后将请求传递给驱动程序。

由于如果设备未处于工作状态,框架不会将 I/O 请求从电源管理的队列传递到驱动程序,因此位于驱动程序堆栈中电源策略所有者上方的驱动程序不得使用电源管理的 I/O 队列。 如果位于电源策略所有者上方的驱动程序使用电源管理的队列,并且设备处于低功耗状态,则驱动程序不会接收请求,并且无法将其传递给电源策略所有者。 因此,控制设备的电源状态的电源策略所有者不会唤醒设备。

2. 如果驱动程序将 PowerManaged 设置为 WdfFalse,则队列不是电源管理的。

当 I/O 请求在非电源管理的队列中可用时,框架会将请求传递给驱动程序,而不考虑设备是否处于其工作 (D0) 状态。 如果已将队列设置为仅接收不需要访问设备的请求,则即使设备不可用,驱动程序也可以处理每个请求。

一些驱动程序需要对即插即用 (PnP) 和电源管理操作进行一些直接控制。 这些驱动程序可以使用 自我管理的 I/O。 

使用自我管理的 I/O

大多数基于框架的驱动程序利用框架的 PnP 和电源管理功能来获取它们支持的设备。 换句话说,大多数基于框架的驱动程序都允许框架通过执行以下所有操作来管理设备的 PnP 和电源状态:

  • 提供 EvtDeviceD0Entry 和 EvtDeviceD0Exit 回调函数;
  • 提供 EvtDevicePrepareHardware 和 EvtDeviceReleaseHardware 回调函数;
  • 对要求设备处于其工作状态的 I/O 请求使用电源托管队列,并为所有其他请求使用非电源管理的队列;

但是,一些基于框架的驱动程序需要更深入地了解其设备的状态,包括以下情况下的驱动程序:

  • 驱动程序执行的操作不由驱动程序从框架 I/O 队列接收的一组 I/O 请求决定;
  • 驱动程序与较旧的非框架驱动程序通信,并直接处理 WDM 接口;
  • 驱动程序接收的 I/O 请求不能分为两组:要求设备处于其工作状态的 I/O 请求和不工作状态的 I/O 请求;

大多数驱动程序不是上述情况之一,但如果驱动程序是,它可能需要更直接地控制设备的 PnP 和电源管理操作。 此类驱动程序可以使用 自我管理的 I/O。 使用自我管理的 I/O 意味着,每当设备插入或拔出电源时,以及设备暂时停止时,需要通过一组回调函数来通知驱动程序 。

请注意,驱动程序可以使用自托管 I/O,并且仍然可以将框架的 I/O 队列用作电源管理的队列。 例如,驱动程序可以将框架的 I/O 队列(而不是电源托管)与一组自我管理的 I/O 回调函数配合使用。

若要使用自托管 I/O,驱动程序会在调用 WdfDeviceInitSetPnpPowerEventCallbacks 时注册一组额外的事件回调函数。 这些事件回调函数包括:

  • EvtDeviceSelfManagedIoInit,用于初始化和启动设备的 I/O 操作;
  • EvtDeviceSelfManagedIoSuspend,可挂起 I/O 操作;
  • EvtDeviceSelfManagedIoRestart,它将在设备的 I/O 操作暂停后重启;
  • EvtDeviceSelfManagedIoFlush,可删除未服务的 I/O 请求;
  • EvtDeviceSelfManagedIoCleanup,用于解除分配 由 EvtDeviceSelfManagedIoInit 分配的资源;

当设备首次进入其工作 (D0) 状态时,框架会调用驱动程序的 EvtDeviceSelfManagedIoInit 回调函数。 每次用户将设备插入系统以及每次重启系统时,都会发生这种情况。

驱动程序必须停止设备的 I/O 操作有三种情况:设备即将进入低功耗状态、即将删除或已意外删除。 以下详细检查了其中每种情况:

  • 设备即将进入低功耗状态,最终将恢复其工作状态:当设备即将进入低功耗状态 (,因为设备处于空闲状态、整个系统进入低功耗状态,或者 PnP 管理器) 重新分发系统硬件资源 时,框架会调用驱动程序的 EvtDeviceSelfManagedIoSuspend 回调函数。 设备重新进入其工作状态后,框架会调用驱动程序的 EvtDeviceSelfManagedIoRestart 回调函数;
  • 设备即将删除:为了处理 用户请求的设备删除,框架在停止设备之前调用驱动程序的 EvtDeviceSelfManagedIoSuspend 回调函数。 停止设备后,框架调用驱动程序的 EvtDeviceSelfManagedIoFlush 回调函数。 删除设备后,框架将调用 EvtDeviceSelfManagedIoCleanup 回调函数;
  • 设备已被意外删除:如果设备总线的驱动程序确定设备不再存在,或者堆栈中的另一个驱动程序确定设备未响应,则发现问题的驱动程序会通知 PnP 管理器。 然后,PnP 管理器通知其余驱动程序设备已消失。 对于基于框架的驱动程序,框架接收 PnP 管理器的消息,并调用驱动程序的 EvtDeviceSelfManagedIoSuspend、 EvtDeviceSelfManagedIoFlush 和 EvtDeviceSelfManagedIoCleanup 回调函数;

驱动程序还可以注册 EvtDeviceSurpriseRemoval 回调函数。 如果设备在删除时处于工作状态 (D0) 状态,框架会在调用自托管 I/O 回调函数之前调用 EvtDeviceSurpriseRemoval 。 如果设备在移除时处于低功耗状态,则会在 EvtDeviceSelfManagedIoSuspend 之后调用 EvtDeviceSurpriseRemoval。

尽管很少必要,但该框架允许驱动程序通过访问 框架中的状态机来更好地控制设备的 PnP 和电源状态。

标签:WDF,框架,队列,PNP,电源,请求,驱动程序,设备
From: https://blog.csdn.net/m0_72813396/article/details/139538270

相关文章

  • WDF驱动开发-PNP和电源管理(三)
    对于PNP设备来说,理解它们的启动和删除顺序,以及意外移除顺序非常重要,在早期,经常有拔插U盘导致windows重启的例子,这就是意外移除带来的问题。功能或Filter驱动程序的启动顺序下图显示了框架调用WDF(KMDF和UMDFV2)功能或Filter驱动程序的事件回调函数的顺序,从图底部的“设......
  • PNPXAssoc.dll文件丢失导致程序无法运行问题
    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库,这时你可以下载这个PNPXAssoc.dll文件(挑选合适的版本文件)把它......
  • BOSHIDA AC/DC电源模块:简化电路设计的便捷解决方案
    BOSHIDAAC/DC电源模块:简化电路设计的便捷解决方案AC/DC电源模块是一种常用的电力转换装置,用于将交流电源转换为直流电源,以提供给各种电子设备和系统使用。它在电路设计中起到了简化电路、提高效率和可靠性的重要作用。本文将介绍AC/DC电源模块的工作原理、应用领域以及优势。......
  • 电源设计01
    嵌入式电源设计电池容量的计算电路充电时的选择:科普硬件知识,写写关于电路板电源的事情。各类电源模块实物但为什么硬件工程师又必须要了解电源并且在板内自己设计电源呢?首先是DCDC的降压芯片下面推荐几个升压芯片:LDO电池容量的计算1kwh=3.6*10^6J,和电源的毫安时,要......
  • 基于STM32的同步整流Buck-Boost数字电源 开源
    一款基于STM32G474的四开关Buck-Boost数字电源,支持TypeC接口PD诱骗输入和DC5.5接口输入,输入/输出最高48V10A,这是我的毕业设计,现在开源出来,含原理图、PCB、程序源码、外壳3D模型等资料。做得一般,勿喷,欢迎友好交流。作品演示视频:https://www.bilibili.com/video/BV1Ui421y7i......
  • MDZ UPnP和端口映射 区别
    DMZ(demilitarizedzone):可以简单理解成把网关的全端口转发到指定内网主机上,只能指定一台主机。这是一种静态全端口映射。这个协议只要早网关开启就行了。UPnP(UniversalPlugandPlay):这个协议的目的是动态的映射网关的指定端口到指定主机上,可以一把网关的不同端口映射到不同......
  • BOSHIDA AC/DC电源模块:跟踪技术的创新之选
    BOSHIDAAC/DC电源模块:跟踪技术的创新之选AC/DC电源模块是一种能将交流电转化为直流电的设备,广泛应用于各种电子设备中。在过去的几十年中,AC/DC电源模块一直在不断发展和演进,以满足不断进步的科技需求。其中一项创新技术,即跟踪技术,成为AC/DC电源模块设计的首选。 跟踪技术是......
  • 开关电源基本原理1
    目录内容概述关于电感认识电感电感充电电感储能电感充电电感参数电感放电利用电感升压电感电流波形伏秒法则电流纹波率电感电流三种导电模式电流纹波率与频率的关系电流纹波率与电感值的关系电感值与电感体积电路纹波率r的最优值电感值与电感体积内容概述......
  • AC/DC电源模块的效率及其影响因素
    BOSHIDAAC/DC电源模块的效率及其影响因素AC/DC电源模块是一种将交流电转换为直流电的设备,广泛应用于电子设备、通信设备、工业自动化等领域。其效率是衡量其性能的重要指标之一。本文将介绍AC/DC电源模块的效率及其影响因素。 AC/DC电源模块的效率指的是其输出功率与输入功......
  • 基于51单片机数控直流数控电源的设计
    电源技术尤其是数控电源技术是一门实践性很强的工程技术,服务于各行各业。当今电源技术融合了电气、电子、系统集成、控制理论、材料等诸多学科领域。直流稳压电源是电子技术常用的仪器设备之一,广泛的应用于教学、科研等领域,是电子实验员、电子设计人员及电路开发部门进行实......