Delen via


DMA-hardware programmeren

[Alleen van toepassing op KMDF]

In dit onderwerp wordt de functionaliteit beschreven die een KMDF-stuurprogramma voor een DMA-apparaat met busmaster doorgaans biedt in de functie EvtProgramDma event callback. Als uw stuurprogramma gebruikmaakt van de DMA-ondersteuning van het framework, moet u deze callback opgeven. Deze informatie is ook van toepassing op een KMDF-stuurprogramma voor een DMA-apparaat in de systeemmodus met een hardware-interrupt.

De callback-functie EvtProgramDma, die wordt aangeroepen bij IRQL = DISPATCH_LEVEL, programmeert het apparaat om een DMA-overdracht te starten. De invoerparameters voor deze callback-functie leveren de richting van de overdracht (invoer of uitvoer) en een spreidings-/verzamellijst. Als de overdracht bestaat uit één pakket, bevat de spreidings-/verzamellijst één element.

De callback-functie EvtProgramDma programmeert het apparaat met behulp van de hardwarebronnen die de EvtDevicePrepareHardware callback-functie van het stuurprogramma heeft ontvangen. Als de callback-functie EvtProgramDma de hardware met succes programmeert, retourneert de functie TRUE.

Nadat de hardware de DMA-overdracht heeft voltooid, treedt er doorgaans een interrupt op en roept het systeem de callback-functie EvtInterruptIsr van het stuurprogramma aan. De callback-functie EvtInterruptIsr van het stuurprogramma wordt meestal:

  • Hiermee wordt de hardwareonderbreking gewist.

  • Slaat de contextinformatie van de interrupt op als dit nodig is. Deze informatie kan verloren gaan nadat de callback-functie werd uitgevoerd en het systeem de IRQL verlaagt, omdat het verlagen van de IRQL extra interrupts toestaat.

  • Roept WdfInterruptQueueDpcForIsr aan om een EvtInterruptDpc-callbackfunctie te plannen.

De callback-functie EvtInterruptDpcvoltooit de DMA-overdracht met behulp van contextinformatie die de callback-functie EvtInterruptIsr heeft opgeslagen.

Als de callback-functie EvtProgramDma een fout detecteert, kan het stuurprogramma de transactie stoppen.

Als u een transactie wilt stoppen wanneer het stuurprogramma een fout detecteert, moet de callbackfunctie EvtProgramDma :

  1. Roep WdfDmaTransactionDmaCompletedFinal aan.

  2. Roep WdfObjectDelete aan om het DMA-transactieobject te verwijderen of roep WdfDmaTransactionRelease aan om het DMA-transactieobject vrij te geven en opnieuw te gebruiken.

  3. De I/O-aanvraag opnieuw in de wachtrij brengen of de I/O-aanvraag voltooien als de transactie is gekoppeld aan een frameworkaanvraagobject. Om een handle naar het verzoek op te halen, kan de driver WdfDmaTransactionGetRequest aanroepen.

  4. Geef FALSE terug.

Stap 1 en 4 worden geïllustreerd in het volgende codevoorbeeld, genomen uit de functie EvtProgramDma van het PLX9x5x-voorbeeld voor callback voor leesaanvragen in het bestand 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;
    }

In het voorbeeld wordt de functie PLxReadRequestComplete aangeroepen om stap 2 en 3 uit te voeren:

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);

}