Partager via


NDIS Scatter/Collect DMA

Attention

Pour les processeurs Arm et Arm64, nous recommandons vivement que les enregistreurs de pilotes NDIS utilisent WDF DMA ou WDM DMA au lieu de NDIS Scatter/Gather DMA.

Pour plus d’informations sur WDF DMA, consultez Gestion des opérations DMA dans les pilotes KMDF.

Pour plus d’informations sur WDM DMA, consultez les rubriques enfants relatives à DMA de La gestion des entrées/sorties pour les pilotes.

Les pilotes de miniport NDIS peuvent utiliser la méthode DMA Scatter/Gather (SGDMA) pour transférer des données entre une carte réseau et la mémoire système. Un transfert DMA réussi nécessite que l’adresse physique des données se trouve dans une plage d’adresses prise en charge par la carte réseau. HAL fournit un mécanisme permettant aux pilotes d’obtenir la liste d’adresses physiques d’une chaîne MDL et, si nécessaire, double la mise en mémoire tampon des données dans une plage d’adresses physique.

Dans les versions NDIS antérieures à NDIS 6.0, la prise en charge de SGDMA dans les pilotes miniport et NDIS est limitée à certains égards, et en particulier ne fonctionne pas bien dans un scénario d’envoi multipacket. La prise en charge de NDIS 6.0 SGDMA surmonte ces limitations tout en fournissant une interface simple pour les pilotes miniport.

Historique de NDIS SGDMA

Dans les versions NDIS antérieures à NDIS 6.0, NDIS obtient une liste de collecte de points (SG) pour chaque paquet avant d’envoyer le paquet au pilote miniport. NDIS gère également le cas où la tentative initiale d’obtention de la liste SG échoue en raison d’une fragmentation excessive. Dans ce cas, NDIS double-tampon le paquet dans une mémoire tampon contiguë et tente à nouveau. HAL peut également doubler la mise en mémoire tampon des données vers une adresse physique prise en charge par la carte réseau si, par exemple, l’adresse physique des données est supérieure à la limite de 32 bits et que la carte réseau ne prend pas en charge DMA 64 bits.

Pour éviter une situation d’interblocage, NDIS obtient une liste SG pour un paquet et envoie un paquet à la fois. Si NDIS tente de mapper tous les paquets avant de les envoyer au pilote miniport, le système peut manquer de ressources. Dans ce cas, NDIS attend que les registres de carte soient disponibles, tandis que certains registres de carte sont verrouillés pour les paquets qui n’ont pas été envoyés. Les paquets verrouillés ne peuvent pas être réutilisés.

Cette approche de la prise en charge de SGDMA présente les limitations suivantes :

  • Étant donné que le paquet est mappé avant d’atteindre le pilote miniport, le pilote ne peut pas optimiser pour les petits paquets ou paquets trop fragmentés. Le pilote miniport ne peut pas doubler la mise en mémoire tampon du paquet sur une adresse physique connue.

  • Il n’existe aucune garantie que le tableau d’adresses physiques transmis par NDIS au pilote miniport correspond à l’adresse virtuelle des données d’origine. Par conséquent, si le pilote modifie les données à l’adresse virtuelle dans la chaîne MDL avant de les envoyer, les modifications apportées aux données ne sont pas répercutées dans les données dans les adresses physiques. Dans ce cas, la carte réseau envoie les données non modifiées.

  • NDIS est limité à l’envoi d’un paquet à la fois pour éviter un blocage dû à des problèmes de ressources. Cela n’est pas aussi efficace que l’envoi de plusieurs paquets.

  • Étant donné que NDIS ne peut pas déterminer les fonctionnalités de transmission des pilotes miniport, il ne peut pas préallouer le stockage pour une mémoire tampon de liste SG. Par conséquent, NDIS doit allouer le stockage nécessaire au moment de l’exécution. Cela n’est pas aussi efficace que la pré-allocation du stockage.

  • Les fonctions HAL qui allouent une liste SG doivent être appelées dans IRQL = DISPATCH_LEVEL. NDIS ne disposant pas des informations IRQL actuelles, il doit donc définir l’IRQL sur DISPATCH_LEVEL même s’il est déjà à DISPATCH_LEVEL. Cela n’est pas efficace si l’IRQL est déjà à DISPATCH_LEVEL.

Avantages de la prise en charge de NDIS SGDMA

Dans l’interface NDIS 6.0 et ultérieure SGDMA, NDIS ne mappe pas la mémoire tampon de données avant de l’envoyer au pilote miniport. Au lieu de cela, NDIS fournit une interface permettant au pilote de mapper les données réseau.

