WdfDmaTransactionExecute function

[Applies to KMDF only]

The WdfDmaTransactionExecute method begins the execution of a specified DMA transaction.

Syntax

NTSTATUS WdfDmaTransactionExecute(
  _In_     WDFDMATRANSACTION DmaTransaction,
  _In_opt_ WDFCONTEXT        Context
);

Parameters

DmaTransaction

A handle to a DMA transaction object that the driver obtained from a previous call to WdfDmaTransactionCreate.

Context

Driver-defined context information. The framework passes the value specified for Context, which can be a pointer, to the driver's EvtProgramDma event callback function. This parameter is optional and can be NULL.

Return Value

WdfDmaTransactionExecute returns STATUS_SUCCESS if the operation succeeds. Otherwise, the method might return one of the following values.

Return code Description
STATUS_INSUFFICIENT_RESOURCES
The driver previously called WdfDmaTransactionSetImmediateExecution and the resources needed for the request are unavailable.
STATUS_INVALID_DEVICE_REQUEST
The call to WdfDmaTransactionExecute was not preceded by a call to WdfDmaTransactionInitialize or WdfDmaTransactionInitializeUsingRequest.
STATUS_WDF_BUSY
The device performs single-packet transfers, and the driver called WdfDmaTransactionExecute while another transaction was executing.
STATUS_WDF_TOO_FRAGMENTED
The number of scatter/gather elements that the operating system needed to handle the specified transfer size was greater than the value that the driver's call to WdfDmaEnablerSetMaximumScatterGatherElements specified. For more information, see the following Remarks section.

This method also might return other NTSTATUS values.

A bug check occurs if the driver supplies an invalid object handle.

Remarks

The WdfDmaTransactionExecute method initializes a transaction's scatter/gather list for the first DMA transfer that is associated with the specified DMA transaction. (For single-packet transfers, the scatter/gather list contains a single element.) Then, the method calls the driver's EvtProgramDma event callback function, and the callback function can program the device to begin the transfer.

Framework-based drivers typically call WdfDmaTransactionExecute from within an I/O queue event callback function.

After a driver has called WdfDmaTransactionInitialize or WdfDmaTransactionInitializeUsingRequest to initialize a DMA transaction, the driver must call WdfDmaTransactionExecute only once before completing the DMA transaction.

      If <b>WdfDmaTransactionInitialize<i>Xxx</i></b> returns success but <b>WdfDmaTransactionExecute</b> returns an error value, your driver must call <a href="..\wdfdmatransaction\nf-wdfdmatransaction-wdfdmatransactionrelease.md">WdfDmaTransactionRelease</a>.

In framework versions prior to 1.11, if the device performs single-packet transfers, the operating system can execute only one DMA transaction at a time. In this case, WdfDmaTransactionExecute returns STATUS_WDF_BUSY if another transaction is executing.

In framework versions 1.11 and later, if the driver uses DMA version 3 to perform single-packet transfers, the operating system can store multiple DMA transactions in an internal queue. In this case, the driver can call WdfDmaTransactionExecute while another transaction is executing. To select DMA version 3, set the WdmDmaVersionOverride member of WDF_DMA_ENABLER_CONFIG to 3.

If the device performs scatter/gather transfers, the operating system can execute multiple DMA transactions simultaneously. In this case, the driver can call WdfDmaTransactionExecute while another transaction is executing.

If the driver calls WdfDmaTransactionDmaCompletedWithLength to report a partial transfer, and if the driver had specified the DMA transaction's data buffer by using MDLs that it chained together (using the Next member of the MDL structure), WdfDmaTransactionExecute can return STATUS_WDF_TOO_FRAGMENTED because the framework might recalculate the number and size of fragments and might exceed the number of allowed fragments.

The WdfDmaTransactionExecute returns STATUS_SUCCESS if the transaction was successfully started. To determine if the framework successfully sent all of the transaction's transfers to the driver's EvtProgramDma callback function, the driver must call WdfDmaTransactionDmaCompleted, WdfDmaTransactionDmaCompletedWithLength, or WdfDmaTransactionDmaCompletedFinal.

If the value that the Context parameter supplies is a pointer or handle, the memory that it references must be accessible in the driver's EvtProgramDma event callback function at IRQL = DISPATCH_LEVEL. You can use framework object context to meet this requirement.

The driver can call WdfDmaTransactionExecute in a non-blocking manner if it has previously called WdfDmaTransactionSetImmediateExecution.

For more information about DMA transactions, see Starting a DMA Transaction.

Examples

The following code example is from the PCIDRV sample driver. This example creates and initializes a DMA transfer and begins its execution.

NTSTATUS
NICInitiateDmaTransfer(
    IN PFDO_DATA  FdoData,
    IN WDFREQUEST  Request
    )
{
    WDFDMATRANSACTION  dmaTransaction;
    NTSTATUS  status;
    BOOLEAN  bCreated = FALSE;

    do {
        status = WdfDmaTransactionCreate(
                                         FdoData->WdfDmaEnabler,
                                         WDF_NO_OBJECT_ATTRIBUTES,
                                         &dmaTransaction
                                         );
        if(!NT_SUCCESS(status)) {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE, 
                        "WdfDmaTransactionCreate failed %X\n", status);
            break;
        }

        bCreated = TRUE;

        status = WdfDmaTransactionInitializeUsingRequest( 
                                     dmaTransaction,
                                     Request,
                                     NICEvtProgramDmaFunction,
                                     WdfDmaDirectionWriteToDevice
                                     );
        if(!NT_SUCCESS(status)) {
            TraceEvents(
                        TRACE_LEVEL_ERROR,
                        DBG_WRITE, 
                        "WdfDmaTransactionInitalizeUsingRequest failed %X\n", 
                        status
                        );
            break;
        }

        status = WdfDmaTransactionExecute(
                                          dmaTransaction,
                                          dmaTransaction
                                          );

        if(!NT_SUCCESS(status)) {
            TraceEvents(
                        TRACE_LEVEL_ERROR,
                        DBG_WRITE, 
                        "WdfDmaTransactionExecute failed %X\n",
                        status
                        );
            break;
        }
    } while (FALSE);

    if(!NT_SUCCESS(status)){

        if(bCreated) {
            WdfObjectDelete(dmaTransaction);
        }
    }
    return status;
}

Requirements

   
Target Platform Universal
Minimum KMDF version 1.0
Header wdfdmatransaction.h (include Wdf.h)
Library Wdf01000.sys (see Framework Library Versioning.)
IRQL "<=DISPATCH_LEVEL"
DDI compliance rules DriverCreate, KmdfIrql, KmdfIrql2

See Also

WdfDmaTransactionInitialize

WdfDmaTransactionInitializeUsingRequest

WdfDmaEnablerSetMaximumScatterGatherElements

EvtProgramDma

WdfDmaTransactionDmaCompletedWithLength

WdfDmaTransactionSetImmediateExecution

WdfDmaTransactionDmaCompleted

WdfDmaTransactionCreate

WdfDmaTransactionDmaCompletedFinal

Send comments about this topic to Microsoft