WdfDmaTransactionInitialize function (wdfdmatransaction.h)
[Applies to KMDF only]
The WdfDmaTransactionInitialize method initializes a specified DMA transaction.
Syntax
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
);
Parameters
[in] DmaTransaction
A handle to a DMA transaction object that the driver obtained from a previous call to WdfDmaTransactionCreate.
[in] EvtProgramDmaFunction
A pointer to the driver's EvtProgramDma event callback function.
[in] DmaDirection
A WDF_DMA_DIRECTION-typed value.
[in] Mdl
A pointer to a memory descriptor list (MDL) that describes the buffer that will be used for the DMA transaction. See more information in Remarks.
[in] VirtualAddress
The virtual address of the buffer that will be used for the DMA transaction.
[in] Length
The number of bytes to be transferred.
Return value
WdfDmaTransactionInitialize returns STATUS_SUCCESS if the operation succeeds. Otherwise, the method might return one of the following values.
Return code | Description |
---|---|
|
A scatter/gather list could not be allocated. |
|
An invalid parameter was detected. |
|
The number of scatter/gather elements that was needed to handle the transaction was greater than the value that the driver's call to WdfDmaEnablerSetMaximumScatterGatherElements specified.
For transactions that were set for single transfer, one way to fix this is to copy the data to a physically contiguous buffer and then initialize the transaction with that buffer. For example, call MmAllocateContiguousMemory, copy the original buffers into the new one, and then call WdfDmaTransactionInitialize again. |
|
This return value applies only to transactions that were set for single transfer.
The number of map registers needed to map the transaction is larger than the number the DMA adapter has reserved. To fix, the driver might reduce the number of required map registers by combining an MDL chain into a single MDL. Drivers using packet and system DMA can call WdfDmaTransactionAllocateResources to reserve a number of map registers from the total allocated to the device. Suppose your driver reserved 4 out of 8 total map registers, but the DMA transfer requires 6. In this case, WdfDmaTransactionInitialize fails. To fix, call WdfDmaTransactionFreeResources and then call WdfDmaTransactionInitialize again. Drivers using scatter/gather DMA cannot reserve map registers. |
|
This return value applies only to transactions that were set for single transfer.
The transaction’s total length exceeds the device’s maximum transfer size. |
This method also might return other NTSTATUS values.
A bug check occurs if the driver supplies an invalid object handle.
Remarks
The WdfDmaTransactionInitialize method prepares a DMA operation for execution, by performing initialization operations such as allocating a transaction's scatter/gather list. After your driver calls WdfDmaTransactionInitialize, the driver must call WdfDmaTransactionExecute to begin executing the transaction.
Framework-based drivers typically call WdfDmaTransactionInitialize from within an I/O queue event callback function.
If you are creating a DMA transaction that is based on information that a framework request object contains, your driver should call WdfDmaTransactionInitializeUsingRequest. If you are creating a DMA transaction that is not based on a request object, use either WdfDmaTransactionInitialize or WdfDmaTransactionInitializeUsingOffset.
The driver can specify an MDL chain in the Mdl parameter of this method. An MDL chain is a sequence of MDL structures that the driver chained together using the Next member of the MDL structure. In framework versions prior to 1.11, only scatter/gather DMA transfers can use MDL chains. Starting in version 1.11, if the driver is using DMA version 3, single-packet transfers can also use chained MDLs.
If the buffer that the driver specifies is larger than the maximum transfer length that your driver specified when it called WdfDmaEnablerCreate or WdfDmaTransactionSetMaximumLength, the framework breaks the transaction into multiple transfers.
For more information about DMA transactions, see Creating and Initializing a DMA Transaction.
Examples
The following code example is from the PLX9x5x sample driver. First, the example initializes a WDF_OBJECT_ATTRIBUTES structure and creates a DMA transaction object. Next, it obtains an MDL that represents a received I/O request's input buffer, and it obtains the virtual address and length of the buffer. Finally, the example calls WdfDmaTransactionInitialize to initialize the 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;
}
Requirements
Requirement | Value |
---|---|
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 | DeferredRequestCompleted(kmdf), DriverCreate(kmdf), KmdfIrql(kmdf), KmdfIrql2(kmdf), KmdfIrqlExplicit(kmdf), MdlAfterReqCompletedIntIoctlA(kmdf), MdlAfterReqCompletedIoctlA(kmdf), MdlAfterReqCompletedReadA(kmdf), MdlAfterReqCompletedWriteA(kmdf), RequestCompleted(kmdf), RequestCompletedLocal(kmdf) |