[KMDF にのみ適用]
このトピックでは、バス マスター DMA デバイスの KMDF ドライバーが EvtProgramDma イベント コールバック関数で通常提供する機能について説明します。 ドライバーがフレームワークの DMA サポートを使用している場合は、このコールバックを指定する必要があります。 この情報は、ハードウェア割り込みを持つ システム モード DMA デバイス の KMDF ドライバーにも適用されます。
IRQL = DISPATCH_LEVEL で呼び出される EvtProgramDma コールバック関数は、 DMA 転送を開始するようにデバイスをプログラムします。 このコールバック関数の入力パラメーターは、転送の方向 (入力または出力) と散布図/収集リストを提供します。 転送が 1 つのパケットで構成されている場合、散布図/収集リストには 1 つの要素が含まれます。
EvtProgramDma コールバック関数は、ドライバーの EvtDevicePrepareHardware コールバック関数が受け取ったハードウェア リソースを使用して、デバイスをプログラムします。 EvtProgramDma コールバック関数がハードウェアを正常にプログラムすると、TRUE が返されます。
ハードウェアが DMA 転送を完了すると、通常は割り込みが発行され、システムはドライバーの EvtInterruptIsr コールバック関数を呼び出します。 通常、ドライバーの EvtInterruptIsr コールバック関数は次のとおりです。
ハードウェア割り込みをクリアします。
必要に応じて、割り込みのコンテキスト情報を保存する。 この情報は、コールバック関数が戻り、システムが IRQL を下げた後に失われる可能性があります (IRQL を下げると、追加の割り込みが発生する可能性があるため)。
WdfInterruptQueueDpcForIsr を呼び出して、EvtInterruptDpc コールバック関数をスケジュールします。
EvtInterruptDpc コールバック関数は、EvtInterruptIsr コールバック関数が保存したコンテキスト情報を使用して DMA 転送を完了します。
EvtProgramDma コールバック関数がエラーを検出した場合、ドライバーはトランザクションを停止できます。
ドライバーがエラーを検出したときにトランザクションを停止するには、 EvtProgramDma コールバック関数は次の手順を実行する必要があります。
WdfDmaTransactionDmaCompletedFinal を呼び出します。
DMA トランザクション オブジェクトを削除するには WdfObjectDelete を呼び出し、DMA トランザクション オブジェクトを解放して再利用するには WdfDmaTransactionRelease を呼び出します。
トランザクションがフレームワーク要求オブジェクトに関連付けられている場合は、I/O 要求を再キューに入れ直すか、I/O 要求を完了します。 要求のハンドルを取得するために、ドライバーは WdfDmaTransactionGetRequest を呼び出すことができます。
FALSE を返します。
手順 1 と 4 は、READ.c ファイル内の読み取り要求に対する PLX9x5x サンプルの EvtProgramDma コールバック関数から取得した次のコード例に示されています。
// If errors occur in the EvtProgramDma callback,
// release the DMA transaction object and complete the request.
if (errors) {
NTSTATUS status;
//
// Must abort the transaction before deleting.
//
(VOID) WdfDmaTransactionDmaCompletedFinal(Transaction, 0, &status);
ASSERT(NT_SUCCESS(status));
PLxReadRequestComplete( Transaction, STATUS_INVALID_DEVICE_STATE );
TraceEvents(TRACE_LEVEL_ERROR, DBG_READ,
"<-- PLxEvtProgramReadDma: errors ****");
return FALSE;
}
この例では、 PLxReadRequestComplete 関数を呼び出して、手順 2 と 3 を実行します。
VOID
PLxReadRequestComplete(
IN WDFDMATRANSACTION DmaTransaction,
IN NTSTATUS Status
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
WDFREQUEST request;
size_t bytesTransferred;
//
// Get the associated request from the transaction.
//
request = WdfDmaTransactionGetRequest(DmaTransaction);
ASSERT(request);
//
// Get the final bytes transferred count.
//
bytesTransferred = WdfDmaTransactionGetBytesTransferred( DmaTransaction );
TraceEvents(TRACE_LEVEL_INFORMATION, DBG_DPC,
"PLxReadRequestComplete: Request %p, Status %!STATUS!, "
"bytes transferred %d\n",
request, Status, (int) bytesTransferred );
WdfDmaTransactionRelease(DmaTransaction);
//
// Complete this Request.
//
WdfRequestCompleteWithInformation( request, Status, bytesTransferred);
}