Condividi tramite


Completamento di un trasferimento tramite DMA

[Si applica solo a KMDF]

In genere, la funzione di callback EvtInterruptDpc del driver completa l'elaborazione di ogni trasferimento DMA.

In primo luogo, poiché più transazioni DMA possono essere in corso contemporaneamente, la funzione di callback EvtInterruptDpc deve determinare la transazione DMA a cui è associato il trasferimento completato. La funzione di callback può eseguire questa operazione recuperando l'handle di transazione archiviato dal driver all'avvio della transazione DMA. Per recuperare l'estensione del dispositivo, l'esempio PLX9x5x definisce una funzione denominata PLxGetDeviceContext nel file di intestazione Private.h:

WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_EXTENSION, PLxGetDeviceContext)

Quindi, nel callback EvtInterruptDpc del driver, esegue le operazioni seguenti:

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

Successivamente, la funzione di callback EvtInterruptDpc deve informare il framework che un trasferimento è stato completato chiamando uno dei metodi di completamento del trasferimento seguenti:

  • WdfDmaTransactionDmaCompleted, se il trasferimento è stato completato correttamente e l'hardware non segnala un conteggio dei byte trasferiti.

  • WdfDmaTransactionDmaCompletedWithLength, se il trasferimento è stato completato correttamente e l'hardware segnala un conteggio dei byte trasferiti (o un conteggio di byte non trasferiti) o se il driver ha rilevato un errore e specifica un conteggio di trasferimento pari a zero per ritentare il trasferimento. Se il driver specifica un conteggio di trasferimento pari a zero, il framework sottrae zero dal numero di byte che rimangono e quindi invia lo stesso trasferimento alla funzione di callback EvtProgramDma .

  • WdfDmaTransactionDmaCompletedFinal, se l'hardware segnala una condizione di sottoflusso o di errore.

Il driver può chiamare WdfDmaTransactionGetCurrentDmaTransferLength per ottenere la lunghezza originale del trasferimento completato. Questa chiamata è utile se il dispositivo segnala un conteggio di byte non trasferiti, perché il driver può sottrarre il numero di byte non trasferiti dalla lunghezza del trasferimento originale e quindi chiamare WdfDmaTransactionGetCurrentDmaTransferLength per segnalare le dimensioni effettive del trasferimento.

Ogni metodo di completamento del trasferimento precedente informa il framework che un singolo trasferimento DMA (non l'intera transazione DMA) è stato completato. Dopo che il driver chiama uno di questi metodi, il driver controlla il valore restituito del metodo per verificare se la transazione richiede più trasferimenti:

  • Se il valore restituito del metodo di completamento è FALSE, il framework ha determinato che sono necessari trasferimenti DMA aggiuntivi per completare l'elaborazione della transazione DMA.

    In genere, la funzione di callback EvtInterruptDpc del driver si limita a restituire. Il framework chiama di nuovo la funzione di callback EvtProgramDma del driver e la funzione di callback può programmare l'hardware per il trasferimento successivo.

    I metodi di completamento del trasferimento forniscono un valore di stato, che è sempre STATUS_MORE_PROCESSING_REQUIRED in questo caso.

  • Se il valore restituito è TRUE, non verranno eseguiti altri trasferimenti per la transazione DMA.

    I metodi di completamento del trasferimento forniscono un valore di stato. Se il valore di stato è STATUS_SUCCESS, tutti i trasferimenti per la transazione DMA sono completi e il driver deve completare la transazione DMA. Se il valore di stato è diverso, si è verificato un errore e la transazione DMA potrebbe non essere stata completata.

Se la funzione di callback EvtInterruptDpc rileva un errore, in genere a causa della scadenza di un timer o di un interrupt hardware che segnala un errore di trasferimento, il driver può riavviare il trasferimento corrente della transazione.

Per riavviare il trasferimento corrente della transazione, la funzione di callback EvtInterruptDpc del driver può chiamare WdfDmaTransactionDmaCompletedWithLength con il parametro TransferLength impostato su zero.