Cette approche offre les avantages suivants :

  • Étant donné que NDIS fournit l’interface à HAL pour le mappage des données réseau, NDIS protège les pilotes de miniport contre la complexité et les détails du processus de mappage.

  • Les pilotes miniport ont accès aux données avant qu’elles ne sont mappées. Par conséquent, toutes les modifications apportées aux données d’origine sont répercutées dans les données représentées par la liste SG, même si NDIS ou HAL double-tampon les données.

  • Les pilotes Miniport peuvent optimiser la transmission de paquets de petite taille ou très fragmentés en les copiant dans une mémoire tampon préallouée avec une adresse physique connue. Cette approche évite le mappage qui n’est pas nécessaire et améliore par conséquent les performances du système.

  • NDIS peut envoyer plusieurs mémoires tampons au pilote miniport en toute sécurité. Cela entraîne moins d’appels aux pilotes de miniport et améliore donc les performances du système.

  • Les pilotes Miniport peuvent préallouer la mémoire d’une liste SG dans le cadre des blocs de descripteur de transmission. Par conséquent, les pilotes NDIS ou miniport ne sont pas nécessaires pour allouer de la mémoire pour les listes SG au moment de l’exécution.

  • Étant donné que les pilotes miniport peuvent s’exécuter sur IRQL = DISPATCH_LEVEL, les pilotes miniport peuvent éviter les appels inutiles pour augmenter l’IRQL à DISPATCH_LEVEL. Par exemple, étant donné que la fin d’un envoi se produit dans le contexte d’un DPC d’interruption, les pilotes miniport peuvent libérer la liste SG sans déclencher l’IRQL.

Inscription et annulation de l’inscription de canaux DMA

Un pilote miniport NDIS appelle la fonction NdisMRegisterScatterGatherDma à partir de sa fonction MiniportInitializeEx pour inscrire un canal DMA auprès de NDIS.

Le pilote miniport transmet une description DMA à NdisMRegisterScatterGatherDma dans le paramètre DmaDescription . NdisMRegisterScatterGatherDma retourne une taille pour la mémoire tampon qui doit être suffisamment grande pour contenir la liste de points/regroupements. Les pilotes miniport doivent utiliser cette taille pour préallouer le stockage pour les listes de points/regroupements.

Le pilote miniport transmet également NdisMRegisterScatterGatherDma les points d’entrée pour les fonctions MiniportXxx que NDIS appelle pour traiter la liste de points/de regroupement. NDIS appelle la fonction MiniportProcessSGList du pilote miniport une fois que HAL a créé la liste de points/regroupements pour une mémoire tampon. NdisMRegisterScatterGatherDma fournit un handle dans le paramètre pNdisMiniportDmaHandle , que le pilote miniport doit utiliser dans les appels ultérieurs aux fonctions NDIS scatter/gather DMA.

Un pilote de miniport NDIS appelle la fonction NdisMDeregisterScatterGatherDma à partir de sa fonction MiniportHaltEx pour libérer des points/collecter des ressources DMA.

Allocation et libération de listes de points/regroupements

Un pilote miniport NDIS appelle la fonction NdisMAllocateNetBufferSGList dans sa fonction MiniportSendNetBufferLists . Le pilote miniport appelle NdisMAllocateNetBufferSGList une fois pour chaque NET_BUFFER structure qu’il doit mapper. Une fois que les ressources sont disponibles et que HAL dispose de la liste SG, NDIS appelle la fonction MiniportProcessSGList du pilote. NDIS peut appeler MiniportProcessSGList avant ou après l’appel du pilote miniport à NdisMAllocateNetBufferSGList .

Pour améliorer les performances du système, la liste de points/regroupements est générée à partir des données réseau à partir du début de la MDL spécifiée au niveau du membre CurrentMdl de la structure de NET_BUFFER_DATA associée. Le début des données réseau dans la liste SG est décalé par rapport au début de la liste SG par la valeur spécifiée dans le membre CurrentMdlOffset de la structure NET_BUFFER_DATA associée.

Lors de la gestion d’un DPC pour une interruption d’envoi complet, et une fois que le pilote miniport n’a plus besoin de la liste SG, le pilote miniport doit appeler la fonction NdisMFreeNetBufferSGList pour libérer la liste SG.

Note N’appelez pas NdisMFreeNetBufferSGList tant que le pilote ou le matériel accède toujours à la mémoire décrite par la structure NET_BUFFER associée à la liste de points/regroupements. 

Avant d’accéder aux données reçues, les pilotes miniport doivent appeler NdisMFreeNetBufferSGList pour vider le cache de mémoire.