Condividi tramite


Modello di chiamata di base per routine DMA versione 3

Per eseguire un trasferimento DMA che usa le routine nella versione 3 dell'interfaccia operativa DMA, il driver deve seguire la procedura descritta nell'elenco seguente. Questi passaggi sono comuni sia ai dispositivi subordinati che ai dispositivi master del bus. La versione 3 di questa interfaccia è disponibile a partire da Windows 8. Per altre informazioni sulle routine in questa interfaccia, vedere DMA_OPERATIONS.

Passaggio 1: Ottenere un oggetto adattatore DMA

In preparazione per un trasferimento DMA, il driver chiama la routine IoGetDmaAdapter per ottenere un oggetto adattatore DMA. Un oggetto adattatore DMA è un oggetto software che rappresenta un dispositivo master del bus o una linea di richiesta in un controller DMA di sistema. Questo oggetto contiene l'interfaccia operativa DMA per il bus utilizzato per trasferire dati da o verso il dispositivo. Inoltre, questo oggetto sincronizza l'accesso del driver alle risorse condivise necessarie per eseguire il trasferimento. Per altre informazioni, vedere Introduzione agli oggetti adapter.

Passaggio 2: Ottenere una descrizione delle risorse DMA necessarie

Il driver chiama la routine GetDmaTransferInfo per ottenere una descrizione delle risorse DMA necessarie per eseguire il trasferimento.

I parametri di input per questa chiamata descrivono il buffer di memoria da usare per il trasferimento e la direzione (lettura o scrittura) del trasferimento.

I requisiti delle risorse ottenuti da questa chiamata includono il numero di registri mappa e le dimensioni dell'elenco di dispersione/raccolta necessari per descrivere il buffer dei dati per il trasferimento. Nella chiamata successiva alla routine AllocateAdapterChannelEx (vedere il passaggio 3), il driver fornisce il conteggio dei registri della mappa come parametro di input.

Passaggio 3: Richiedere le risorse DMA necessarie

Il driver chiama la routine AllocateAdapterChannelEx per allocare risorse da assegnare all'oggetto adapter DMA. Queste risorse includono un canale DMA e registri mappa.

Una chiamata AllocateAdapterChannelEx può essere asincrona o sincrona.

Se il flag DMA_SYNCHRONOUS_CALLBACK non è impostato, la chiamata è asincrona. In questo caso, il parametro ExecutionRoutine punta a una routine di esecuzione fornita dal chiamante che viene chiamata quando sono disponibili le risorse richieste. In caso di esito positivo, una chiamata allocateAdapterChannelEx asincrona restituisce STATUS_SUCCESS senza attendere l'esecuzione della routine di esecuzione.

Se il flag DMA_SYNCHRONOUS_CALLBACK è impostato, la chiamata AllocateAdapterChannelEx è sincrona. In questo caso, il parametro ExecutionRoutine nella chiamata è facoltativo e AllocateAdapterChannelEx si comporta come segue:

  • Se ExecutionRoutine è diverso da NULL e le risorse DMA possono essere allocate immediatamente, AllocateAdapterChannelEx chiama la routine di esecuzione nel contesto del thread chiamante. Al termine dell'esecuzione della routine di esecuzione, AllocateAdapterChannelEx restituisce STATUS_SUCCESS. Se le risorse non sono immediatamente disponibili, AllocateAdapterChannelEx ha esito negativo e restituisce il codice di stato di errore STATUS_INSUFFICIENT_RESOURCES.

  • Se ExecutionRoutine è NULL e AllocateAdapterChannelEx può allocare immediatamente le risorse DMA, AllocateAdapterChannelEx restituisce STATUS_SUCCESS. Se tutte le risorse non sono immediatamente disponibili, la chiamata ha esito negativo con codice di stato di errore STATUS_INSUFFICIENT_RESOURCES.

Per le chiamate sincrone che restituiscono STATUS_SUCCESS, se il parametro MapRegisterBase per AllocateAdapterChannelEx è diverso da NULL, AllocateAdapterChannelEx scrive l'indirizzo di base della mappa allocata registra all'indirizzo a cui punta il parametro MapRegisterBase . Se ExecutionRoutine è NULL, MapRegisterBase deve essere diverso da NULL. Se ExecutionRoutine è diverso da NULL, il parametro MapRegisterBase per AllocateAdapterChannelEx è facoltativo e la routine di esecuzione riceve l'indirizzo di base del registro della mappa come parametro di input.

Per le chiamate asincrone AllocateAdapterChannelEx , ExecutionRoutine deve essere diverso da NULL e la routine di esecuzione riceve l'indirizzo di base del registro mappa come parametro di input.

Nelle chiamate successive alla routine MapTransferEx (vedere il passaggio 5), il driver fornisce l'indirizzo di base del registro mappa come parametro di input.

Se ExecutionRoutine è diverso da NULL, la routine di esecuzione restituisce un valore di stato per indicare l'eliminazione delle risorse allocate. Per i trasferimenti DMA di sistema, questo valore restituito deve essere KeepObject. Questo valore informa il sistema operativo che l'oggetto adapter (e tutte le risorse allocate) è in uso e non deve essere liberato. Se non viene fornita alcuna routine di esecuzione, il driver deve invece chiamare la routine FreeAdapterObject e specificare KeepObject come parametro AllocationOption .

