NDIS dispersione/raccolta DMA
Attenzione
Per i processori Arm e Arm64, è consigliabile che i writer di driver NDIS usino WDF DMA o WDM DMA anziché NDIS Scatter/Gather DMA.
Per altre informazioni su WDF DMA, vedere Gestione delle operazioni DMA nei driver KMDF.
Per altre informazioni su WDM DMA, vedere gli argomenti figlio correlati a DMA di Gestione dell'input/output per i driver.
I driver miniport NDIS possono usare il metodo DMA (SGDMA) di dispersione/raccolta per trasferire i dati tra una scheda di interfaccia di rete e una memoria di sistema. Un trasferimento DMA riuscito richiede che l'indirizzo fisico dei dati sia incluso in un intervallo di indirizzi supportato dalla scheda di interfaccia di rete. HAL fornisce un meccanismo per i driver per ottenere l'elenco indirizzi fisici per una catena MDL e, se necessario, eseguirà il double-buffer dei dati in un intervallo di indirizzi fisici.
Nelle versioni di NDIS precedenti a NDIS 6.0, il supporto SGDMA nei driver miniport e NDIS è limitato in alcuni aspetti e in particolare non funziona correttamente in uno scenario di invio multipacket. Il supporto SGDMA di NDIS 6.0 supera queste limitazioni, fornendo un'interfaccia semplice per i driver miniport.
Cronologia di NDIS SGDMA
Nelle versioni di NDIS precedenti a NDIS 6.0, NDIS ottiene un elenco di raccolta a dispersione (SG) per ogni pacchetto prima di inviare il pacchetto al driver miniport. NDIS gestisce anche il caso in cui il tentativo originale di ottenere l'elenco SG non riesce a causa di una frammentazione eccessiva. In questo caso, NDIS esegue il double-buffer del pacchetto in un buffer contiguo e riprova. HAL può anche eseguire il double buffer dei dati in un indirizzo fisico supportato dalla scheda di interfaccia di rete se, ad esempio, l'indirizzo fisico dei dati è superiore al massimo a 32 bit e la scheda di interfaccia di rete non supporta DMA a 64 bit.
Per evitare una situazione di deadlock, NDIS ottiene un elenco sg per un pacchetto e invia un pacchetto alla volta. Se NDIS tenta di eseguire il mapping di tutti i pacchetti prima di inviarli al driver miniport, il sistema potrebbe esaurire le risorse. In questo caso, NDIS è in attesa che i registri della mappa diventino disponibili mentre alcuni registri mappa sono bloccati per i pacchetti che non sono stati inviati. I pacchetti bloccati non possono essere riutilizzati.
Questo approccio al supporto di SGDMA presenta le limitazioni seguenti:
Poiché il pacchetto viene mappato prima che venga eseguito il mapping al driver miniport, il driver non può ottimizzare per pacchetti o pacchetti troppo frammentati. Il driver miniport non può duplicare il buffer del pacchetto in un indirizzo fisico noto.
Non è garantito che la matrice di indirizzi fisici passata al driver miniport esegue il mapping all'indirizzo virtuale dei dati originali. Pertanto, se il driver modifica i dati all'indirizzo virtuale nella catena MDL prima di inviarli, le modifiche apportate ai dati non vengono riflesse nei dati negli indirizzi fisici. In questo caso, la scheda di interfaccia di rete invia i dati non modificati.
NDIS è limitato all'invio di un pacchetto alla volta per evitare un deadlock a causa di problemi di risorsa. Questo non è così efficiente come l'invio di più pacchetti.
Poiché NDIS non può determinare le funzionalità di trasmissione dei driver miniport, non può preallocare l'archiviazione per un buffer elenco SG. Pertanto, NDIS deve allocare l'archiviazione necessaria in fase di esecuzione. Questo non è così efficiente come preallocare l'archiviazione.
Le funzioni HAL che allocano un elenco SG devono essere chiamate in IRQL = DISPATCH_LEVEL. NDIS non dispone delle informazioni IRQL correnti, quindi deve impostare irQL su DISPATCH_LEVEL anche se è già in DISPATCH_LEVEL. Questo non è efficiente se irQL è già in DISPATCH_LEVEL.
Vantaggi del supporto di NDIS SGDMA
Nell'interfaccia NDIS 6.0 e versioni successive SGDMA, NDIS non esegue il mapping del buffer dei dati prima di inviarlo al driver miniport. Invece, NDIS fornisce un'interfaccia per il driver per eseguire il mapping dei dati di rete.
Questo approccio offre i vantaggi seguenti:
Poiché NDIS fornisce l'interfaccia a HAL per il mapping dei dati di rete, i driver miniport NDIS vengono schermati dalla complessità e dai dettagli del processo di mapping.
I driver Miniport hanno accesso ai dati prima di eseguire il mapping. Pertanto, tutte le modifiche apportate ai dati originali vengono riflesse nei dati rappresentati dall'elenco SG anche se NDIS o HAL esegue il doppio buffer dei dati.
I driver miniport possono ottimizzare la trasmissione di pacchetti piccoli o altamente frammentati copiandoli in un buffer preallocato con un indirizzo fisico noto. Questo approccio evita il mapping non richiesto e migliora quindi le prestazioni del sistema.
NDIS può inviare più buffer al driver miniport in modo sicuro. Ciò comporta un minor numero di chiamate ai driver miniport e quindi migliora le prestazioni del sistema.
I driver miniport possono preallocare la memoria per un elenco sg come parte dei blocchi di descrittore di trasmissione. Pertanto, i driver NDIS o miniport non sono necessari per allocare memoria per gli elenchi sg in fase di esecuzione.
Poiché i driver miniport possono essere eseguiti in IRQL = DISPATCH_LEVEL, i driver miniport possono evitare chiamate non necessarie per generare irQL a DISPATCH_LEVEL. Ad esempio, poiché il completamento di un invio avviene nel contesto di un DPC di interruzione, i driver miniport possono liberare l'elenco SG senza generare irQL.
Registrazione e registrazione dei canali DMA
Un driver miniport NDIS chiama la funzione NdisMRegisterScatterGatherDma dalla funzione MiniportInitializeEx per registrare un canale DMA con NDIS.
Il driver miniport passa una descrizione DMA a NdisMRegisterScatterGatherDma nel parametro DmaDescription . NdisMRegisterScatterGatherDma restituisce una dimensione per il buffer che deve essere abbastanza grande per contenere l'elenco di dispersione/raccolta. I driver miniport devono usare questa dimensione per preallocare l'archiviazione per elenchi di dispersione/raccolta.
Il driver miniport passa anche NdisMRegisterScatterGatherDma i punti di ingresso per le funzioni MiniportXxx chiamate da NDIS per elaborare l'elenco di dispersione/raccolta. NDIS chiama la funzione MiniportProcessSGList del driver miniport dopo che HAL ha compilato l'elenco di dispersione/raccolta per un buffer. NdisMRegisterScatterGatherDma fornisce un handle nel parametro pNdisMiniportDmaHandle , che il driver miniport deve usare nelle chiamate successive alle funzioni DMA a dispersione/raccolta NDIS.
Un driver miniport NDIS chiama la funzione NdisMDeregisterScatterGatherDma dalla funzione MiniportHaltEx per rilasciare le risorse DMA a dispersione/raccolta.
Allocazione e liberazione di elenchi a dispersione/raccolta
Un driver miniport NDIS chiama la funzione NdisMAllocateNetBufferSGList nella funzione MiniportSendNetBufferLists . Il driver miniport chiama NdisMAllocateNetBufferSGList una volta per ogni struttura NET_BUFFER che deve eseguire il mapping. Dopo aver reso disponibili le risorse e HAL ha pronto l'elenco SG, NDIS chiama la funzione MiniportProcessSGList del driver. NDIS può chiamare MiniportProcessSGList prima o dopo la chiamata del driver miniport a NdisMAllocateNetBufferSGList .
Per migliorare le prestazioni del sistema, l'elenco di dispersione/raccolta viene generato dai dati di rete a partire dall'inizio del MDL specificato nel membro CurrentMdl della struttura di NET_BUFFER_DATA associata. L'inizio dei dati di rete nell'elenco SG viene offset dall'inizio dell'elenco SG dal valore specificato nel membro CurrentMdlOffsetdella struttura NET_BUFFER_DATA associata.
Durante la gestione di un DPC per un interruzione completa di invio e dopo che il driver miniport non necessita più dell'elenco SG, il driver miniport deve chiamare la funzione NdisMFreeNetBufferSGList per liberare l'elenco SG.
Nota Non chiamare NdisMFreeNetBufferSGList mentre il driver o l'hardware accedono ancora alla memoria descritta dalla struttura NET_BUFFER associata all'elenco di dispersione/raccolta.
Prima di accedere ai dati ricevuti, i driver miniport devono chiamare NdisMFreeNetBufferSGList per scaricare la cache di memoria.