完成 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,如果傳輸成功完成,而且硬體未報告傳輸位元組的數量。
WdfDmaTransactionDmaCompletedWithLength,如果傳輸成功完成,且硬體報告傳輸的位元元組計數(或未傳輸的位元組計數),或驅動程式偵測到錯誤,並指定零的傳輸計數來重試傳輸。 如果驅動程式指定零的傳輸計數,則架構會從剩餘的位元組數量減去零,因此會將相同的傳輸傳送至 EvtProgramDma 回呼函式。
WdfDmaTransactionDmaCompletedFinal,如果硬體報告執行不足或失敗狀況。
您的驅動程式可以呼叫 WdfDmaTransactionGetCurrentDmaTransferLength,以取得已完成傳輸的原始長度。 如果您的裝置報告未傳輸的位元組計數,此呼叫會很有用,因為驅動程式可以從原始傳輸長度減去非傳輸位元組數目,然後呼叫 WdfDmaTransactionGetCurrentDmaTransferLength 來報告實際的傳輸大小。
上述每個傳輸完成方法都會通知架構單一 DMA 傳輸(不是整個 DMA 交易) 已完成。 在驅動程式呼叫下列其中一種方法之後,驅動程式會檢查方法的傳回值,以查看交易是否需要更多傳輸:
如果完成方法的傳回值 FALSE,則架構已判斷完成處理 DMA 交易需要額外的 DMA 傳輸。
一般而言,驅動程式的 EvtInterruptDpc 回呼函式只會傳回。 架構會再次呼叫驅動程式的 EvtProgramDma 回呼函式,而回呼函式可以程式設計硬體以進行下一次傳輸。
傳輸完成的方式會提供一個狀態值,在此情況下,該狀態值始終為STATUS_MORE_PROCESSING_REQUIRED。
如果傳回值 TRUE,則 DMA 交易不會再發生任何傳輸。
傳輸完成方法會提供狀態值。 如果狀態值是STATUS_SUCCESS,則 DMA 交易的所有傳輸都會完成,而且驅動程式必須 完成 DMA 交易。 如果狀態值是任何其他值,則發生錯誤且 DMA 交易可能尚未完成。
如果 EvtInterruptDpc 回呼函式偵測到錯誤,這通常是因為定時器過期或硬體中斷指示傳輸錯誤,驅動程式可以重新啟動交易當前的傳輸。
若要重新啟動交易目前的傳輸,驅動程式的 EvtInterruptDpc 回呼函式可以呼叫 WdfDmaTransactionDmaCompletedWithLength,並將 transferedLength 參數設為零。