割り込み関連のコールバック
オプションとして、汎用 I/O (GPIO) コントローラーのドライバーは、GPIO 割り込みのサポートを提供できます。 GPIO 割り込みをサポートするため、GPIO コントローラー ドライバーは、これらの割り込みを管理するためのコールバック関数のセットを実装します。 ドライバーには、GPIO フレームワーク拡張機能 (GpioClx) のクライアントとして登録する際にドライバーが提供する登録パケットに、これらのコールバック関数へのポインターが含まれています。 この登録パケットの詳細については、GPIO_CLIENT_REGISTRATION_PACKET を参照してください。
原則として、システム オン チップ (SoC) チップの統合部分である GPIO コントローラーには、SoC チップ内のプロセッサから直接アクセスできるメモリ マップされたハードウェア レジスタがあります。 ただし、次の図に示すように、別の GPIO コントローラー デバイスがシリアル バスを介して SoC チップに外部接続されていることもあります。
この図では、外部 GPIO コントローラーが I²C バスに接続しています。 このバスは、SoC チップの統合部分である I²C バス コントローラーによって制御されます。 外部 GPIO コントローラーからの割り込み要求ラインは、統合された GPIO コントローラーのピンに接続されます。 この例では、GpioClx DDI は、統合された GPIO コントローラーと外部 GPIO コントローラーの両方に対応できます。
GPIO コントローラー デバイスがメモリ マップされている場合、GPIO コントローラー ドライバーは DIRQL でコントローラーのハードウェア レジスタに直接アクセスできます。 ただし、GPIO コントローラーがシリアル接続されている場合、GPIO コントローラー ドライバーは、「パッシブ レベルの ISR」に説明するように、IRQL = PASSIVE_LEVEL でのみハードウェア レジスタにアクセスできます。
メモリ マップされたハードウェア レジスタがある GPIO コントローラーのドライバーは、ドライバーが GpioClx に提供するデバイス情報で MemoryMappedController フラグ ビットを設定する必要があります。 これを行なわない場合、GpioClx は、ハードウェア レジスタがメモリ マップされおらず、ドライバーが IRQL = PASSIVE_LEVEL でのみこれらのレジスタにアクセスできるものと見なします。 このフラグ ビットについての詳細は、CONTROLLER_ATTRIBUTE_FLAGS を参照してください。
GpioClx は、割り込みサービス ルーチン (ISR) を実装して GPIO コントローラーからの割り込み要求を処理します。 この ISR は、次の割り込み関連のコールバック関数を呼び出します。
CLIENT_ClearActiveInterruptsCLIENT_MaskInterruptsCLIENT_QueryActiveInterruptsCLIENT_QueryEnabledInterruptsCLIENT_UnmaskInterrupt これらの関数は、GpioClx の ISR が DIRQL で実行されるか、PASSIVE_LEVELで実行されるかに応じて、DIRQL またはPASSIVE_LEVELで呼び出されます。 ISR による関数の呼び出しは、MemoryMappedController = 1 の場合には DIRQL、MemoryMappedController = 0 の場合には PASSIVE_LEVEL で行なわれます。 どちらの場合も、ISR はコールバックを自動的にシリアル化して、これらのいずれかの関数への呼び出しが別の関数の呼び出し途中で発生しないようにします。
GPIO フレームワーク拡張機能は、MemoryMappedController フラグが設定されているかに関係なく、PASSIVE_LEVEL でのみ次の割り込み関連のコールバック関数を呼び出します。
CLIENT_DisableInterruptCLIENT_EnableInterrupt MemoryMappedController フラグが設定されていない場合、割り込みに関連するすべてのコールバック関数は PASSIVE_LEVEL で呼び出されます。 GpioClx では、これらの関数の呼び出しが自動的にシリアル化されるため、これらのいずれかの関数への呼び出しは別の関数の呼び出し途中で発生しません。
ただし、MemoryMappedController フラグが設定されている場合、CLIENT_EnableInterrupt 関数と CLIENT_DisableInterrupt 関数は、割り込みに関連する他の 4 つの関数を DIRQL で呼び出す GpioClx ISR に対して、その割り込みの有効化と操作の無効化を明示的に同期することが必要です。
通常、他の CLIENT_Xxx コールバック関数 (名前に「Interrupt」が含まれていないもの) は割り込み関連の処理を実行しないため、GpioClx ISR と同期する必要はありません。 ただし、これらの関数のいずれかが PASSIVE_LEVEL で呼び出され、DIRQL の割り込み関連関数によってアクセスされる割り込み設定にアクセスするコードが含まれている場合は、このコードを ISR に同期する必要があります。
割り込み同期をサポートするため、GpioClx は割り込みロックのセットを実装します。 PASSIVE_LEVEL で実行されるコールバック関数は、GPIO_CLX_AcquireInterruptLock メソッドを呼び出して割り込みロックを取得し、GPIO_CLX_ReleaseInterruptLock メソッドを呼び出してロックを解放できます。 関数が割り込みロックを保持している場合、GpioClx ISR を実行することはできず、この ISR は割り込み関連のコールバック関数を呼び出すことができません。 GPIO 割り込みをタイムリーに処理できるようにするには、ドライバーが割り込みロックを必要なだけ保持するようにします。
詳細については、「GPIO コントローラー ドライバーの割り込み同期」を参照してください。