WdfDmaTransactionInitialize, fonction (wdfdmatransaction.h)

[S’applique uniquement à KMDF]

La méthode WdfDmaTransactionInitialize initialise une transaction DMA spécifiée.

Syntaxe

NTSTATUS WdfDmaTransactionInitialize(
  [in] WDFDMATRANSACTION   DmaTransaction,
  [in] PFN_WDF_PROGRAM_DMA EvtProgramDmaFunction,
  [in] WDF_DMA_DIRECTION   DmaDirection,
  [in] PMDL                Mdl,
  [in] PVOID               VirtualAddress,
  [in] size_t              Length
);

Paramètres

[in] DmaTransaction

Handle pour un objet de transaction DMA que le pilote a obtenu à partir d’un appel précédent à WdfDmaTransactionCreate.

[in] EvtProgramDmaFunction

Pointeur vers la fonction de rappel d’événement EvtProgramDma du pilote.

[in] DmaDirection

Valeur de type WDF_DMA_DIRECTION.

[in] Mdl

Pointeur vers une liste de descripteurs de mémoire (MDL) qui décrit la mémoire tampon qui sera utilisée pour la transaction DMA. Pour plus d’informations, consultez Remarques.

[in] VirtualAddress

Adresse virtuelle de la mémoire tampon qui sera utilisée pour la transaction DMA.

[in] Length

Nombre d’octets à transférer.

Valeur retournée

WdfDmaTransactionInitialize retourne STATUS_SUCCESS si l’opération réussit. Sinon, la méthode peut retourner l’une des valeurs suivantes.

Code de retour Description
STATUS_INSUFFICIENT_RESOURCES
Une liste de points/regroupement n’a pas pu être allouée.
STATUS_INVALID_PARAMETER
Un paramètre non valide a été détecté.
STATUS_WDF_TOO_FRAGMENTED
Le nombre d’éléments de diffusion/collecte nécessaires pour gérer la transaction était supérieur à la valeur spécifiée par l’appel du pilote à WdfDmaEnablerSetMaximumScatterGatherElements .

Pour les transactions qui ont été définies pour un transfert unique, une façon de résoudre ce problème consiste à copier les données dans une mémoire tampon contiguë physiquement, puis à initialiser la transaction avec cette mémoire tampon. Par exemple, appelez MmAllocateContiguousMemory, copiez les mémoires tampons d’origine dans le nouveau, puis appelez À nouveau WdfDmaTransactionInitialize .

STATUS_WDF_NOT_ENOUGH_MAP_REGISTERS
Cette valeur de retour s’applique uniquement aux transactions qui ont été définies pour un transfert unique.

Le nombre de registres de carte nécessaires pour mapper la transaction est supérieur au nombre réservé par l’adaptateur DMA.

Pour résoudre ce problème, le pilote peut réduire le nombre de registres de carte requis en combinant une chaîne MDL en une seule MDL.

Les pilotes utilisant le DMA de paquet et le système peuvent appeler WdfDmaTransactionAllocateResources pour réserver un certain nombre de registres de carte à partir du total alloué à l’appareil. Supposons que votre pilote a réservé 4 registres de carte sur 8 au total, mais que le transfert DMA en nécessite 6. Dans ce cas, WdfDmaTransactionInitialize échoue. Pour résoudre le problème, appelez WdfDmaTransactionFreeResources , puis appelez à nouveau WdfDmaTransactionInitialize .

Les pilotes qui utilisent la DMA de nuages de points/regroupements ne peuvent pas réserver les registres de carte.

STATUS_WDF_TOO_MANY_TRANSFERS
Cette valeur de retour s’applique uniquement aux transactions qui ont été définies pour un transfert unique.

La longueur totale de la transaction dépasse la taille de transfert maximale de l’appareil.

 

Cette méthode peut également retourner d’autres valeurs NTSTATUS.

Un bogue case activée se produit si le pilote fournit un handle d’objet non valide.

Remarques

La méthode WdfDmaTransactionInitialize prépare une opération DMA pour l’exécution, en effectuant des opérations d’initialisation telles que l’allocation de la liste de points/regroupements d’une transaction. Une fois que votre pilote a appelé WdfDmaTransactionInitialize, le pilote doit appeler WdfDmaTransactionExecute pour commencer à exécuter la transaction.

