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