デバイス電源状態についての IRP_MN_SET_POWER の処理
デバイス設定電源 IRP は、単一のデバイスの状態の変更を要求し、デバイスのスタック内のすべてのドライバーに送信されます。 このような IRP は、I/O スタックの場所の Power.Type メンバーで DevicePowerState を指定します。
ドライバーは、スタックの下に移動する電源オフ IRP を処理します。 電源投入 IRP の場合、ドライバーは、IRP がスタックを下に移動する際に IoCompletion ルーチンを設定し、IRP がスタックを上に戻る際に IoCompletion ルーチン内の IRP を処理します。 一般的なデバイス スタックのドライバーは、以下のようにデバイス設定電源 IRP を処理します。
ほとんどのフィルター ドライバーは、IoMarkIrpPending をそのまま呼び出して、IRP を次の下位ドライバーに渡し (「電話 IRP の受け渡し」を参照)、DispatchPower ルーチンから STATUS_PENDING を返す必要があります。 ただし、フィルター ドライバーによっては、受信 IRP のキューやデバイス電源状態の保存など、デバイス固有のタスクを最初に実行する必要があります。
ファンクション ドライバーは、IoMarkIrpPending を呼び出して、デバイス固有のタスク (保留中の I/O 要求の完了、受信 I/O 要求のキュー、デバイス コンテキストの保存、デバイスの電源変更など) を実行し、必要に応じて IoCompletion ルーチンを設定して、デバイスの電源 IRP を次の下位ドライバーに渡します (「電源の IRP の受け渡し」を参照)。 DispatchPower ルーチンから STATUS_PENDING を返します。
これを行うことができる場合、バス ドライバーはデバイスの電源を変更した後、PoSetPowerState を呼び出して、新しいデバイスの電源状態を電源マネージャーに通知します。 Windows Server 2003、Windows XP、Windows 2000 でのみ、ドライバーは PoStartNextPowerIrp を呼び出して、電源状態を設定した後、次の電源 IRP を開始する必要があります。 その後、ドライバーは IO_NO_INCREMENT を指定して IRP を完了します。 ドライバーがすぐに IRP を完了できない場合、IoMarkIrpPending を呼び出し、DispatchPower ルーチンから STATUS_PENDING を返して、後で IRP を完了します。
ターゲット デバイスが既に要求された電源状態にある場合でも、各ファンクションまたはフィルター ドライバーは、次の下位ドライバーに IRP を渡す必要があります。 すべての設定電源 IRP は、デバイス スタックから (IRP を完了する) バス ドライバーまで移動する必要があります。
バス ドライバーの上にあるファンクション ドライバーとフィルター ドライバーは、デバイスの設定電源 IRP に失敗してはなりません。 バス ドライバーは、デバイスが取り出された場合、または取り出し処理中に、デバイスの電源投入 IRP に失敗する可能性があります。
ドライバー スタック内の各ドライバー (ファンクション、フィルター、およびバス ドライバー) は、PoSetPowerState を呼び出して、対応するデバイス オブジェクトの電源状態の変化を電源マネージャーに通知する必要があります。
デバイスの電源投入と電源オフに関連付けられている他のドライバー タスクと同様、PoSetPowerState の呼び出しは、デバイスの電源がオンになった後 (新しい状態が D0 の場合)、またはデバイスの電源がオフになるまで (新しい状態が他の状態の場合) に発生する必要があります。
各ドライバーは、デバイスの電源状態を追跡する必要があります。 電源マネージャーは、この情報をドライバーに提供しません。
デバイスの電源状態に対する IRP_MN_SET_POWER 要求を処理している間、ドライバーは可能な限り迅速に DispatchPower ルーチンから戻る必要があります。 ドライバーは、同じ IRP を処理するコードによって通知されるカーネル イベントの DispatchPower ルーチンで待機してはなりません。 電源 IRP はシステム全体で同期されるため、デッドロックが発生する可能性があります。
特にマルチメディア アプリケーションの場合、最高レベルのシステム パフォーマンスを確保するため、ドライバーは、PASSIVE_LEVEL と同じ割り込み要求レベル (IRQL) で時間のかかる操作を実行する必要があります。 IRQL= PASSIVE_LEVEL で操作を実行するため、ドライバーは専用スレッドまたはシステム ワーカー スレッドを使用できます。 マルチメディア プラットフォームのドライバー パフォーマンスの最適化に関するガイドラインについては、「ストリーミング メディア デバイス設計ガイド」をご覧ください。
以下のセクションで説明するように、ドライバーが電源 IRP を処理するために実行する必要がある正確な手順は、デバイスの電源をオンにするかオフにするかによって異なります。