Partager via


Modèle d’appel de base pour les routines DMA version 3

Pour effectuer un transfert DMA qui utilise les routines de la version 3 de l’interface des opérations DMA, votre pilote doit suivre les étapes décrites dans la liste suivante. Ces étapes sont communes aux appareils subordonnés et aux appareils bus-master. La version 3 de cette interface est disponible à partir de Windows 8. Pour plus d’informations sur les routines de cette interface, consultez DMA_OPERATIONS.

Étape 1 : Obtenir un objet d’adaptateur DMA

En vue d’un transfert DMA, le pilote appelle la routine IoGetDmaAdapter pour obtenir un objet d’adaptateur DMA. Un objet adaptateur DMA est un objet logiciel qui représente un appareil maître de bus ou une ligne de requête sur un contrôleur DMA système. Cet objet contient l’interface des opérations DMA pour le bus utilisé pour transférer des données vers ou depuis l’appareil. En outre, cet objet synchronise l’accès du pilote aux ressources partagées requises pour effectuer le transfert. Pour plus d’informations, consultez Présentation des objets adaptateurs.

Étape 2 : Obtenir une description des ressources DMA requises

Le pilote appelle la routine GetDmaTransferInfo pour obtenir une description des ressources DMA dont il a besoin pour effectuer le transfert.

Les paramètres d’entrée de cet appel décrivent la mémoire tampon à utiliser pour le transfert et la direction (lecture ou écriture) du transfert.

Les exigences en matière de ressources obtenues à partir de cet appel incluent le nombre de registres de mappage et la taille de la liste de dispersion/rassemblement nécessaires pour décrire la mémoire tampon de données pour le transfert. Dans l’appel suivant à la routine AllocateAdapterChannelEx (voir l’étape 3), le pilote fournit le nombre de registres de mappage en tant que paramètre d’entrée.

Étape 3 : Demander les ressources DMA requises

Le pilote appelle la routine AllocateAdapterChannelEx pour allouer des ressources à affecter à l’objet d’adaptateur DMA. Ces ressources incluent un canal DMA et des registres cartographiques.

Un appel AllocateAdapterChannelEx peut être asynchrone ou synchrone.

Si l’indicateur DMA_SYNCHRONOUS_CALLBACK n’est pas défini, l’appel est asynchrone. Dans ce cas, le paramètre ExecutionRoutine pointe vers une routine d’exécution fournie par l’appelant appelée lorsque les ressources demandées sont disponibles. Si elle réussit, un appel AllocateAdapterChannelEx asynchrone retourne STATUS_SUCCESS sans attendre l’exécution de la routine d’exécution.

Si l’indicateur DMA_SYNCHRONOUS_CALLBACK est défini, l’appel AllocateAdapterChannelEx est synchrone. Dans ce cas, le paramètre ExecutionRoutine dans l’appel est facultatif et AllocateAdapterChannelEx se comporte comme suit :

  • Si ExecutionRoutine n’est pas NULL et que les ressources DMA peuvent être allouées immédiatement, AllocateAdapterChannelEx appelle la routine d’exécution dans le contexte du thread appelant. Une fois la routine d’exécution terminée, AllocateAdapterChannelEx retourne STATUS_SUCCESS. Si les ressources ne sont pas immédiatement disponibles, AllocateAdapterChannelEx échoue et retourne le code d’état d’erreur STATUS_INSUFFICIENT_RESOURCES.

  • Si ExecutionRoutine a la valeur NULL et que AllocateAdapterChannelEx peut immédiatement allouer les ressources DMA, AllocateAdapterChannelEx retourne STATUS_SUCCESS. Si toutes les ressources ne sont pas immédiatement disponibles, l’appel échoue avec le code d’état d’erreur STATUS_INSUFFICIENT_RESOURCES.

Pour les appels synchrones qui retournent STATUS_SUCCESS, si le paramètre MapRegisterBase à AllocateAdapterChannelEx n’est pas NULL, AllocateAdapterChannelEx écrit l’adresse de base des registres de mappage alloués à l’adresse pointée par le paramètre MapRegisterBase . Si ExecutionRoutine a la valeur NULL, MapRegisterBase doit être non NULL. Si ExecutionRoutine n’est pas NULL, le paramètre MapRegisterBase à AllocateAdapterChannelEx est facultatif et la routine d’exécution reçoit l’adresse de base du registre de carte en tant que paramètre d’entrée.

Pour les appels AllocateAdapterChannelEx asynchrones, ExecutionRoutine doit être non NULL et la routine d’exécution reçoit l’adresse de base du registre de carte en tant que paramètre d’entrée.

Dans les appels suivants à la routine MapTransferEx (voir l’étape 5), le pilote fournit l’adresse de base du registre de carte en tant que paramètre d’entrée.

Si ExecutionRoutine n’est pas NULL, la routine d’exécution retourne une valeur d’état pour indiquer la destruction des ressources allouées. Pour les transferts DMA système, cette valeur de retour doit être KeepObject. Cette valeur informe le système d’exploitation que l’objet adaptateur (et toutes ses ressources allouées) est en cours d’utilisation et ne doit pas être libéré. Si aucune routine d’exécution n’est fournie, le pilote doit à la place appeler la routine FreeAdapterObject et fournir KeepObject comme paramètre AllocationOption .

