GpioClx DDI 中的驱动程序支持方法

从 Windows 8 开始,提供 GPIO 框架扩展 (GpioClx)。 GpioClx-DDI 中系统提供的方法在 GpioClx 内核模式驱动程序 Msgpioclx.sys 中实现。 此驱动程序导出 GpioClx 驱动程序支持方法的入口点。 从 Windows 8 开始,Msgpioclx.sys 是操作系统的标准组件。

在生成时,GPIO 控制器驱动程序静态链接到 GpioClx 存根库中的 DDI 入口点 Msgpioclxstub.lib。 在运行时,此库执行必要的驱动程序版本协商,以动态链接到 Msgpioclx.sys中的相应入口点。

需要特定版本的 Msgpioclx.sys 的 GPIO 控制器驱动程序可以安全地链接到版本号较高的 Msgpioclx.sys 版本。 但是,此驱动程序无法链接到版本号较低的 Msgpioclx.sys 版本。

驱动程序注册

若要注册为 GpioClx 的客户端,GPIO 控制器驱动程序调用 GPIO_CLX_RegisterClient 方法。 通常,驱动程序从其 DriverEntry 例程调用此方法。 在此调用期间,驱动程序会将注册数据包传递给该方法。 此数据包包含指向一组驱动程序实现的事件回调函数的指针。 这些函数访问 GPIO 控制器设备中的硬件寄存器。 GpioClx 调用这些函数来处理 I/O 请求并管理中断。

GPIO 控制器驱动程序调用 GPIO_CLX_UnregisterClient 方法以取消其与 GpioClx 的注册。 通常,驱动程序从其 EvtDriverUnload 事件回调函数调用此方法。

设备对象初始化

若要初始化 GpioClx,GPIO 控制器驱动程序必须从其 EvtDriverDeviceAdd 回调函数调用两个 GpioClx 方法。 第一个方法 (GPIO_CLX_ProcessAddDevicePreDeviceCreate)必须在调用 WdfDeviceCreate 方法之前调用,该方法将创建设备对象。 第二种方法 (GPIO_CLX_ProcessAddDevicePostDeviceCreate)必须在 WdfDeviceCreate 调用后调用。

中断锁

大多数驱动程序实现的事件回调函数仅由 GpioClx 在 IRQL = PASSIVE_LEVEL 调用。 但是,以下列表中的回调函数在 PASSIVE_LEVEL 或 DIRQL 上调用,具体取决于 CLIENT_QueryControllerBasicInformation 回调函数提供给 GpioClx 的设备信息:

这些函数是从 GpioClx 中的中断服务例程(ISR)调用的,该例程在 DIRQL 或PASSIVE_LEVEL运行,具体取决于 GPIO 控制器的硬件寄存器是内存映射的。

CLIENT_QueryControllerBasicInformation函数以CLIENT_CONTROLLER_BASIC_INFORMATION结构的形式提供设备信息。 如果在此结构的 Flags 成员中设置了 MemoryMappedController 标志位,GpioClx ISR 会在 DIRQL 上调用上述列表中的回调函数。 否则,ISR 会在 PASSIVE_LEVEL 调用所有由驱动程序实现的回调函数。 有关此标志位的详细信息,请参阅 Interrupt-Related 回调

GpioClx 自动同步对驱动程序实现的回调函数的调用,这些函数在PASSIVE_LEVEL运行,并且不会从 GpioClx ISR 调用。 因此,一次只能运行其中一个函数。 但是,GpioClx 不会自动将这些PASSIVE_LEVEL回调与 GpioClx 从其 ISR 发出的回调同步。 如果需要,GPIO 控制器驱动程序必须显式提供此类同步。

为了避免潜在的同步错误,GpioClx 实现 GPIO 控制器驱动程序可以获取和释放的 中断锁 。 中断锁主要用于驱动程序 的CLIENT_EnableInterruptCLIENT_DisableInterrupt 回调函数。 驱动程序调用 GPIO_CLX_AcquireInterruptLock 方法以获取锁,并调用 GPIO_CLX_ReleaseInterruptLock 方法来释放锁。 驱动程序从在 PASSIVE_LEVEL 调用的回调函数中调用这些方法,并且不会从 GpioClx 的 ISR 中调用。 当驱动程序持有锁时,GpioClx ISR 无法运行。 驱动程序应仅短暂且仅在必须与 ISR 同步的关键作期间保留锁。

如果 GpioClx ISR 调用驱动程序实现的回调函数,则此函数不需要获取中断锁(或释放),因为 ISR 已持有锁(并将释放它)。 此函数对 GPIO_CLX_AcquireInterruptLockGPIO_CLX_ReleaseInterruptLock 方法的调用不起作用,但不会被视为错误。