次の方法で共有


コンポーネントの電源状態での I/O 要求の調整

[KMDF のみに適用]

複数コンポーネント デバイスの KMDF ドライバーは、アクティブな状態のコンポーネントにのみ要求を送信する必要があります。 通常、ドライバーは、コンポーネントまたはコンポーネントのセットに I/O キューを割り当てます。

最初に、1 つのコンポーネントに割り当てられているキューについて考えてみましょう。 ドライバーは、コンポーネントがアクティブになったときにキューを起動し、コンポーネントがアイドル状態になったときにキューを停止します。 そのため、KMDF がキューの要求ハンドラーを呼び出すと、デバイスは完全にオン (D0) 状態で、必要なコンポーネントはアクティブです。 要求ハンドラーは、コンポーネント ハードウェアに安全にアクセスできます。

コンポーネント セットに割り当てられているキューにも、同じ概念が適用されます。 この場合、セット内のすべてのコンポーネントがアクティブになると、ドライバーはキューを開始します。 いずれかのコンポーネントがアイドル状態になると、ドライバーはキューを停止します。

このトピックでは、コンポーネントの異なる組み合わせを必要とする複数の要求の種類が関係する状況で、複数コンポーネント デバイスの KMDF ドライバーがこのようなサポートを実装する方法について説明します。

ドライバーでサポートされている要求の種類ごとに、必要なコンポーネントを特定します。 たとえば、0、1、2 の 3 つのコンポーネントを持つデバイスを考えてみましょう。それに対してドライバーは 3 種類の要求 A、B、C を受け取ります。要求のコンポーネント要件は次のとおりです。

要求の種類 必要なコンポーネント
A 0,2
B 1
C 0,1,2

この例では、要求の種類ごとに 1 つずつ、3 つの異なるコンポーネント セットがあります。 ドライバーは、デバイスの 1 つの既定の電源管理 I/O キューと、コンポーネントの各セットに対応する 1 つの追加の電源管理キューを提供します。 上の例では、ドライバーは 1 つのプライマリ キューと、各コンポーネント セットに対応する 3 つのセカンダリ キューを作成します。 次の図に、キュー構成を示します。

Diagram showing queue implementation for a multiple-component device with request types A, B, and C.

ドライバーは各コンポーネント セットのビットマスクを維持します。 ビットマスク内の各ビットは、いずれかのコンポーネントのアクティブ/アイドル状態を表します。 ビットが設定されている場合、コンポーネントはアクティブです。 ビットがクリアされている場合、コンポーネントはアイドル状態です。

要求が到着すると、最上位キューの要求ハンドラーによって要求に必要なコンポーネントが決定され、それぞれに対して PoFxActivateComponent が呼び出されます。 次に要求ハンドラーは、そのコンポーネントのセットに対応するセカンダリ I/O キューに要求を転送します。

コンポーネントがアクティブになると、電源管理フレームワーク (PoFx) はドライバーの ComponentActiveConditionCallback ルーチンを呼び出します。 このコールバックでは、ドライバーは、そのコンポーネントが表される各ビットマスクで、指定されたコンポーネントに対応するビットを設定します。 所定のビットマスク内のすべてのビットが設定されている場合、対応するセット内のすべてのコンポーネントがアクティブです。 完全にアクティブに設定されているコンポーネント セットごとに、ドライバーは WdfIoQueueStart を呼び出して、対応するセカンダリ I/O キューを開始します。

たとえば、上記の架空のデバイスについて考えてみましょう。 コンポーネント 0 がアクティブで、コンポーネント 1 とコンポーネント 2 がアイドル状態であるとします。 コンポーネント 2 がアクティブになると、PoFx はそのコンポーネントの ComponentActiveConditionCallback ルーチンを呼び出します。 要求の種類 A と C はコンポーネント 2 を使用するため、ドライバーはこれら 2 つの要求の種類のビットマスクを操作します。 要求の種類 A のビットマスク内のすべてのビットが設定されたので、ドライバーは要求の種類 A のキューを開始します。ただし、要求の種類 C に対してはすべてのビットが設定されてはいません (コンポーネント 1 はまだアイドル状態です)。 ドライバーは、要求の種類 C のキューを開始しません。

セカンダリ I/O キューが開始されると、フレームワークはキューに格納されている要求の配信を開始します。 セカンダリ I/O キューの要求ハンドラーでは、ドライバーは、コンポーネントがアクティブであり、各要求のコンポーネントに電源参照が取得されているため、要求を安全に処理できます。

ドライバーは、要求の処理を完了すると、要求が使用していたコンポーネントごとに PoFxIdleComponent を呼び出してから、要求を完了します。 コンポーネントを使用する要求がこれ以上ない場合、電源るフェームワークはドライバーの ComponentIdleConditionCallback ルーチンを呼び出します。

このコールバックでは、ドライバーは、そのコンポーネントが表される各ビットマスクで、指定されたコンポーネントに対応するビットをクリアします。 所定のビットマスクが、対応するセット内の最初のコンポーネントがアイドル状態に遷移することを示す場合、ドライバーは WdfIoQueueStop を呼び出して、対応するセカンダリ I/O キューを停止します。 これにより、ドライバーは、対応するセット内のすべてのコンポーネントがアクティブでない限り、キューが要求をディスパッチしないようにします。

前の例をもう一度考えてみます。 すべてのコンポーネントがアクティブであるため、すべてのキューが開始されているとします。 コンポーネント 1 がアイドル状態になると、PoFx はコンポーネント 1 の ComponentIdleConditionCallback ルーチンを呼び出します。 このコールバックでは、要求の種類 B と C はコンポーネント 1 を使用するため、ドライバー要求の種類 B と C のビットマスクを操作します。 コンポーネント 1 は、これらの要求の種類の両方でアイドル状態になる最初のコンポーネントであるため、ドライバーは、要求の種類 B と C のキューを停止します。

この時点で、コンポーネント 0 がアイドル状態になるとします。 コンポーネント 0 の ComponentIdleConditionCallback では、ドライバーは要求の種類 A と C のビットマスクを操作します。コンポーネント 0 は要求の種類 A でアイドル状態になる最初のコンポーネントであるため (コンポーネント 2 はまだアクティブです)、ドライバーは要求の種類 A のキューを停止します。ただし、要求タイプ C では、コンポーネント 0 はアイドル状態になる最初のコンポーネントではありません。 ドライバーは、要求の種類 C のキューを停止しません (以前に行いました)。

この例で説明されている手法を使用するには、ドライバーは、各セカンダリ キューの EvtIoCanceledOnQueue コールバック関数も登録する必要があります。 セカンダリ キュー内で要求が取り消された場合、ドライバーはこのコールバックを使用して、対応するコンポーネントごとに PoFxIdleComponent を呼び出します。 これにより、要求をセカンダリ キューに転送する前に、要求ハンドラーが PoFxActivateComponent を呼び出したときに取得した電源参照が解放されます。