Completamento di un trasferimento DMA

[Si applica solo a KMDF]

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

Prima di tutto, poiché più transazioni DMA possono essere in corso simultaneamente, la funzione di callback EvtInterruptDpc deve determinare quale transazione DMA è associata al trasferimento completato. La funzione di callback può eseguire questa operazione recuperando l'handle delle transazioni archiviato dal driver all'avvio della transazione DMA. Per recuperare l'estensione del dispositivo, l'esempio PLX9x5x5x 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 quanto segue:

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

Successivamente, la funzione callback EvtInterruptDpc deve informare il framework che un trasferimento è 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 numero di 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 riprovare 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 sottorun o di errore.

Il driver può chiamare WdfDmaTransactionGetCurrentDmaTransferLength per ottenere la lunghezza originale del trasferimento completato. Questa chiamata è utile se il dispositivo segnala un numero 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.

Ognuno dei metodi di completamento del trasferimento precedente informa il framework che è stato completato un singolo trasferimento DMA (non l'intera transazione DMA). 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 restituisce. 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 si verificheranno più 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 vengono completati e il driver deve completare la transazione DMA. Se il valore di stato è qualsiasi altro elemento, 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 di una scadenza timer o di un interruzione 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.