WdfDmaTransactionInitialize 函数 (wdfdmatransaction.h)

[仅适用于 KMDF]

WdfDmaTransactionInitialize 方法初始化指定的 DMA 事务。

语法

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

参数

[in] DmaTransaction

驱动程序从上一次调用 WdfDmaTransactionCreate 获取的 DMA 事务对象的句柄。

[in] EvtProgramDmaFunction

指向驱动程序的 EvtProgramDma 事件回调函数的指针。

[in] DmaDirection

WDF_DMA_DIRECTION类型的值。

[in] Mdl

指向内存描述符列表的指针 (MDL) ,用于描述将用于 DMA 事务的缓冲区。 有关详细信息,请参阅 备注

[in] VirtualAddress

将用于 DMA 事务的缓冲区的虚拟地址。

[in] Length

要传输的字节数。

返回值

如果操作成功,WdfDmaTransactionInitialize 将返回STATUS_SUCCESS。 否则,方法可能会返回以下值之一。

返回代码 说明
STATUS_INSUFFICIENT_RESOURCES
无法分配散点/收集列表。
STATUS_INVALID_PARAMETER
检测到无效的参数。
STATUS_WDF_TOO_FRAGMENTED
处理事务所需的散点/收集元素数大于驱动程序调用 WdfDmaEnablerSetMaximumScatterGatherElements 指定的值。

对于为 单次传输设置的事务,解决此问题的一种方法是将数据复制到物理上连续的缓冲区,然后使用该缓冲区初始化事务。 例如,调用 MmAllocateContiguousMemory,将原始缓冲区复制到新缓冲区,然后再次调用 WdfDmaTransactionInitialize

STATUS_WDF_NOT_ENOUGH_MAP_REGISTERS
此返回值仅适用于为 单次传输设置的事务。

映射事务所需的映射寄存器数大于 DMA 适配器保留的数量。

若要修复,驱动程序可能会通过将 MDL 链合并为单个 MDL 来减少所需的映射寄存器的数量。

使用数据包和系统 DMA 的驱动程序可以调用 WdfDmaTransactionAllocateResources ,以从分配给设备的总数中保留多个映射寄存器。 假设驱动程序在总共 8 个地图寄存器中保留 4 个,但 DMA 传输需要 6 个。 在这种情况下, WdfDmaTransactionInitialize 失败。 若要修复,请调用 WdfDmaTransactionFreeResources ,然后再次调用 WdfDmaTransactionInitialize

使用散点/收集 DMA 的驱动程序无法保留地图寄存器。

STATUS_WDF_TOO_MANY_TRANSFERS
此返回值仅适用于为 单次传输设置的事务。

事务的总长度超过了设备的最大传输大小。

 

此方法还可能返回其他 NTSTATUS 值

如果驱动程序提供无效的对象句柄,则会发生 bug 检查。

注解

WdfDmaTransactionInitialize 方法通过执行初始化操作(例如分配事务的散点/收集列表)来准备执行 DMA 操作。 驱动程序调用 WdfDmaTransactionInitialize 后,驱动程序必须调用 WdfDmaTransactionExecute 才能开始执行事务。

基于框架的驱动程序通常从 I/O 队列事件回调函数中调用 WdfDmaTransactionInitialize

如果要创建基于框架请求对象包含的信息的 DMA 事务,驱动程序应调用 WdfDmaTransmaTransactionInitializeUsingRequest。 如果要创建不基于请求对象的 DMA 事务,请使用 WdfDmaTransactionInitializeWdfDmaTransactionInitializeUsingOffset

驱动程序可以在此方法的 Mdl 参数中指定 MDL 链。 MDL 链是驱动程序使用 MDL 结构的 Next 成员链接在一起的 MDL 结构的序列。 在 1.11 之前的框架版本中,只有散点/收集 DMA 传输可以使用 MDL 链。 从版本 1.11 开始,如果驱动程序使用 DMA 版本 3,则单数据包传输也可以使用链接的 MDL。

如果驱动程序指定的缓冲区大于驱动程序在调用 WdfDmaEnablerCreateWdfDmaTransactionSetMaximumLength 时指定的最大传输长度,则框架会将事务分解为多个 传输

有关 DMA 事务的详细信息,请参阅 创建和初始化 DMA 事务

示例

以下代码示例来自 PLX9x5x 示例驱动程序。 首先,该示例初始化 WDF_OBJECT_ATTRIBUTES 结构并创建 DMA 事务对象。 接下来,它获取表示收到的 I/O 请求输入缓冲区的 MDL,并获取缓冲区的虚拟地址和长度。 最后,该示例调用 WdfDmaTransactionInitialize 来初始化事务。

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

要求

要求
目标平台 通用
最低 KMDF 版本 1.0
标头 wdfdmatransaction.h (包括 Wdf.h)
Library Wdf01000.sys (请参阅框架库版本控制.)
IRQL <=DISPATCH_LEVEL
DDI 符合性规则 DeferredRequestCompleted (kmdf) DriverCreate (kmdf) KmdfIrql (kmdf) KmdfIrql2 (kmdf) 、 KmdfIrqlExplicit (kmdf) , MdlAfterReqCompletedIntIoctlA (kmdf) MdlAfterReqCompletedIoctlA (kmdf) MdlAfterReqCompletedReadA (kmdf) MdlAfterReqCompletedWriteA (kmdf) RequestCompleted (kmdf) RequestCompletedLocal (kmdf)

另请参阅

EvtProgramDma

MmGetMdlByteCount

MmGetMdlVirtualAddress

WDF_DMA_DIRECTION

WdfDmaEnablerSetMaximumScatterGatherElements

WdfDmaTransactionCreate

WdfDmaTransactionExecute

WdfDmaTransactionInitializeUsingRequest