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

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

[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 事务,驱动程序应调用 WdfDmaTransactionInitializeUsingRequest。 如果要创建不基于请求对象的 DMA 事务,请使用 WdfDmaTransactionInitializeWdfDmaTransactionInitializeUsingOffset

驱动程序可以在此方法的 Mdl 参数中指定 MDL 链。 MDL 链是一系列 MDL 结构,驱动程序使用 MDL 结构的 Next 成员链接在一起。 在 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)
图书馆 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