Función WdfDmaTransactionInitialize (wdfdmatransaction.h)

[Solo se aplica a KMDF]

El método WdfDmaTransactionInitialize inicializa una transacción DMA especificada.

Sintaxis

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
);

Parámetros

[in] DmaTransaction

Identificador de un objeto de transacción DMA que el controlador obtuvo de una llamada anterior a WdfDmaTransactionCreate.

[in] EvtProgramDmaFunction

Puntero a la función de devolución de llamada de eventos EvtProgramDma del controlador.

[in] DmaDirection

Valor con tipo WDF_DMA_DIRECTION.

[in] Mdl

Puntero a una lista de descriptores de memoria (MDL) que describe el búfer que se usará para la transacción DMA. Vea más información en Comentarios.

[in] VirtualAddress

Dirección virtual del búfer que se usará para la transacción DMA.

[in] Length

Número de bytes que se van a transferir.

Valor devuelto

WdfDmaTransactionInitialize devuelve STATUS_SUCCESS si la operación se realiza correctamente. De lo contrario, el método podría devolver uno de los valores siguientes.

Código devuelto Descripción
STATUS_INSUFFICIENT_RESOURCES
No se pudo asignar una lista de dispersión o recopilación.
STATUS_INVALID_PARAMETER
Se ha detectado un parámetro no válido.
STATUS_WDF_TOO_FRAGMENTED
El número de elementos de dispersión y recopilación necesarios para controlar la transacción era mayor que el valor que especificó la llamada del controlador a WdfDmaEnablerSetMaximumScatterGatherElements .

Para las transacciones que se establecieron para una sola transferencia, una manera de corregir esto es copiar los datos en un búfer físico contiguo y, a continuación, inicializar la transacción con ese búfer. Por ejemplo, llame a MmAllocateContiguousMemory, copie los búferes originales en el nuevo y, a continuación, vuelva a llamar a WdfDmaTransactionInitialize .

STATUS_WDF_NOT_ENOUGH_MAP_REGISTERS
Este valor devuelto solo se aplica a las transacciones que se establecieron para una única transferencia.

El número de registros de mapa necesarios para asignar la transacción es mayor que el número que el adaptador DMA ha reservado.

Para corregirlo, el controlador puede reducir el número de registros de mapa necesarios mediante la combinación de una cadena MDL en una sola MDL.

Los controladores que usan paquetes y DMA del sistema pueden llamar a WdfDmaTransactionAllocateResources para reservar un número de registros de mapa del total asignado al dispositivo. Supongamos que el controlador reservó 4 de 8 registros totales de mapa, pero la transferencia DMA requiere 6. En este caso, WdfDmaTransactionInitialize produce un error. Para corregirlo, llame a WdfDmaTransactionFreeResources y, a continuación, vuelva a llamar a WdfDmaTransactionInitialize .

Los controladores que usan DMA de dispersión y recopilación no pueden reservar registros de mapa.

STATUS_WDF_TOO_MANY_TRANSFERS
Este valor devuelto solo se aplica a las transacciones que se establecieron para una única transferencia.

La longitud total de la transacción supera el tamaño máximo de transferencia del dispositivo.

 

Este método también podría devolver otros valores NTSTATUS.

Se produce una comprobación de errores si el controlador proporciona un identificador de objeto no válido.

Comentarios

El método WdfDmaTransactionInitialize prepara una operación DMA para su ejecución mediante la realización de operaciones de inicialización, como asignar la lista de dispersión y recopilación de una transacción. Después de que el controlador llame a WdfDmaTransactionInitialize, el controlador debe llamar a WdfDmaTransactionExecute para empezar a ejecutar la transacción.

Normalmente, los controladores basados en marcos llaman a WdfDmaTransactionInitialize desde dentro de una función de devolución de llamada de eventos de cola de E/S.

Si va a crear una transacción DMA basada en información que contiene un objeto de solicitud de marco, el controlador debe llamar a WdfDmaTransactionInitializeUsingRequest. Si va a crear una transacción DMA que no se basa en un objeto de solicitud, use WdfDmaTransactionInitialize o WdfDmaTransactionInitializeUsingOffset.

El controlador puede especificar una cadena MDL en el parámetro Mdl de este método. Una cadena MDL es una secuencia de estructuras MDL que el controlador encadenó mediante el miembro Next de la estructura MDL. En las versiones de marco anteriores a la versión 1.11, solo las transferencias DMA de dispersión y recopilación pueden usar cadenas MDL. A partir de la versión 1.11, si el controlador usa la versión 3 de DMA, las transferencias de paquetes únicos también pueden usar MDL encadenadas.

Si el búfer que especifica el controlador es mayor que la longitud máxima de transferencia que el controlador especificó cuando llamó a WdfDmaEnablerCreate o WdfDmaTransactionSetMaximumLength, el marco divide la transacción en varias transferencias.

Para obtener más información sobre las transacciones de DMA, consulte Creación e inicialización de una transacción DMA.

Ejemplos

El ejemplo de código siguiente procede del controlador de ejemplo PLX9x5x . En primer lugar, el ejemplo inicializa una estructura de WDF_OBJECT_ATTRIBUTES y crea un objeto de transacción DMA. A continuación, obtiene una MDL que representa el búfer de entrada de una solicitud de E/S recibida y obtiene la dirección virtual y la longitud del búfer. Por último, el ejemplo llama a WdfDmaTransactionInitialize para inicializar la transacción.

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;
}

Requisitos

Requisito Value
Plataforma de destino Universal
Versión mínima de KMDF 1.0
Encabezado wdfdmatransaction.h (incluya Wdf.h)
Library Wdf01000.sys (consulte Control de versiones de la biblioteca de marcos).
IRQL <=DISPATCH_LEVEL
Reglas de cumplimiento de DDI DeferredRequestCompleted(kmdf), DriverCreate(kmdf), KmdfIrql(kmdf), KmdfIrql2(kmdf), KmdfIrqlExplicit(kmdf), MdlAfterReqCompletedIntIoctlA(kmdf), MdlAfterReqCompletedIoctlA(kmdf), MdlAfterReqCompletedReadA(kmdf), MdlAfterReqCompletedWriteA(kmdf), RequestCompleted(kmdf), RequestCompletedLocal(kmdf)

Consulte también

EvtProgramDma

MmGetMdlByteCount

MmGetMdlVirtualAddress

WDF_DMA_DIRECTION

WdfDmaEnablerSetMaximumScatterGatherElements

WdfDmaTransactionCreate

WdfDmaTransactionExecute

WdfDmaTransactionInitializeUsingRequest