使用 IoConnectInterruptEx 的 CONNECT_MESSAGE_BASED 版本

对于 Windows Vista 和更高版本的操作系统,驱动程序可以使用 ioConnectInterruptEx CONNECT_MESSAGE_BASED 版本为驱动程序的消息信号中断注册 ISR。 驱动程序为 Parameters-Version> 指定值 CONNECT_MESSAGE_BASED,并使用 Parameters-MessageBased> 的成员指定操作的其他参数。

  • Parameters-MessageBased.PhysicalDeviceObject> 指定 ISR 服务的设备的 PDO。 系统使用设备对象自动识别设备的消息信号中断。

  • Parameters-MessageBased.MessageServiceRoutine> 指向 InterruptMessageService 例程,而 Parameters-MessageBased.ServiceContext> 指定系统作为 ServiceContext 参数传递给 InterruptMessageService 的值。 驱动程序可以使用此来传递上下文信息。 有关传递上下文信息的详细信息,请参阅 提供 ISR 上下文信息

  • 驱动程序还可以在 Parameters-MessageBased.FallBackServiceRoutine> 中指定回退 InterruptMessageService 例程。 如果设备具有基于线路的中断,但没有消息信号中断,系统将改为注册 InterruptMessageService 例程来为基于线路的中断提供服务。 在这种情况下,系统会将 Parameters-MessageBased.ServiceContext> 作为 ServiceContext 参数传递给 InterruptServiceIoConnectInterruptExParameters-Version> 更新为 CONNECT_LINE_BASED(如果它注册了回退例程)。

  • Parameters-MessageBased.ConnectionContext> 指向一个变量,该变量接收指向用于 InterruptMessageService) 结构的IO_INTERRUPT_MESSAGE_INFO (或用于 InterruptService) 的 KINTERRUPT 结构 (的指针。 驱动程序可以使用收到的指针删除 ISR。 有关详细信息,请参阅 删除 ISR

  • 驱动程序可以选择在 Parameters-MessageBased.SpinLock> 中指定一个旋转锁,供系统在与 ISR 同步时使用。 大多数驱动程序只能指定 NULL ,使系统能够代表驱动程序分配旋转锁。 有关与 ISR 同步的详细信息,请参阅 同步对设备数据的访问

下面的代码示例演示如何使用 CONNECT_MESSAGE_BASED 注册 InterruptMessageService 例程。

IO_CONNECT_INTERRUPT_PARAMETERS params;

// deviceExtension is a pointer to the driver's device extension. 
//     deviceExtension->IntInfo is a PVOID.
//     deviceExtension->IntType is a ULONG.
// deviceInterruptService is a pointer to the driver's InterruptService routine.
// deviceInterruptMessageService is a pointer to the driver's InterruptMessageService routine.
// PhysicalDeviceObject is a pointer to the device's PDO. 
// ServiceContext is a pointer to driver-specified context for the ISR.

RtlZeroMemory( &params, sizeof(IO_CONNECT_INTERRUPT_PARAMETERS) );
params.Version = CONNECT_MESSAGE_BASED;
params.MessageBased.PhysicalDeviceObject = PhysicalDeviceObject;
params.MessageBased.MessageServiceRoutine = deviceInterruptMessageService;
params.MessageBased.ServiceContext = ServiceContext;
params.MessageBased.SpinLock = NULL;
params.MessageBased.SynchronizeIrql = 0;
params.MessageBased.FloatingSave = FALSE;
params.MessageBased.FallBackServiceRoutine = deviceInterruptService;

status = IoConnectInterruptEx(&params);

if (NT_SUCCESS(status)) {
    // We record the type of ISR registered.
    devExt->IsrType = params.Version;
} else {
    // Operation failed. Handle error.
    ...
}