使用被动级别中断服务例程

从 Windows 8 开始,驱动程序可以使用 IoConnectInterruptEx 例程 (ISR) 注册被动级别 InterruptService 例程。 发生关联的中断时,内核的中断陷阱处理程序会将此例程安排在 IRQL = PASSIVE_LEVEL 运行。 如果 ISR 只能通过 I/O 请求访问设备的硬件寄存器,则可能需要在被动级别运行。 被动级别 ISR 可以同步地向设备发送 I/O 请求并阻止,直到请求完成。

注册Passive-Level ISR

IoConnectInterruptEx 的输入参数是指向IO_CONNECT_INTERRUPT_PARAMETERS结构的指针。 若要注册被动级别 ISR,请将此结构的 Version 成员设置为 CONNECT_FULLY_SPECIFIED 或 CONNECT_LINE_BASED。 如果 Version = CONNECT_FULLY_SPECIFIED,请将 Irql 成员设置为 PASSIVE_LEVEL, 将 SynchronizeIrql 成员设置为 PASSIVE_LEVEL, 将 SpinLock 成员设置为 NULL。 如果 Version = CONNECT_LINE_BASED,请将 SynchronizeIrql 设置为 PASSIVE_LEVEL 和 SpinLock = NULL

如果中断对象指定被动级别 ISR, 则 KeSynchronizeExecution 例程使用内核同步事件对象而不是旋转锁将 SynchCritSection 例程的执行与 ISR 同步。

此事件对象由注册被动级别 ISR 的调用中的 IoConnectInterruptEx 例程分配。 调用方不得在此调用中提供旋转锁。 (也就是说,如果 ISR 要在被动级别运行,调用方必须将 IO_CONNECT_INTERRUPT_PARAMETERS 结构的 SpinLock 成员设置为 NULL。) 否则,IoConnectInterruptEx 将失败并返回错误状态STATUS_INVALID_PARAMETER。

如果提供的中断对象的 ISR 以 IRQL = PASSIVE_LEVEL 运行,则 KeAcquireInterruptSpinLockKeReleaseInterruptSpinLock 例程会导致 bug 检查。

需要Passive-Level中断处理的设备

对于向级别触发的中断请求发出信号的内存映射设备,设备 ISR 通常在 DIRQL 中从内核的中断陷阱处理程序中调用。 ISR 操作设备中的硬件寄存器以关闭中断。

但是,如果关联的设备发出级别触发的中断请求信号,但无法直接从从内核的中断陷阱处理程序中的 DIRQL 中调用的 ISR 访问设备的硬件寄存器,则 ISR 可能需要在 IRQL = PASSIVE_LEVEL 运行。 例如,设备寄存器可能未进行内存映射,或者在寄存器访问期间可能暂时阻止 ISR。

从 Windows 8 开始,驱动程序可以注册被动级别的 ISR。 发生中断时,内核的中断陷阱处理程序会将 ISR 计划为在 IRQL = PASSIVE_LEVEL 运行。 在处理程序返回之前,它必须在中断控制器 (或 GPIO 控制器) 中静音中断。 如果设备发出边缘触发的中断信号,处理程序会清除中断控制器中的中断。 如果设备发出级别触发的中断信号,处理程序会暂时屏蔽中断控制器中的中断;在 ISR 运行后,内核将取消屏蔽中断。

示例

可能需要被动级别 ISR 的一个设备示例是连接到低功率串行总线(如 I²C)的传感器设备。 从 Windows 8 开始,SPB 框架扩展 (SpbCx) 提供对 I²C 和其他简单外围总线 (SPB) 的支持。

为了访问 I²C 连接的传感器设备的寄存器,传感器驱动程序向传感器设备发送 I/O 请求,该请求由 SpbCx 和总线的控制器驱动程序共同处理。 若要执行请求的操作,SPB 控制器必须通过总线串行传输数据。 此传输速度相对较慢,无法在以 DIRQL 运行的 ISR 的时间限制内执行。 但是,被动级别 ISR 可以同步发送 I/O 请求,然后阻止,直到请求完成。

如果在 ISR 将 I/O 请求发送到中断设备时关闭 I²C 总线控制器,则本示例中的被动级别 ISR 可能会被阻止更长时间。 在这种情况下,控制器必须完成到 D0 电源状态的转换,然后才能通过总线传输数据。

与 PCI 等总线相比,此示例中的 I²C 总线不提供特定于总线的方式将中断请求从外围设备传递到处理器。 相反,传感器设备可能会向 GPIO 控制器设备上的引脚发出中断信号,然后将中断请求中继到处理器。 有关详细信息,请参阅 GPIO 中断

通常,GPIO 控制器的硬件寄存器是内存映射的,可以通过内核的中断陷阱处理程序在 DIRQL 中访问。 当传感器设备导致中断时,处理程序必须通过操作 GPIO 控制器寄存器中的中断位来静音中断。

对于级别触发的中断,内核的中断陷阱处理程序会屏蔽 GPIO 引脚上的中断请求,然后将传感器设备的 ISR 计划为在被动级别运行。 ISR 必须清除传感器设备的中断请求。 ISR 返回后,内核会在 GPIO 引脚上取消屏蔽中断请求。

对于边缘触发的中断,内核的陷阱处理程序会清除 GPIO 引脚上的中断请求,然后将传感器设备的 ISR 计划为在被动级别运行。

辅助角色例程

在调用 IoConnectInterruptEx 时,驱动程序可以选择拆分被动级别 ISR 和辅助角色例程之间的中断处理。 一般情况下,ISR 应执行中断的初始处理 (例如,将级别触发的中断) 静音,并将其他处理推迟到辅助角色。 尽管 ISR 和辅助角色都在被动级别运行,但 ISR 以相对较高的优先级运行,并可能会延迟其他高优先级任务。 这些任务可能包括用于新中断的被动级别 ISR。

在极少数情况下,中断可能需要很少的处理,以至于被动级别 ISR 可以执行中断的所有处理,并且不需要工作器例程。

有关在 KMDF 驱动程序中使用被动级别 ISR 的信息,请参阅 支持Passive-Level中断