Étape 4 : Si nécessaire, annulez la demande de ressource en attente

Une fois qu’un appel AllocateAdapterChannelEx met en file d’attente un adaptateur DMA pour attendre les ressources DMA, le pilote peut, si nécessaire, appeler la routine CancelAdapterChannel pour annuler la demande de ressource en attente.

Si CancelAdapterChannel retourne TRUE, la demande de ressource est annulée avec succès. Si une routine d’exécution a été fournie dans l’appel AllocateAdapterChannelEx , cette routine ne s’exécute pas.

Si CancelAdapterChannel retourne FALSE, la demande de ressource ne peut pas être annulée, car elle a déjà été accordée. Si une routine d’exécution a été fournie dans l’appel AllocateAdapterChannelEx , cette routine est appelée.

Étape 5 : Initialiser les ressources DMA et démarrer le transfert DMA

Le pilote appelle MapTransferEx pour initialiser les ressources DMA et démarrer le transfert DMA. Cet appel peut se produire dans le même thread de pilote qui appelle AllocateAdapterChannelEx, ou dans la routine d’exécution que le pilote fournit à AllocateAdapterChannelEx. Si plusieurs appels MapTransferEx sont requis pour transférer l’intégralité de la mémoire tampon de données DMA, un appel MapTransferEx ultérieur peut se produire dans la routine d’achèvement de l’appel MapTransferEx précédent.

MapTransferEx prend en charge les MDL chaînés en tant que paramètres d’entrée. Chaque MDL décrit une région de la mémoire tampon DMA contiguë en mémoire virtuelle. Lorsque MapTransferEx génère la liste de points/regroupements, il gère automatiquement les transitions d’une région de mémoire tampon pratiquement contiguë vers la suivante sans intervention du pilote. Pour plus d’informations, consultez Using the MapTransferEx Routine.

Pour un transfert DMA système, un pointeur vers une routine d’achèvement DMA peut être transmis à MapTransferEx dans le paramètre DmaCompletionRoutine facultatif. Cette routine est planifiée pour s’exécuter au niveau de répartition en réponse à une interruption du contrôleur DMA système qui indique que le transfert DMA est terminé.

Si MapTransferEx ne parvient pas à mapper l’intégralité de la taille de transfert demandée, il définit le paramètre de sortie *Length sur la longueur mappée et retourne STATUS_SUCCESS.

Étape 6 : Si nécessaire, effectuez des opérations spécifiques au matériel

MapTransferEx retourne STATUS_SUCCESS pour indiquer que le transfert DMA est lancé avec succès. Sur certaines plateformes, le pilote peut avoir à effectuer une action supplémentaire, en dehors de l’appel MapTransferEx , pour démarrer le transfert, mais ce type de démarrage différé n’est pas nécessaire pour toutes les plateformes. Les pilotes ne doivent pas dépendre de ces délais pour les décisions relatives à l’utilisation et à la libération des ressources allouées.

Les routines de l’interface des opérations DMA conservent la cohérence du cache pour les transferts DMA d’une manière transparente pour les pilotes qui utilisent ces routines. Sur les plateformes qui n’appliquent pas la cohérence du cache dans le matériel, MapTransferEx garantit que les caches de données processeur sont vidés avant les transferts en écriture (mémoire à appareil). Pour les transferts en lecture (appareil à mémoire), les caches sont invalidés pendant l’appel à la routine FlushAdapterBuffersEx (voir l’étape 8) qui suit chaque appel MapTransferEx .

Étape 7 : Recevoir une notification lorsque le transfert DMA se termine

Lorsqu’un transfert DMA est terminé, le pilote est averti de l’une des deux manières suivantes :

  • Une interruption pour le pilote de périphérique, pour un périphérique maître de bus
  • Exécution de la routine d’achèvement fournie par le pilote, pour un périphérique subordonné qui utilise un contrôleur DMA système

Pour un transfert DMA système, un pilote peut fournir une routine d’achèvement à MapTransferEx en tant que paramètre d’entrée.

Étape 8 : Vider les données qui restent dans le cache

Une fois le transfert DMA terminé, le pilote doit appeler la routine FlushAdapterBuffersEx pour vider les données qui restent dans le cache. Le pilote doit appeler FlushAdapterBuffersEx après chaque appel MapTransferEx .

Si un appel MapTransferEx mappe uniquement une partie de la mémoire tampon de données DMA, le pilote doit appeler MapTransferEx à nouveau pour mapper les données restantes. Un transfert complexe peut nécessiter plusieurs appels MapTransferEx . Pour chaque appel MapTransferEx supplémentaire, répétez les étapes 5 à 8.

Étape 9 : Libérer le canal DMA et les registres cartographiques

Une fois l’intégralité de la mémoire tampon de données DMA mappée et le transfert final terminé, le pilote doit appeler la routine FreeAdapterChannel pour libérer le canal DMA et tous les registres de carte précédemment alloués.

Étape 10 : Libérer l’objet adaptateur DMA

Une fois que tous les transferts DMA sont terminés et que tous les registres de carte précédemment alloués sont libérés, le pilote appelle la routine PutDmaAdapter pour libérer l’objet adaptateur.