Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
[Gilt nur für KMDF]
In diesem Thema werden die Funktionen beschrieben, die ein KMDF-Treiber für ein Busmaster-DMA-Gerät in der Regel in seiner EvtProgramDma-Ereignisrückruffunktion bereitstellt. Wenn Ihr Treiber die DMA-Unterstützung des Frameworks verwendet, müssen Sie diesen Rückruf bereitstellen. Diese Informationen gelten auch für einen KMDF-Treiber für ein DMA-Gerät im Systemmodus , das über einen Hardwareunterbruch verfügt.
Die EvtProgramDma-Rückruffunktion , die bei IRQL = DISPATCH_LEVEL aufgerufen wird, programmiert das Gerät, um eine DMA-Übertragung zu starten. Die Parameter für diese Rückruffunktion liefern die Übertragungsrichtung (Eingabe oder Ausgabe) und eine Scatter/Gather-Liste. Wenn die Übertragung aus einem einzelnen Paket besteht, enthält die Scatter-Gather-Liste ein einzelnes Element.
Die Rückruffunktion EvtProgramDma programmiert das Gerät mithilfe der Hardwareressourcen, die die EvtDevicePrepareHardware-Rückruffunktion des Treibers empfangen haben. Wenn die EvtProgramDma-Rückruffunktion die Hardware erfolgreich programmiert, wird WAHR zurückgegeben.
Nachdem die Hardware die DMA-Übertragung abgeschlossen hat, gibt sie in der Regel einen Interrupt aus, und das System ruft die EvtInterruptIsr-Rückruffunktion des Treibers auf. Die Rückruffunktion EvtInterruptIsr des Treibers bedeutet in der Regel:
Löscht den Hardwareunterbruch.
Speichert die Kontextinformationen des Interrupts, falls erforderlich. Diese Informationen gehen möglicherweise verloren, nachdem die Rückruffunktion zurückgegeben wurde, und das System verringert die IRQL (da durch das Verringern der IRQL zusätzliche Unterbrechungen auftreten können).
Ruft WdfInterruptQueueDpcForIsr auf, um eine EvtInterruptDpc-Rückruffunktion zu planen.
Die Rückruffunktion EvtInterruptDpcschließt die DMA-Übertragung mithilfe von Kontextinformationen ab, die die EvtInterruptIsr-Rückruffunktion gespeichert hat.
Wenn die EvtProgramDma-Rückruffunktion einen Fehler erkennt, kann der Treiber die Transaktion beenden.
Um eine Transaktion zu beenden, wenn der Treiber einen Fehler erkennt, muss die EvtProgramDma-Rückruffunktion Folgendes ausführen:
Rufen Sie WdfDmaTransactionDmaCompletedFinal auf.
Rufen Sie WdfObjectDelete auf, um das DMA-Transaktionsobjekt zu löschen, oder rufen Sie WdfDmaTransactionRelease auf, um das DMA-Transaktionsobjekt freizugeben und wiederzuverwenden.
Stellen Sie die E/A-Anforderung erneut ab, oder schließen Sie die E/A-Anforderung ab, wenn die Transaktion einem Framework-Anforderungsobjekt zugeordnet ist. Um ein Handle für die Anforderung abzurufen, kann der Treiber WdfDmaTransactionGetRequest aufrufen.
False zurückgeben.
Die Schritte 1 und 4 werden im folgenden Codebeispiel veranschaulicht, das aus der EvtProgramDma-Rückruffunktion des PLX9x5x-Beispiels für Leseanforderungen in der Datei "Read.c" entnommen wurde.
// 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;
}
Im Beispiel wird die PLxReadRequestComplete-Funktion aufgerufen, um die Schritte 2 und 3 auszuführen:
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);
}