启动 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;
}