DMA 転送の完了
[KMDF のみに適用]
通常、ドライバーの EvtInterruptDpc コールバック関数は、各 DMA 転送の処理を完了します。
まず、複数の DMA トランザクションが同時に進行することがあるため、EvtInterruptDpc コールバック関数は、完了した転送がどの DMA トランザクションに関連付けられているかを判断する必要があります。 コールバック関数は、DMA トランザクションの開始時にドライバーが格納したトランザクション ハンドルを取得することでこれを行うことができます。 デバイス拡張機能を取得するために、PLX9x5x サンプルでは、Private.h ヘッダー ファイルに PLxGetDeviceContext という関数を定義します。
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_EXTENSION, PLxGetDeviceContext)
次に、ドライバーの EvtInterruptDpc コールバックで、次の処理を行います。
WDFDMATRANSACTION dmaTransaction;
PDEVICE_EXTENSION devExt;
...
devExt = PLxGetDeviceContext(WdfInterruptGetDevice(Interrupt));
...
dmaTransaction = devExt->WriteDmaTransaction;
次に、EvtInterruptDpc コールバック関数は、次のいずれかの転送完了メソッドを呼び出すことによって、転送が完了したことをフレームワークに通知する必要があります。
転送が正常に完了し、ハードウェアが転送されたバイト数を報告しない場合、WdfDmaTransactionDmaCompleted。
転送が正常に完了し、ハードウェアが転送されたバイト数 (または転送されなかったバイト数) を報告した場合、またはドライバーがエラーを検出し、転送を再試行するために転送回数を 0 に指定した場合、WdfDmaTransactionDmaCompletedWithLength。 ドライバーが転送カウント 0 を指定した場合、フレームワークは、残りバイト数から 0 を減算し、EvtProgramDma コールバック関数に同じ転送を送信します。
ハードウェアがアンダーランまたはエラー状態を報告する場合、WdfDmaTransactionDmaCompletedFinal。
ドライバーは、WdfDmaTransactionGetCurrentDmaTransferLength を呼び出して、完了した転送の元の長さを取得できます。 この呼び出しは、ドライバーが転送されなかったバイト数をデバイスが報告する場合に便利です。元の転送長から転送されていないバイト数を減算し、WdfDmaTransactionGetCurrentDmaTransferLength を呼び出して実際の転送サイズを報告できるからです。
上記の各転送完了メソッドは、(DMA トランザクション全体ではなく) 1 つの DMA 転送が完了したことをフレームワークに通知します。 ドライバーは、これらのメソッドのいずれかを呼び出した後、トランザクションがさらに転送を必要とするかどうかを確認するためメソッドの戻り値をチェックします。
完了メソッドの戻り値が FALSE の場合、フレームワークは DMA トランザクションの処理を完了するために追加の DMA 転送が必要であると判断しました。
通常、ドライバーの EvtInterruptDpc コールバック関数は単に戻ります。 フレームワークは、ドライバーの EvtProgramDma コールバック関数をもう一度呼び出し、コールバック関数は次の転送に向けてハードウェアをプログラムできます。
転送完了メソッドはステータス値を提供します。この場合、常に STATUS_MORE_PROCESSING_REQUIRED です。
戻り値が TRUE の場合、DMA トランザクションに対してそれ以上の転送は行われません。
転送完了メソッドは、状態値を提供します。 状態の値が STATUS_SUCCESS場合 は、DMA トランザクションのすべての転送が完了し、ドライバーは DMA トランザクションを完了する必要があります。 状態値がそれ以外の場合は、エラーが発生し、DMA トランザクションが完了していない可能性があります。
EvtInterruptDpc コールバック関数がエラーを検出した場合 (通常はタイマーの期限切れ、または転送エラーを通知するハードウェア割り込みのため)、ドライバーはトランザクションの現在の転送を再開できます。
トランザクションの現在の転送を再開するために、ドライバーの EvtInterruptDpc コールバック関数は、TransferedLength パラメーターを 0 に設定して WdfDmaTransactionDmaCompletedWithLength を呼び出すことができます。