Share via


DMA 転送の完了

通常、ドライバーの EvtInterruptDpc コールバック関数が、各 DMA 転送の処理を完了させます。

DMA トランザクションは同時に複数実行できるため、EvtInterruptDpc コールバック関数は、完了した転送が関連付けられている DMA トランザクションをまず判断する必要があります。コールバック関数は、ドライバーが DMA トランザクションの開始時に保存したトランザクション ハンドルを取得することでこれを実行できます。ドライバーは、必要に応じて WdfDmaTransactionGetDevice および WdfDmaTransactionGetRequest を呼び出して、トランザクション ハンドルを含むコンテキスト情報を保存した可能性のあるオブジェクトを取得できます。

次に、EvtInterruptDpc コールバック関数は、転送が完了したことをフレームワークに通知する必要があります。これを行うには、次のいずれかの転送完了メソッドを呼び出します。

  • 転送が正常に完了し、ハードウェアから転送済みバイト数が報告されない場合は、WdfDmaTransactionDmaCompleted を呼び出します。

  • 転送が正常に完了し、ハードウェアから転送済みバイト数 (または未転送バイト数) が報告される場合、またはドライバーがエラーを検出し、転送カウントに 0 を指定することによって転送を再試行する場合は、WdfDmaTransactionDmaCompletedWithLength を呼び出します。ドライバーが転送カウントに 0 を指定した場合、フレームワークは残りのバイト数から 0 を差し引いて、同じ転送を EvtProgramDma コールバック関数に渡します。

  • ハードウェアからアンダーラン状態またはエラー状態が報告された場合は、WdfDmaTransactionDmaCompletedFinal を呼び出します。

ドライバーは、WdfDmaTransactionGetCurrentDmaTransferLength を呼び出して、完了した転送の元の長さを取得できます。この呼び出しは、デバイスから未転送バイト数が報告される場合に便利です。ドライバーが、転送の元の長さから未転送バイト数を差し引いてから、WdfDmaTransactionGetCurrentDmaTransferLength を呼び出すことで、実際の転送サイズを報告できるためです。

前に示した転送完了メソッドはそれぞれ、単一の DMA 転送 (DMA トランザクション 全体ではない) が完了したことをフレームワークに通知します。ドライバーは、これらのメソッドのうちいずれかを呼び出した後、メソッドの戻り値をチェックして、トランザクションでさらに転送を行う必要があるかどうかを確認します。

  • 完了メソッドの戻り値が FALSE の場合は、DMA トランザクションの処理を完了するために、さらに DMA 転送が必要であるとフレームワークが判断しています。

    通常、ドライバーの EvtInterruptDpc コールバック関数から制御が戻ります。フレームワークは、ドライバーの EvtProgramDma コールバック関数を再度呼び出します。これにより、このコールバック関数で次の転送用にハードウェアをプログラムできるようになります。

    転送完了メソッドは状態の値を返しますが、この場合、この値は常に STATUS_MORE_PROCESSING_REQUIRED です。

  • 戻り値が TRUE の場合、DMA トランザクションでこれ以上の転送は行われません。

    転送完了メソッドは、状態の値を返します。状態の値が STATUS_SUCCESS の場合、DMA トランザクションのすべての転送は完了しています。これ以外の状態の値が返された場合は、エラーが発生しており、DAM トランザクションが完了していない可能性があります。

転送完了メソッドが FALSE を返した後は、ドライバーが DMA トランザクションを完了させる必要があります。