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 master bus. 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 préparation d’un transfert DMA, le pilote appelle la routine IoGetDmaAdapter pour obtenir un objet d’adaptateur DMA. Un objet d’adaptateur DMA est un objet logiciel qui représente un appareil master bus ou une ligne de requête sur un contrôleur DMA système. Cet objet contient l’interface d’opérations DMA pour le bus utilisé pour transférer des données vers ou à partir de 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 d’adaptateur.

É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 besoins en ressources obtenus à partir de cet appel incluent le nombre de registres de carte et la taille de la liste de points/regroupement nécessaire pour décrire la mémoire tampon de données pour le transfert. Dans l’appel suivant à la routine AllocateAdapterChannelEx (voir étape 3), le pilote fournit le nombre de registres de carte 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 de mappage.

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 qui est appelée lorsque les ressources demandées sont disponibles. En cas de réussite, un appel asynchrone AllocateAdapterChannelEx 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’a pas la valeur 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 l’exécution de la routine d’exécution terminée, AllocateAdapterChannelEx retourne STATUS_SUCCESS. Si les ressources ne sont pas immédiatement disponibles, AllocateAdapterChannelEx échoue et retourne l’erreur status code STATUS_INSUFFICIENT_RESOURCES.

  • Si ExecutionRoutine a la valeur NULL et qu’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 une erreur status code STATUS_INSUFFICIENT_RESOURCES.

Pour les appels synchrones qui retournent STATUS_SUCCESS, si le paramètre MapRegisterBasesur AllocateAdapterChannelEx n’est pas NULL, AllocateAdapterChannelEx écrit l’adresse de base des registres de carte alloués dans l’adresse pointée par le paramètre MapRegisterBase . Si ExecutionRoutine a la valeur NULL, MapRegisterBase doit être non NULL. Si ExecutionRoutine n’a pas la valeur NULL, le paramètre MapRegisterBasesur 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 asynchrones AllocateAdapterChannelEx , ExecutionRoutine doit avoir une valeur 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 étape 5), le pilote fournit l’adresse de base du registre de carte en tant que paramètre d’entrée.

Si ExecutionRoutine n’a pas la valeur NULL, la routine d’exécution retourne une valeur status pour indiquer la disposition 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 appeler la routine FreeAdapterObject et fournir KeepObject comme paramètre AllocationOption .

Étape 4 : si nécessaire, annuler 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. 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 nécessaires 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 dll MDL chaînées en tant que paramètres d’entrée. Chaque MDL décrit une région de la mémoire tampon DMA contiguë dans la 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ë à l’autre sans intervention du pilote. Pour plus d’informations, consultez Utilisation de la routine MapTransferEx.

Pour un transfert DMA système, un pointeur vers une routine d’achèvement DMA peut être passé à MapTransferEx dans le paramètre DmaCompletionRoutine facultatif. Cette routine est planifiée pour s’exécuter au niveau de la 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 qui a été mappée et retourne STATUS_SUCCESS.

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

MapTransferEx retourne STATUS_SUCCESS pour indiquer que le transfert DMA a démarré avec succès. Sur certaines plateformes, le pilote peut devoir prendre des mesures supplémentaires, en dehors de l’appel MapTransferEx , pour démarrer le transfert, mais ce type de démarrage différé n’est pas obligatoire pour toutes les plateformes. Les pilotes ne doivent pas dépendre de tels retards pour prendre des 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 de 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 du processeur sont vidés avant les transferts d’é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 se termine, le pilote est averti de l’une des deux manières suivantes :

  • Interruption du pilote de périphérique pour un appareil master bus
  • Exécution de la routine d’achèvement fournie par le pilote, pour un appareil 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 toutes les données qui restent dans le cache

Une fois le transfert DMA terminé, le pilote doit appeler la routine FlushAdapterBuffersEx pour vider toutes 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 de mappage

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

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

Une fois tous les transferts DMA terminés et 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.