使用 CONNECT_FULLY_SPECIFIED 版 IoConnectInterruptEx
驅動程式可以使用 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結構的陣列中提供必要的資訊。
系統會為每個中斷一 個CM_PARTIAL_RESOURCE_DESCRIPTOR 結構,且 Type 成員等於 CmResourceTypeInterrupt。 針對訊息訊號中斷,會設定 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)) {
...
}