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。 否则,方法可能会返回以下值之一。
返回代码 | 说明 |
---|---|
|
无法分配散点/收集列表。 |
|
检测到无效的参数。 |
|
处理事务所需的散点/收集元素数大于驱动程序调用 WdfDmaEnablerSetMaximumScatterGatherElements 指定的值。
对于为 单次传输设置的事务,解决此问题的一种方法是将数据复制到物理上连续的缓冲区,然后使用该缓冲区初始化事务。 例如,调用 MmAllocateContiguousMemory,将原始缓冲区复制到新缓冲区,然后再次调用 WdfDmaTransactionInitialize 。 |
|
此返回值仅适用于为 单次传输设置的事务。
映射事务所需的映射寄存器数大于 DMA 适配器保留的数量。 若要修复,驱动程序可能会通过将 MDL 链合并为单个 MDL 来减少所需的映射寄存器的数量。 使用数据包和系统 DMA 的驱动程序可以调用 WdfDmaTransactionAllocateResources ,以从分配给设备的总数中保留多个映射寄存器。 假设驱动程序在总共 8 个地图寄存器中保留 4 个,但 DMA 传输需要 6 个。 在这种情况下, WdfDmaTransactionInitialize 失败。 若要修复,请调用 WdfDmaTransactionFreeResources ,然后再次调用 WdfDmaTransactionInitialize 。 使用散点/收集 DMA 的驱动程序无法保留地图寄存器。 |
|
此返回值仅适用于为 单次传输设置的事务。
事务的总长度超过了设备的最大传输大小。 |
此方法还可能返回其他 NTSTATUS 值。
如果驱动程序提供无效的对象句柄,则会发生 bug 检查。
注解
WdfDmaTransactionInitialize 方法通过执行初始化操作(例如分配事务的散点/收集列表)来准备执行 DMA 操作。 驱动程序调用 WdfDmaTransactionInitialize 后,驱动程序必须调用 WdfDmaTransactionExecute 才能开始执行事务。
基于框架的驱动程序通常从 I/O 队列事件回调函数中调用 WdfDmaTransactionInitialize。
如果要创建基于框架请求对象包含的信息的 DMA 事务,驱动程序应调用 WdfDmaTransmaTransactionInitializeUsingRequest。 如果要创建不基于请求对象的 DMA 事务,请使用 WdfDmaTransactionInitialize 或 WdfDmaTransactionInitializeUsingOffset。
驱动程序可以在此方法的 Mdl 参数中指定 MDL 链。 MDL 链是驱动程序使用 MDL 结构的 Next 成员链接在一起的 MDL 结构的序列。 在 1.11 之前的框架版本中,只有散点/收集 DMA 传输可以使用 MDL 链。 从版本 1.11 开始,如果驱动程序使用 DMA 版本 3,则单数据包传输也可以使用链接的 MDL。
如果驱动程序指定的缓冲区大于驱动程序在调用 WdfDmaEnablerCreate 或 WdfDmaTransactionSetMaximumLength 时指定的最大传输长度,则框架会将事务分解为多个 传输。
有关 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) |