Passaggio 4: Se necessario, annullare la richiesta di risorsa in sospeso

Dopo che una chiamata AllocateAdapterChannelEx accoda una scheda DMA per attendere le risorse DMA, il driver può, se necessario, chiamare la routine CancelAdapterChannel per annullare la richiesta di risorsa in sospeso.

Se CancelAdapterChannel restituisce TRUE, la richiesta di risorsa viene annullata correttamente. Se è stata specificata una routine di esecuzione nella chiamata AllocateAdapterChannelEx , questa routine non viene eseguita.

Se CancelAdapterChannel restituisce FALSE, la richiesta di risorsa non può essere annullata perché è già stata concessa. Se è stata specificata una routine di esecuzione nella chiamata AllocateAdapterChannelEx , questa routine verrà chiamata.

Passaggio 5: Inizializzare le risorse DMA e avviare il trasferimento DMA

Il driver chiama MapTransferEx per inizializzare le risorse DMA e avviare il trasferimento DMA. Questa chiamata può verificarsi nello stesso thread del driver che chiama AllocateAdapterChannelEx oppure potrebbe verificarsi nella routine di esecuzione fornita dal driver a AllocateAdapterChannelEx. Se è necessaria più di una chiamata MapTransferEx per trasferire l'intero buffer di dati DMA, potrebbe verificarsi una chiamata MapTransferEx successiva nella routine di completamento per la chiamata MapTransferEx precedente.

MapTransferEx supporta mdls concatenati come parametri di input. Ogni MDL descrive un'area del buffer DMA contigua nella memoria virtuale. Quando MapTransferEx compila l'elenco di dispersione/raccolta, gestisce automaticamente le transizioni da un'area del buffer virtualmente contigua alla successiva senza l'intervento del driver. Per altre informazioni, vedere Uso della routine MapTransferEx.

Per il trasferimento DMA di sistema, un puntatore a una routine di completamento DMA può essere passato a MapTransferEx nel parametro facoltativo DmaCompletionRoutine . Questa routine viene pianificata per l'esecuzione a livello di invio in risposta a un interrupt dal controller DMA di sistema che indica che il trasferimento DMA è completo.

Se MapTransferEx non è in grado di eseguire il mapping dell'intera dimensione di trasferimento richiesta, il parametro di output *Length verrà impostato sulla lunghezza mappata e restituirà STATUS_SUCCESS.

Passaggio 6: Se necessario, eseguire operazioni specifiche dell'hardware

MapTransferEx restituisce STATUS_SUCCESS per indicare che il trasferimento DMA è stato avviato correttamente. In alcune piattaforme, il driver potrebbe dover eseguire un'azione aggiuntiva, al di fuori della chiamata MapTransferEx , per avviare il trasferimento, ma questo tipo di avvio ritardato non è necessario per tutte le piattaforme. I driver non devono dipendere da tali ritardi per le decisioni relative all'uso e alla liberazione delle risorse allocate.

Le routine nell'interfaccia delle operazioni DMA mantengono la coerenza nella cache per i trasferimenti DMA in modo trasparente per i driver che usano queste routine. Nelle piattaforme che non applicano la coerenza della cache nell'hardware, MapTransferEx garantisce che le cache dei dati del processore vengano scaricate prima dei trasferimenti di scrittura (da memoria a dispositivo). Per i trasferimenti di lettura (da dispositivo a memoria), le cache vengono invalidate durante la chiamata alla routine FlushAdapterBuffersEx (vedere il passaggio 8) che segue ogni chiamata MapTransferEx .

Passaggio 7: Ricevere una notifica al termine del trasferimento DMA

Al termine del trasferimento DMA, il driver riceve una notifica in uno dei due modi seguenti:

  • Interruzione del driver di dispositivo per un dispositivo master del bus
  • Esecuzione della routine di completamento fornita dal driver, per un dispositivo subordinato che usa un controller DMA di sistema

Per il trasferimento DMA di sistema, un driver può fornire una routine di completamento a MapTransferEx come parametro di input.

Passaggio 8: Scaricare tutti i dati che rimangono nella cache

Al termine del trasferimento DMA, il driver deve chiamare la routine FlushAdapterBuffersEx per scaricare tutti i dati che rimangono nella cache. Il driver deve chiamare FlushAdapterBuffersEx dopo ogni chiamata MapTransferEx .

Se una chiamata MapTransferEx esegue il mapping solo di una parte del buffer di dati DMA, il driver deve chiamare di nuovo MapTransferEx per eseguire il mapping dei dati rimanenti. Un trasferimento complesso potrebbe richiedere diverse chiamate MapTransferEx . Per ogni chiamata MapTransferEx aggiuntiva, ripetere i passaggi da 5 a 8.

Passaggio 9: Liberare il canale DMA e registrare le mappe

Dopo il mapping dell'intero buffer di dati DMA e il completamento del trasferimento finale, il driver deve chiamare la routine FreeAdapterChannel per liberare il canale DMA ed eventuali registri mappa allocati in precedenza.

Passaggio 10: Rilasciare l'oggetto adapter DMA

Al termine di tutti i trasferimenti DMA e vengono liberati tutti i registri mappa allocati in precedenza, il driver chiama la routine PutDmaAdapter per rilasciare l'oggetto adapter.