启动 DMA 事务
[仅适用于 KMDF]
在驱动程序 创建并初始化 DMA 事务后,驱动程序可以调用 WdfDmaTransactionExecute 方法来启动该事务。 此方法为与事务关联的第一个 DMA 传输 生成散点/收集列表。 接下来, 方法调用驱动程序为事务注册的 EvtProgramDma 回调函数。 回调函数 对 DMA 硬件进行程序 以启动传输。
在驱动程序调用 WdfDmaTransactionExecute 之前,驱动程序必须存储 DMA 事务句柄,以便在驱动程序完成与事务关联的每个 DMA 传输时可以检索该句柄。 存储事务句柄的一个好位置是在框架对象的上下文内存中,通常是设备的框架设备对象。 有关使用对象上下文内存的详细信息,请参阅 框架对象上下文空间。
PLX9x5x 示例中的以下代码示例演示如何初始化并执行 DMA 事务。 此代码显示在 Read.c 文件中。
VOID PLxEvtIoRead(
IN WDFQUEUE Queue,
IN WDFREQUEST Request,
IN size_t Length
)
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
PDEVICE_EXTENSION devExt;
// Get the DevExt from the queue handle
devExt = PLxGetDeviceContext(WdfIoQueueGetDevice(Queue));
do {
// Validate the Length parameter.
if (Length > PCI9656_SRAM_SIZE) {
status = STATUS_INVALID_BUFFER_SIZE;
break;
}
// Initialize the DmaTransaction.
status =
WdfDmaTransactionInitializeUsingRequest(
devExt->ReadDmaTransaction,
Request,
PLxEvtProgramReadDma,
WdfDmaDirectionReadFromDevice
);
if(!NT_SUCCESS(status)) {
. . . //Error-handling code omitted
break;
}
// Execute this DmaTransaction.
status = WdfDmaTransactionExecute( devExt->ReadDmaTransaction,
WDF_NO_CONTEXT);
if(!NT_SUCCESS(status)) {
. . . //Error-handling code omitted
break;
}
// Indicate that the DMA transaction started successfully.
// The DPC routine will complete the request when the DMA
// transaction is complete.
status = STATUS_SUCCESS;
} while (0);
// If there are errors, clean up and complete the request.
if (!NT_SUCCESS(status )) {
WdfDmaTransactionRelease(devExt->ReadDmaTransaction);
WdfRequestComplete(Request, status);
}
return;
}