次の方法で共有


パッシブ レベル割り込みサービス ルーチンの使用

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 で実行される場合、 KeAcquireInterruptSpinLock ルーチンと KeReleaseInterruptSpinLock ルーチンによってバグ チェックが発生します。

パッシブ レベルの割り込み処理を必要とするデバイス

レベルによってトリガーされる割り込み要求を通知するメモリ マップド デバイスの場合、通常、デバイスの ISR はカーネルの割り込みトラップ ハンドラー内から DIRQL で呼び出されます。 ISR はデバイスのハードウェア レジスタを操作して割り込みをオフにします。

ただし、関連付けられているデバイスがレベルによってトリガーされる割り込み要求を通知するが、デバイスのハードウェア レジスタにカーネルの割り込みトラップ ハンドラー内から DIRQL で呼び出された ISR から直接アクセスできない場合は、ISR を IRQL = PASSIVE_LEVEL で実行する必要がある場合があります。 たとえば、デバイス レジスタがメモリ マップされていない場合や、レジスタ アクセス中に ISR が一時的にブロックされる可能性があります。

Windows 8 以降では、ドライバーはパッシブ レベルの ISR を登録できます。 割り込みが発生すると、カーネルの割り込みトラップ ハンドラーは、IRQL = PASSIVE_LEVEL で実行する ISR をスケジュールします。 ハンドラーが戻る前に、割り込みコントローラー (または GPIO コントローラー) で割り込みを無音にする必要があります。 デバイスがエッジによってトリガーされる割り込みを通知すると、ハンドラーは割り込みコントローラーの割り込みをクリアします。 デバイスがレベルによってトリガーされた割り込みを通知する場合、ハンドラーは割り込みコントローラー内の割り込みを一時的にマスクします。ISR の実行後、カーネルは割り込みのマスクを解除します。

パッシブ レベルの ISR を必要とする可能性があるデバイスの例として、I²C などの低電力シリアル バスに接続されているセンサー デバイスがあります。 Windows 8 以降では、I²C とその他の 単純な周辺機器バス (SPB) のサポートは、 SPB フレームワーク拡張機能 (SpbCx) によって提供されます。

I²C に接続されたセンサー デバイスのレジスタにアクセスするために、センサー ドライバーは、SpbCx とバスのコントローラー ドライバーによって共同で処理される I/O 要求をセンサー デバイスに送信します。 要求された操作を実行するには、SPB コントローラーがバス経由でデータを順次転送する必要があります。 この転送は比較的遅く、DIRQL で実行される ISR の時間制約内では実行できません。 ただし、パッシブ レベルの ISR は I/O 要求を同期的に送信し、要求が完了するまでブロックできます。

この例のパッシブ レベルの ISR は、ISR が I/O 要求を割り込みデバイスに送信するときに I²C バス コントローラーがオフになっている場合、長時間ブロックされる可能性があります。 この場合、コントローラーは、バス経由でデータを転送する前に、D0 電源状態への移行を完了する必要があります。

PCI などのバスとは異なり、この例の I²C バスでは、周辺機器からプロセッサに割り込み要求を伝達するバス固有の手段はありません。 代わりに、センサー デバイスが割り込みを GPIO コントローラー デバイス上のピンに通知し、割り込み要求をプロセッサに中継する可能性があります。 詳しくは、 GPIO の割り込みを参照してください。

通常、GPIO コントローラーのハードウェア レジスタはメモリ マップされ、カーネルの割り込みトラップ ハンドラーによって DIRQL でアクセスできます。 センサー デバイスで割り込みが発生した場合、ハンドラーは、GPIO コントローラーのレジスタ内の割り込みビットを操作することによって、割り込みを無音にする必要があります。

レベルによってトリガーされる割り込みの場合、カーネルの割り込みトラップ ハンドラーは、GPIO ピンで割り込み要求をマスクし、パッシブ レベルで実行するようにセンサー デバイスの ISR をスケジュールします。 ISR は、センサー デバイスからの割り込み要求をクリアする必要があります。 ISR から制御が戻った後、カーネルは GPIO ピンで割り込み要求のマスクを解除します。

エッジ トリガーされる割り込みの場合、カーネルのトラップ ハンドラーは、GPIO ピンで割り込み要求をクリアにし、パッシブ レベルで実行するようにセンサー デバイスの ISR をスケジュールします。

ワーカー ルーチン

IoConnectInterruptEx の呼び出しでは、ドライバーには、パッシブ レベルの ISR とワーカー ルーチンの間で割り込みの処理を分割するオプションがあります。 一般に、ISR は割り込みの初期処理 (レベルによってトリガーされる割り込みを無音にするなど) を実行し、ワーカーに追加の処理を延期する必要があります。 ISR と worker はどちらもパッシブ レベルで実行されますが、ISR は比較的高い優先度で実行され、他の優先度の高いタスクが遅れる可能性があります。 これらのタスクには、新しい割り込みのためのパッシブ レベルの ISR が含まれる場合があります。

まれに、割り込みに必要な処理が非常に少ないため、パッシブ レベルの ISR が割り込みのすべての処理を実行できる場合があります。この場合、ワーカー ルーチンは必要ありません。

KMDF ドライバーでパッシブ レベルの ISR を使用する方法については、 パッシブ レベルの割り込みのサポートを参照してください。