DPC ルーチンの記述
DpcForIsr ルーチンと CustomDpc ルーチンの主な役割は、次のデバイス I/O 操作がすぐに開始され、現在の IRP を完了することです。
DpcForIsr または CustomDpc ルーチンによって行われる追加の作業は、ドライバーの設計とデバイスの性質によって異なります。 たとえば、 DpcForIsr ルーチンまたは CustomDpc ルーチンでは、次のいずれかを実行することもできます。
タイムアウトまたは失敗した操作を再試行する。
IoAllocateErrorLogEntry を呼び出し、デバイス I/O エラーを報告するようにエラー ログ パケットを設定し、 IoWriteErrorLogEntry を呼び出します。
I/O エラーの処理の詳細については、 エラーのログ記録を参照してください。
ドライバーが バッファー I/O を使用する場合、または IRP がデバイス制御操作を指定する場合は、IRP を完了する前に、デバイスから読み取られたデータを Irp->AssociatedIrp.SystemBuffer のシステム バッファーに転送します。
ドライバーが 直接 I/O を使用し、大きな転送をより小さな部分に分割する必要がある場合は、完了した各部分転送操作に関する状態を保存し、次の部分転送範囲を計算し、ドライバーが提供する SynchCritSection ルーチンを使用して、次の部分転送操作用にデバイスをプログラムします。
バッファーされた I/O を使用するドライバーでも、デバイスの転送機能が制限されている場合は、転送要求を分割する必要があります。
ドライバーがパケット ベースの DMA を使用する場合は、各デバイス転送操作の後に FlushAdapterBuffers を呼び出し、一連の部分転送が完了し、完全な転送要求が満たされたときに FreeAdapterChannel または FreeMapRegisters を呼び出します。
要求された転送が 1 つの DMA 操作によって部分的にしか満たされない場合、通常、 DpcForIsr または CustomDpc ルーチンは、IRP の指定されたバイト数が完全に転送されるまで、1 つ以上の DMA 操作を設定します。
DMA の使用方法の詳細については、 「アダプター オブジェクトと DMA」を参照してください。
ドライバーがプログラムされた I/O (PIO) を使用する場合には、現在の IRP が読み取りを要求する場合は、各転送操作の最後に KeFlushIoBuffers を呼び出します。
要求された転送が 1 つの PIO 操作によって部分的にしか満たされない場合、通常、 DpcForIsr または CustomDpc ルーチンは、IRP の指定されたバイト数が完全に転送されるまで、1 つ以上の転送操作を設定します。
PIO の使用の詳細については、 「ダイレクト I/O の使用」を参照してください。
WDM 以外のドライバーに ControllerControl ルーチンがある場合は、要求された操作が完了したときに IoFreeController を呼び出します。
通常、 DpcForIsr または CustomDpc ルーチンは、IRP を満たすためにドライバーのデバイス I/O 処理の大部分を実行します。 これらのルーチンは、ドライバーのディスパッチ ルーチンを使用してデバイスに IRP をキューイングする責任の一部も共有します。
次の一般的な設計ガイドラインを考慮してください。
DpcForIsr または CustomDpc ルーチンは、この呼び出しを安全に行うことができるとすぐに IoStartNextPacket を呼び出す必要があります。つまり、ドライバーの StartIo ルーチンまたはその他のルーチンでリソースの競合や競合状態を引き起こすことなく、 StartIo ルーチンによって実行されます。
ドライバーが IRP の独自のキューを管理する場合、その DpcForIsr または CustomDpc ルーチンは、安全に次の IRP をデキューし、次の要求に対してデバイスを設定できるようになった場合にはすぐにドライバーに通知する必要があります。
DpcForIsr または CustomDpc ルーチンは、 IoStartNextPacket を呼び出す必要があります。そうしない場合には、次の要求のデバイス I/O 処理を開始できるようになった段階で、適切なドライバー ルーチンに通知する必要があります。 ドライバーとそのデバイスによっては、 DpcForIsr または CustomDpc ルーチンが IoCompleteRequest を使用して現在の IRP を完了する前にこれが発生する可能性があります。または、このルーチンが現在の IRP を完了してコントロールを返す直前に発生する可能性があります。