Abschließen einer DMA-Übertragung

[Gilt nur für KMDF]

In der Regel schließt die EvtInterruptDpc-Rückruffunktion Ihres Treibers die Verarbeitung jeder DMA-Übertragung ab.

Da zunächst mehrere DMA-Transaktionen gleichzeitig ausgeführt werden können, muss die Rückruffunktion EvtInterruptDpc ermitteln, welcher DMA-Transaktion die abgeschlossene Übertragung zugeordnet ist. Die Rückruffunktion kann dazu das Transaktionshandle abrufen, das der Treiber beim Starten der DMA-Transaktion gespeichert hat. Um die Geräteerweiterung abzurufen, definiert das PLX9x5x-Beispiel eine Funktion namens PLxGetDeviceContext in der Headerdatei Private.h:

WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_EXTENSION, PLxGetDeviceContext)

Anschließend erfolgt im EvtInterruptDpc-Rückruf des Treibers Folgendes:

WDFDMATRANSACTION   dmaTransaction;
PDEVICE_EXTENSION   devExt;
...
devExt  = PLxGetDeviceContext(WdfInterruptGetDevice(Interrupt));
...
dmaTransaction = devExt->WriteDmaTransaction;

Als Nächstes muss die EvtInterruptDpc-Rückruffunktion das Framework darüber informieren, dass eine Übertragung abgeschlossen ist, indem sie eine der folgenden Vervollständigungsmethoden aufruft:

  • WdfDmaTransactionDmaCompleted, wenn die Übertragung erfolgreich abgeschlossen wurde und die Hardware keine Anzahl der übertragenen Bytes meldet.

  • WdfDmaTransactionDmaCompletedWithLength, wenn die Übertragung erfolgreich abgeschlossen wurde und die Hardware eine Anzahl der übertragenen Bytes (oder eine Anzahl nicht übertragener Bytes) meldet oder wenn der Treiber einen Fehler erkannt hat und eine Übertragungsanzahl von 0 angibt, um die Übertragung erneut zu versuchen. Wenn der Treiber eine Übertragungsanzahl von null angibt, subtrahiert das Framework null von der Anzahl der verbleibenden Bytes und sendet daher dieselbe Übertragung an die Rückruffunktion EvtProgramDma .

  • WdfDmaTransactionDmaCompletedFinal, wenn die Hardware eine Unterlauf- oder Fehlerbedingung meldet.

Ihr Treiber kann WdfDmaTransactionGetCurrentDmaTransferLength aufrufen, um die ursprüngliche Länge der abgeschlossenen Übertragung abzurufen. Dieser Aufruf ist nützlich, wenn Ihr Gerät eine Anzahl von Bytes meldet, die nicht übertragen wurden, da der Treiber die Anzahl der nicht übertragenen Bytes von der ursprünglichen Übertragungslänge subtrahieren und dann WdfDmaTransactionGetCurrentDmaTransferLength aufrufen kann, um die tatsächliche Übertragungsgröße zu melden.

Jede der vorherigen Transferabschlussmethoden informiert das Framework darüber, dass eine einzelne DMA-Übertragung (nicht die gesamte DMA-Transaktion) abgeschlossen ist. Nachdem Ihr Treiber eine der folgenden Methoden aufgerufen hat, überprüft der Treiber den Rückgabewert der Methode, um festzustellen, ob die Transaktion weitere Übertragungen erfordert:

  • Wenn der Rückgabewert der Vervollständigungsmethode FALSE ist, hat das Framework ermittelt, dass zusätzliche DMA-Übertragungen erforderlich sind, um die Verarbeitung der DMA-Transaktion abzuschließen.

    In der Regel gibt die EvtInterruptDpc-Rückruffunktion des Treibers einfach zurück. Das Framework ruft die EvtProgramDma-Rückruffunktion des Treibers erneut auf, und die Rückruffunktion kann die Hardware für die nächste Übertragung programmieren.

    Die Vervollständigungsmethoden stellen einen status Wert bereit, der in diesem Fall immer STATUS_MORE_PROCESSING_REQUIRED ist.

  • Wenn der Rückgabewert TRUE ist, werden keine weiteren Übertragungen für die DMA-Transaktion durchgeführt.

    Die Methoden zur Vervollständigung der Übertragung stellen einen status Wert bereit. Wenn der status Wert STATUS_SUCCESS ist, sind alle Übertragungen für die DMA-Transaktion abgeschlossen, und der Treiber muss die DMA-Transaktion abschließen. Wenn der status Wert etwas anderes ist, ist ein Fehler aufgetreten, und die DMA-Transaktion wurde möglicherweise nicht abgeschlossen.

Wenn die Rückruffunktion EvtInterruptDpc einen Fehler erkennt, in der Regel aufgrund eines Ablaufs des Timers oder eines Hardwareunterbrechungs, der einen Übertragungsfehler signalisiert, kann der Treiber die aktuelle Übertragung der Transaktion neu starten.

Um die aktuelle Übertragung der Transaktion neu zu starten, kann die EvtInterruptDpc-Rückruffunktion des Treibers WdfDmaTransactionDmaCompletedWithLength aufrufen, wobei der TransferLength-Parameter auf 0 festgelegt ist.