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

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

注册被动级别的 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 例程将导致错误检查。

需要被动级别中断处理的设备

对于发出级别触发中断请求信号的内存映射设备,通常在 DIRQL 时从内核中断陷阱处理程序中调用设备的 ISR。 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 的信息,请参阅支持被动级别中断