程式設計 DMA 硬體
[僅適用于 KMDF]
本主題描述匯流排主機 DMA 裝置的 KMDF 驅動程式通常會在其 EvtProgramDma 事件回呼函式中提供的功能。 如果您的驅動程式使用架構的 DMA 支援,驅動程式必須提供此回呼。 這項資訊也適用于具有硬體中斷 之系統模式 DMA 裝置 的 KMDF 驅動程式。
在 IRQL = DISPATCH_LEVEL 呼叫 的 EvtProgramDma 回呼 函式會程式設計裝置以啟動 DMA 傳輸。 此回呼函式的輸入參數會提供傳輸的方向 (輸入或輸出) 和散佈/收集清單。 如果傳輸是由單一封包所組成,散佈/收集清單會包含單一元素。
EvtProgramDma 回呼函式會使用驅動程式的 EvtDevicePrepareHardware回呼函式收到的硬體資源來設定裝置的程式。 如果 EvtProgramDma 回呼 函式成功對硬體進行程式,則會傳回 TRUE。
在硬體完成 DMA 傳輸之後,硬體通常會發出中斷,而且系統會呼叫驅動程式的 EvtInterruptIsr 回呼函式。 驅動程式的 EvtInterruptIsr 回呼函式通常:
清除硬體中斷。
視需要儲存中斷的內容資訊。 在回呼函式傳回且系統降低 IRQL (之後,這項資訊可能會遺失,因為降低 IRQL 可讓) 發生額外的中斷。
呼叫 WdfInterruptQueueDpcForIsr 來排程 EvtInterruptDpc 回呼函式。
EvtInterruptDpc回呼函式會使用EvtInterruptIsr回呼函式儲存的內容資訊來完成 DMA 傳輸。
如果 EvtProgramDma 回呼 函式偵測到錯誤,驅動程式可以停止交易。
若要在驅動程式偵測到錯誤時停止交易, EvtProgramDma 回 呼函式必須:
呼叫 WdfObjectDelete 以刪除 DMA 交易對象,或呼叫 WdfDmaTransactionRelease 釋放並重複使用 DMA 交易對象。
如果交易與架構要求物件相關聯,請重新佇列 I/O 要求或完成 I/O 要求。 若要擷取要求的控制碼,驅動程式可以呼叫 WdfDmaTransactionGetRequest。
傳回 FALSE。
下列程式碼範例說明步驟 1 和 4,取自 PLX9x5x 範例的 EvtProgramDma 回呼函式,以取得 Read.c 檔案中的讀取要求。
// 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);
}