Les pilotes basés sur l’infrastructure appellent généralement WdfDmaTransactionInitialize à partir d’une fonction de rappel d’événement de file d’E/S.

Si vous créez une transaction DMA basée sur les informations contenues dans un objet de demande d’infrastructure, votre pilote doit appeler WdfDmaTransactionInitializeUsingRequest. Si vous créez une transaction DMA qui n’est pas basée sur un objet de requête, utilisez WdfDmaTransactionInitialize ou WdfDmaTransactionInitializeUsingOffset.

Le pilote peut spécifier une chaîne MDL dans le paramètre Mdl de cette méthode. Une chaîne MDL est une séquence de structures MDL que le pilote a chaînées ensemble à l’aide du membre Suivant de la structure MDL. Dans les versions de framework antérieures à la version 1.11, seuls les transferts DMA de diffusion/collecte peuvent utiliser des chaînes MDL. À compter de la version 1.11, si le pilote utilise DMA version 3, les transferts à paquet unique peuvent également utiliser des dll MDL chaînées.

Si la mémoire tampon spécifiée par le pilote est supérieure à la longueur de transfert maximale spécifiée par votre pilote lorsqu’il a appelé WdfDmaEnablerCreate ou WdfDmaTransactionSetMaximumLength, l’infrastructure décompose la transaction en plusieurs transferts.

Pour plus d’informations sur les transactions DMA, consultez Création et initialisation d’une transaction DMA.

Exemples

L’exemple de code suivant provient de l’exemple de pilote PLX9x5x . Tout d’abord, l’exemple initialise une structure WDF_OBJECT_ATTRIBUTES et crée un objet de transaction DMA. Ensuite, il obtient un MDL qui représente la mémoire tampon d’entrée d’une demande d’E/S reçue, et il obtient l’adresse virtuelle et la longueur de la mémoire tampon. Enfin, l’exemple appelle WdfDmaTransactionInitialize pour initialiser la transaction.

WDF_OBJECT_ATTRIBUTES  attributes;
PMDL  mdl;
PVOID  virtualAddress;
ULONG  length;
NTSTATUS  status;

WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(
                                        &attributes,
                                        TRANSACTION_CONTEXT
                                        );

status = WdfDmaTransactionCreate(
                                 devExt->DmaEnabler,
                                 &attributes,
                                 &dmaTransaction
                                 );
if(!NT_SUCCESS(status)) {
    goto CleanUp;
}

status = WdfRequestRetrieveInputWdmMdl(
                                       Request,
                                       &mdl
                                       );
if (!NT_SUCCESS(status)) {
    goto CleanUp;
}

virtualAddress = MmGetMdlVirtualAddress(mdl);
length = MmGetMdlByteCount(mdl);

status = WdfDmaTransactionInitialize(
                                     dmaTransaction,
                                     PLxEvtProgramWriteDma,
                                     WdfDmaDirectionWriteToDevice,
                                     mdl,
                                     virtualAddress,
                                     length
                                     );
if(!NT_SUCCESS(status)) {
    goto CleanUp;
}

Configuration requise

Condition requise Valeur
Plateforme cible Universal
Version KMDF minimale 1.0
En-tête wdfdmatransaction.h (inclure Wdf.h)
Bibliothèque Wdf01000.sys (consultez Gestion de version de la bibliothèque d’infrastructure.)
IRQL <=DISPATCH_LEVEL
Règles de conformité DDI DeferredRequestCompleted(kmdf),DriverCreate(kmdf), KmdfIrql(kmdf), KmdfIrql2(kmdf), KmdfIrqlExplicit(kmdf), MdlAfterReqCompletedIntIoctlA(kmdf),MdlAfterReqCompletedIoctlA(kmdf), MdlAfterReqCompletedReadA(kmdf), MdlAfterReqCompletedWriteA(kmdf), RequestCompleted(kmdf), RequestCompletedLocal(kmdf)

Voir aussi

EvtProgramDma

MmGetMdlByteCount

MmGetMdlVirtualAddress

WDF_DMA_DIRECTION

WdfDmaEnablerSetMaximumScatterGatherElements

WdfDmaTransactionCreate

WdfDmaTransactionExecute

WdfDmaTransactionInitializeUsingRequest