Partager via


Utilisation de la routine MapTransferEx

La routine MapTransferEx initialise un ensemble de ressources DMA précédemment allouées et démarre un transfert DMA. Cette routine est disponible dans la version 3 de l’interface d’opérations DMA. La version 3 de cette interface est prise en charge à partir de Windows 8. Pour plus d’informations sur l’interface d’opérations DMA, consultez DMA_OPERATIONS.

Comparaison de MapTransferEx à MapTransfer

MapTransferEx est une version améliorée de la routine MapTransfer . MapTransfer est disponible dans toutes les versions de l’interface d’opérations DMA, à compter de la version 1 dans Windows 2000. Un appel à MapTransfer peut mapper un bloc contigu de mémoire physique à partir d’une MDL. Toutefois, la mémoire tampon de données pour un transfert DMA complexe peut être décrite par une chaîne MDL, et chaque MDL de la chaîne peut décrire plusieurs blocs de mémoire physiquement contiguë. Pour utiliser MapTransfer pour transférer une telle mémoire tampon, un pilote doit effectuer de nombreux appels à MapTransfer. En règle générale, ces appels sont effectués à l’intérieur d’une paire de boucles imbriquées. La boucle interne itère d’un bloc de mémoire physique contiguë vers le suivant dans chaque MDL, et la boucle externe itère d’une MDL à l’autre dans la chaîne MDL.

En revanche, un appel à MapTransferEx peut transférer l’intégralité de la mémoire tampon de données pour un transfert DMA complexe. Les trois paramètres MapTransferEx suivants décrivent la mémoire tampon à utiliser pour le transfert.

Paramètre Description
Mdl

Pointeur vers la première MDL d’une chaîne d’une ou plusieurs DLL. Pour plus d’informations sur les chaînes MDL, consultez Utilisation de MDL.

Offset

Décalage d’octets de la mémoire tampon à partir du début de la mémoire décrite par la chaîne MDL.

Longueur

Pointeur vers un emplacement qui contient la longueur, en octets, de la mémoire tampon de données.

Au début d’un appel MapTransferEx , la routine MapTransferEx avance dans la chaîne MDL pour trouver le début de la mémoire tampon. Le début de la mémoire tampon est spécifié par le paramètre Offset . Ensuite, en travaillant du début à la fin de la mémoire tampon, MapTransferEx construit une liste de points/regroupements dans laquelle chaque fragment de mémoire tampon dans la liste est un bloc de mémoire physiquement contigu de la chaîne MDL. Pour construire cette liste, MapTransferEx effectue des étapes d’un bloc de mémoire physiquement contigu au suivant dans chaque MDL, et d’une MDL à l’autre dans la chaîne MDL. La construction de la liste se termine lorsque la quantité totale de mémoire tampon décrite par la liste de points/regroupements est égale au nombre d’octets spécifié par le paramètre d’entrée *Length . L’ordre des fragments de mémoire tampon dans la liste de points/regroupements résultant correspond à l’ordre des blocs physiquement contigus dans la chaîne MDL.

Plusieurs appels à MapTransferEx

MapTransferEx peut ne pas toujours être en mesure de transférer une mémoire tampon de données DMA entière en un seul appel. La liste suivante décrit certaines des conditions qui peuvent nécessiter l’appel de MapTransferEx plusieurs fois pour terminer le transfert :

  • L’adaptateur DMA nécessite des registres de carte, et le nombre de registres de carte attribués à l’adaptateur n’est pas suffisant pour décrire l’intégralité de la mémoire tampon.
  • Le stockage alloué par le pilote pour contenir la liste de points/regroupements n’est pas assez grand pour contenir la liste de points/regroupements pour l’ensemble de la mémoire tampon.
  • Le transfert utilise un contrôleur DMA système qui limite le nombre de fragments de mémoire tampon qui peuvent être spécifiés dans une liste de points/regroupements matériels.

Dans tous ces cas, MapTransferEx mappe autant de la mémoire tampon de données que possible dans un appel et indique au pilote la quantité de la mémoire tampon qui a été mappée par l’appel. La liste précédente n’inclut pas d’autres conditions, telles que le comportement du cache spécifique à la plateforme, qui peuvent nécessiter plusieurs appels à MapTransferEx pour effectuer un transfert. Les plateformes matérielles futures peuvent imposer des contraintes supplémentaires sur la longueur de transfert DMA. Pour ces raisons, les développeurs de pilotes doivent concevoir leurs pilotes pour gérer correctement le cas où MapTransferEx ne peut pas mapper une mémoire tampon de données DMA entière en un seul appel.

Avant d’appeler MapTransferEx, l’appelant définit le paramètre *Length sur le nombre d’octets dans la mémoire tampon de données DMA qui doivent encore être mappés. Avant de retourner, MapTransferEx définit *Length sur le nombre d’octets dans la mémoire tampon qui ont été mappés par l’appel. Lorsqu’un appel MapTransferEx ne peut pas mapper la longueur entière de la mémoire tampon, comme spécifié par la valeur d’entrée *Length , la valeur de sortie de *Length est inférieure à sa valeur d’entrée. Si un transfert DMA nécessite au moins deux appels MapTransferEx , le pilote appelant doit obtenir la valeur de sortie *Length d’un appel avant de pouvoir spécifier la valeur d’entrée *Length pour l’appel suivant.

Par exemple, si un appel MapTransferEx peut transférer uniquement X octets vers ou depuis une mémoire tampon pour laquelle Offset = B et *Length = N (en entrée), alors, au retour, *Length = X. Pour l’appel suivant à MapTransferEx, le pilote doit définir Offset = B + X et *Length = N - X. Dans les deux appels, la même chaîne MDL est utilisée sans modification.

Si l’appelant spécifie un DmaCompletionRoutine, MapTransferEx écrit la valeur de sortie *Length avant de planifier l’exécution de DmaCompletionRoutine . Ce comportement garantit que la valeur *Length mise à jour est toujours disponible avant l’exécution de DmaCompletionRoutine . Par exemple, si un transfert DMA nécessite deux appels MapTransferEx , le DmaCompletionRoutine que les premières planifications d’appel peuvent obtenir la valeur de sortie *Length du premier appel. La routine peut ensuite utiliser cette valeur pour calculer la valeur d’entrée *Longueur pour le deuxième appel. En règle générale, le paramètre Length pointe vers un emplacement dans la valeur *CompletionContext fournie à DmaCompletionRoutine en tant que paramètre.