WdfDmaTransactionExecute 函数 (wdfdmatransaction.h)
[仅适用于 KMDF]
WdfDmaTransactionExecute 方法开始执行指定的 DMA 事务。
语法
NTSTATUS WdfDmaTransactionExecute(
[in] WDFDMATRANSACTION DmaTransaction,
[in, optional] WDFCONTEXT Context
);
参数
[in] DmaTransaction
驱动程序从上一次调用 WdfDmaTransactionCreate 获取的 DMA 事务对象的句柄。
[in, optional] Context
驱动程序定义的上下文信息。 框架会将为 Context 指定的值(可以是指针)传递给驱动程序的 EvtProgramDma 事件回调函数。 此参数是可选的,可以为 NULL。
返回值
如果操作成功,WdfDmaTransactionExecute 将返回STATUS_SUCCESS。 否则,方法可能会返回以下值之一。
返回代码 | 说明 |
---|---|
|
以前名为 WdfDmaTransactionSetImmediateExecution 的 驱动程序和请求所需的资源不可用。 |
|
在调用 WdfDmaTransactionExecute 之前,没有调用 WdfDmaTransactionInitialize 或 WdfDmaTransactionInitializeUsingRequest。 |
|
设备在执行另一个事务时执行单数据包传输,驱动程序名为 WdfDmaTransactionExecute 。 |
|
操作系统处理指定传输大小所需的散点/收集元素数大于驱动程序调用 WdfDmaEnablerSetMaximumScatterGatherElements 指定的值。 有关更多信息,请参见下面的“备注”部分。 |
此方法还可能返回其他 NTSTATUS 值。
如果驱动程序提供无效的对象句柄,则会发生 bug 检查。
注解
WdfDmaTransactionExecute 方法为与指定的 DMA 事务关联的第一个 DMA 传输初始化事务的散点/收集列表。 (对于单数据包传输,散点/收集列表包含单个元素。) 然后,该方法调用驱动程序的 EvtProgramDma 事件回调函数,回调函数可以编程设备以开始传输。
基于框架的驱动程序通常从 I/O 队列事件回调函数中调用 WdfDmaTransactionExecute。
驱动程序调用 WdfDmaTransactionInitialize 或 WdfDmaTransactionInitializeUsingRequest 以初始化 DMA 事务后,驱动程序必须在完成 DMA 事务之前仅调用一次 WdfDmaTransactionExecute。
如果 WdfDmaTransactionInitializeXxx 返回成功,但 WdfDmaTransactionExecute 返回错误值,则驱动程序必须调用 WdfDmaTransactionRelease。
在 1.11 之前的框架版本中,如果设备执行单数据包传输,则操作系统一次只能执行一个 DMA 事务。 在这种情况下,如果正在执行另一个事务, WdfDmaTransactionExecute 将返回STATUS_WDF_BUSY。
在框架版本 1.11 及更高版本中,如果驱动程序使用 DMA 版本 3 执行单数据包传输,则操作系统可以将多个 DMA 事务存储在内部队列中。 在这种情况下,驱动程序可以在执行另一个事务时调用 WdfDmaTransactionExecute 。 若要选择 DMA 版本 3,请将 WDF_DMA_ENABLER_CONFIG 的 WdmDmaVersionOverride 成员设置为 3。
如果设备执行散点/收集传输,操作系统可以同时执行多个 DMA 事务。 在这种情况下,驱动程序可以在执行另一个事务时调用 WdfDmaTransactionExecute 。
如果驱动程序调用 WdfDmaTransactionDmaCompletedWithLength 来报告部分传输, 如果驱动程序使用链接在一起的 MDL (使用 MDL 结构的 Next 成员) 指定了 DMA 事务的数据缓冲区, 则 WdfDmaTransactionExecute 可以返回STATUS_WDF_TOO_FRAGMENTED,因为框架可能会重新计算片段的数量和大小,并且可能超出允许的片段数。
如果事务已成功启动, WdfDmaTransactionExecute 将返回STATUS_SUCCESS。 若要确定框架是否成功将事务的所有传输发送到驱动程序的 EvtProgramDma 回调函数,驱动程序必须调用 WdfDmaTransactionDmaCompleted、 WdfDmaTransactionDmaCompletedWithLength 或 WdfDmaTransactionDmaCompletedFinal。
如果 Context 参数提供的值是指针或句柄,则必须在驱动程序的 EvtProgramDma 事件回调函数(IRQL = DISPATCH_LEVEL)中访问它引用的内存。 可以使用 框架对象上下文 来满足此要求。
如果驱动程序以前已调用 WdfDmaTransactionSetImmediateExecution ,则驱动程序可以非阻塞方式调用 WdfDmaTransactionExecute。
有关 DMA 事务的详细信息,请参阅 启动 DMA 事务。
示例
以下代码示例来自 PCIDRV 示例驱动程序。 此示例创建并初始化 DMA 传输并开始执行。
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;
}
要求
要求 | 值 |
---|---|
目标平台 | 通用 |
最低 KMDF 版本 | 1.0 |
标头 | wdfdmatransaction.h (包括 Wdf.h) |
Library | Wdf01000.sys (请参阅框架库版本控制.) |
IRQL | <=DISPATCH_LEVEL |
DDI 符合性规则 | DriverCreate (kmdf) 、 KmdfIrql (kmdf) 、 KmdfIrql2 (kmdf) 、 KmdfIrqlExplicit (kmdf) |
另请参阅
WdfDmaEnablerSetMaximumScatterGatherElements
WdfDmaTransactionDmaCompletedFinal
WdfDmaTransactionDmaCompletedWithLength