使用 IoConnectInterruptEx 的 CONNECT_FULLY_SPECIFIED 版本
驱动程序可以使用 ioConnectInterruptEx CONNECT_FULLY_SPECIFIED 版本为特定中断注册 InterruptService 例程。 从 Windows Vista 开始,驱动程序可以使用CONNECT_FULLY_SPECIFIED版本。 通过链接到 Iointex.lib 库,驱动程序可以使用 Windows 2000、Windows XP 和 Windows Server 2003 中的 CONNECT_FULLY_SPECIFIED 版本。 有关详细信息,请参阅 在 Windows Vista 之前使用 IoConnectInterruptEx。
驱动程序将 parameters-Version> 的值指定为 CONNECT_FULLY_SPECIFIED,并使用 Parameters-FullySpecified> 的成员来指定操作的其他参数:
Parameters-FullySpecified.PhysicalDeviceObject> 为 ISR 服务的设备指定 PDO。
Parameters-FullySpecified.ServiceRoutine> 指向 InterruptService 例程,而 Parameters-FullySpecified>。ServiceContext 指定系统作为 ServiceContext 参数传递给 InterruptService 的值。 驱动程序可以使用此来传递上下文信息。 有关传递上下文信息的详细信息,请参阅 提供 ISR 上下文信息。
驱动程序提供指向 Parameters-FullySpecified.InterruptObject> 中的 PKINTERRUPT 变量的指针。 IoConnectInterruptEx 例程将此变量设置为指向中断的中断对象,该对象可在删除 ISR 时使用。
驱动程序可以选择在 Parameters-FullySpecified.SpinLock> 中指定旋转锁,供系统在与 ISR 同步时使用。 大多数驱动程序只需指定 NULL ,使系统能够代表驱动程序分配旋转锁。 有关与 ISR 同步的详细信息,请参阅 同步对设备数据的访问。
驱动程序必须在 Parameters-FullySpecified> 的其他成员中指定中断的关键属性。 系统在将 IRP_MN_START_DEVICE IRP 发送到驱动程序时,在 CM_PARTIAL_RESOURCE_DESCRIPTOR 结构数组中提供必要的信息。
系统为每个中断提供一个类型成员等于 CmResourceTypeInterrupt的CM_PARTIAL_RESOURCE_DESCRIPTOR结构。 对于消息信号中断,设置 Flags 成员的CM_RESOURCE_INTERRUPT_MESSAGE位;否则,会将其清除。
CM_PARTIAL_RESOURCE_DESCRIPTOR 的 u.Interrupt 成员包含基于行的中断的说明,而 u.MessageInterrupt.Translated 成员包含消息信号中断的说明。 下表指示在 CM_PARTIAL_RESOURCE_DESCRIPTOR 结构中查找为这两种类型的中断设置 Parameters-FullySpecified> 成员所需的信息。 有关详细信息,请参阅表后面的代码示例。
成员 | 基于行的中断 | 消息信号中断 |
---|---|---|
ShareVector |
ShareDisposition |
ShareDisposition |
向量 |
u.Interrupt.Vector |
u.MessageInterrupt.Translated.Vector |
Irql |
u.Interrupt.Level |
u.MessageInterrupt.Translated.Level |
InterruptMode |
标志 & CM_RESOURCE_INTERRUPT_LATCHED |
标志 & CM_RESOURCE_INTERRUPT_LATCHED |
ProcessorEnableMask |
u.Interrupt.Affinity |
u.MessageInterrupt.Translated.Affinity |
驱动程序将仅接收 windows Vista 和更高版本的 Windows 上消息信号中断 的CM_PARTIAL_RESOURCE_DESCRIPTOR 结构。
下面的代码示例演示如何使用 CONNECT_FULLY_SPECIFIED 注册 InterruptService 例程。
IO_CONNECT_INTERRUPT_PARAMETERS params;
// deviceExtension is a pointer to the driver's device extension.
// deviceExtension->IntObj is a PKINTERRUPT.
// deviceInterruptService is a pointer to the driver's InterruptService routine.
// IntResource is a CM_PARTIAL_RESOURCE_DESCRIPTOR structure of either type CmResourceTypeInterrupt or CmResourceTypeMessageInterrupt.
// PhysicalDeviceObject is a pointer to the device's PDO.
// ServiceContext is a pointer to driver-specified context for the ISR.
RtlZeroMemory( ¶ms, sizeof(IO_CONNECT_INTERRUPT_PARAMETERS) );
params.Version = CONNECT_FULLY_SPECIFIED;
params.FullySpecified.PhysicalDeviceObject = PhysicalDeviceObject;
params.FullySpecified.InterruptObject = &devExt->IntObj;
params.FullySpecified.ServiceRoutine = deviceInterruptService;
params.FullySpecified.ServiceContext = ServiceContext;
params.FullySpecified.FloatingSave = FALSE;
params.FullySpecified.SpinLock = NULL;
if (IntResource->Flags & CM_RESOURCE_INTERRUPT_MESSAGE) {
// The resource is for a message-signaled interrupt. Use the u.MessageInterrupt.Translated member of IntResource.
params.FullySpecified.Vector = IntResource->u.MessageInterrupt.Translated.Vector;
params.FullySpecified.Irql = (KIRQL)IntResource->u.MessageInterrupt.Translated.Level;
params.FullySpecified.SynchronizeIrql = (KIRQL)IntResource->u.MessageInterrupt.Translated.Level;
params.FullySpecified.ProcessorEnableMask = IntResource->u.MessageInterrupt.Translated.Affinity;
} else {
// The resource is for a line-based interrupt. Use the u.Interrupt member of IntResource.
params.FullySpecified.Vector = IntResource->u.Interrupt.Vector;
params.FullySpecified.Irql = (KIRQL)IntResource->u.Interrupt.Level;
params.FullySpecified.SynchronizeIrql = (KIRQL)IntResource->u.Interrupt.Level;
params.FullySpecified.ProcessorEnableMask = IntResource->u.Interrupt.Affinity;
}
params.FullySpecified.InterruptMode = (IntResource->Flags & CM_RESOURCE_INTERRUPT_LATCHED ? Latched : LevelSensitive);
params.FullySpecified.ShareVector = (BOOLEAN)(IntResource->ShareDisposition == CmResourceShareShared);
status = IoConnectInterruptEx(¶ms);
if (!NT_SUCCESS(status)) {
...
}