Configurazione di un'operazione di trasferimento

Quando AllocateAdapterChannel trasferisce il controllo alla routine AdapterControl di un driver, ha allocato un set di registri mappa. Tuttavia, il driver deve eseguire il mapping della memoria fisica del sistema per la richiesta di trasferimento di IRP corrente all'intervallo di indirizzi logici dell'adattatore master del bus, come indicato di seguito:

  1. Chiamare MmGetMdlVirtualAddress con MDL in Irp-MdlAddress> per ottenere un indice per l'indirizzo fisico di sistema in cui deve iniziare il trasferimento.

    Il valore restituito è un parametro obbligatorio (CurrentVa) a MapTransfer.

  2. Chiamare MapTransfer per eseguire il mapping degli intervalli di indirizzi fisici del sistema per il buffer di IRP all'intervallo di indirizzi logici dell'adattatore bus-master.

Il driver può quindi configurare l'adattatore per l'operazione di trasferimento. Nella figura seguente vengono illustrati i passaggi coinvolti nella configurazione del trasferimento.

diagramma che illustra la configurazione di un'operazione di trasferimento.

Come illustrato nella figura precedente, la routine AdapterControl di un driver configura un'operazione DMA master del bus come segue:

  1. La routine AdapterControl ottiene l'indirizzo in corrispondenza del quale avviare il trasferimento. Per il trasferimento iniziale necessario per soddisfare un'IRP, la routine AdapterControl chiama MmGetMdlVirtualAddress, passando un puntatore all'MDL in Irp-MdlAddress>, che descrive il buffer per il trasferimento DMA.

    MmGetMdlVirtualAddress restituisce un indirizzo virtuale che il driver può usare come indice per l'indirizzo fisico del sistema in cui deve iniziare il trasferimento.

    Se l'IRP richiede più operazioni di trasferimento, il driver calcola un indirizzo iniziale aggiornato, come descritto più avanti in questa sezione.

  2. La routine AdapterControl salva l'indirizzo restituito da MmGetMdlVirtualAddress o calcolato nel passaggio 1. Questo indirizzo è un parametro obbligatorio (CurrentVa) a MapTransfer.

  3. La routine AdapterControl chiama MapTransfer, che restituisce un indirizzo logico in cui il driver può programmare l'adattatore bus-master per avviare l'operazione di trasferimento. Nella chiamata a MapTransfer il driver fornisce i parametri seguenti:

    • Puntatore dell'oggetto adapter restituito da IoGetDmaAdapter

    • Puntatore a MDL in Irp-MdlAddress> per l'IRP corrente

    • Handle MapRegisterBase passato alla routine AdapterControl del driver by AllocateAdapterChannel (vedere Allocazione dell'oggetto adapter Bus-Master)

    • Valore restituito da MmGetMdlVirtualAddress se si tratta della prima chiamata a MapTransfer per l'IRP corrente

      In caso contrario, il driver fornisce un valore CurrentVa aggiornato, che indica il mapping fisico-logico successivo da eseguire. Come calcolare currentVa aggiornato viene descritto più avanti in questa sezione.

    • Puntatore a una variabile (lunghezza), che indica il numero di byte per il trasferimento

      Se il driver dispone di registri di mapping sufficienti per trasferire tutti i dati richiesti in un'unica operazione DMA e non ha vincoli specifici del dispositivo per le operazioni DMA, la lunghezza può essere impostata sul valore di Lunghezza nella posizione dello stack I/O del driver dell'IRP. Al massimo, la lunghezza di input in byte può essere (PAGE_SIZE * i numberOfMapRegisters restituiti da IoGetDmaAdapter). In caso contrario, il driver deve suddividere la richiesta, come illustrato in Divisione richieste di trasferimento e deve aggiornare il valore di Lunghezza nelle chiamate successive a MapTransfer per l'IRP corrente.

    • Valore booleano (WriteToDevice), che indica la direzione dell'operazione di trasferimento (TRUE per trasferire i dati dalla memoria al dispositivo)

  4. La routine AdapterControl configura il dispositivo per l'operazione DMA.

  5. La routine AdapterControl restituisce DeallocateObjectKeepRegisters.

Se il driver deve chiamare MapTransfer più di una volta per soddisfare l'IRP corrente, fornisce lo stesso puntatore a oggetti adattatore, puntatore Mdl , handle MapRegisterBase e direzione di trasferimento in ogni chiamata a MapTransfer. Tuttavia, il driver deve fornire i valori CurrentVa e Length aggiornati nella seconda e successiva chiamata a MapTransfer. Usare le formule seguenti per calcolare questi valori:

  • CurrentVa = CurrentVa + (lunghezza richiesta nella chiamata precedente a MapTransfer)

  • Length = Minimo ( lunghezza rimanente da trasferire, (PAGE_SIZE * NumberOfMapRegisters restituito da IoGetDmaAdapter))

Le informazioni sul contesto che ogni driver deve mantenere sui trasferimenti DMA dipende dalle esigenze del dispositivo specifico. Il contesto tipico può includere l'indirizzo virtuale corrente nell'oggetto MDL (CurrentVa), il numero di byte trasferiti finora, il numero di byte rimanenti per il trasferimento e eventualmente un puntatore all'IRP corrente.

Per i driver di dispositivi con funzionalità di dispersione/raccolta, il parametro Length to MapTransfer è sia un parametro di input che di output. In caso di ritorno da MapTransfer, indica il numero di byte di dati mappati dal sistema. Ovvero, il valore restituito di Length, in combinazione con l'indirizzo logico restituito, indica l'intervallo di indirizzi logici che l'adattatore master del bus può usare per questa parte del trasferimento in questa operazione DMA.

Nota Poiché la lunghezza viene sovrascritta da MapTransfer, seguire questa linea guida di implementazione: non passare mai un puntatore alla lunghezza nella posizione dello stack I/O del driver di un'IRP come parametro Length to MapTransfer se il dispositivo supporta la dispersione/raccolta.

In questo modo il valore potrebbe essere eliminato nell'IRP corrente, rendendo impossibile determinare se il driver ha trasferito tutti i dati richiesti.

Alla fine di ogni operazione DMA, il driver deve chiamare FlushAdapterBuffers con un puntatore a oggetti adattatore valido e l'handle MapRegisterBase per assicurarsi che tutti i dati siano stati trasferiti e per rilasciare i mapping fisici a logica per l'operazione DMA corrente. Se il driver deve configurare operazioni DMA aggiuntive per soddisfare l'IRP corrente, deve chiamare FlushAdapterBuffers dopo il completamento di ogni operazione di trasferimento.

Quando tutto il trasferimento richiesto viene completato o il driver deve restituire uno stato di errore per l'IRP, il driver deve chiamare FreeMapRegisters immediatamente dopo l'ultima chiamata a FlushAdapterBuffers per ottenere la velocità effettiva migliore possibile per l'adattatore bus-master. Nella chiamata a FreeMapRegisters, il driver deve passare il puntatore dell'oggetto adapter passato nella chiamata precedente a AllocateAdapterChannel.