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->バージョン の CONNECT_FULLY_SPECIFIED の値を指定し、他の Parameters->FullySpecified のメンバーを使用して、操作の他のパラメーター指定します。
Parameters->FullySpecified.PhysicalDeviceObject は、ISR がサービスするデバイスの PDO を指定します。
Parameters->FullySpecified.ServiceRoutine は InterruptService ルーチンを指し、Parameters->FullySpecified.ServiceContext はシステムが InterruptService に ServiceContext パラメーターとして渡す値を指定します。 ドライバーは、これを使用してコンテキスト情報を渡すことができます。 コンテキスト情報の受け渡しの詳細については、「 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 |
Flags &CM_RESOURCE_INTERRUPT_LATCHED |
Flags &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)) {
...
}