Запуск транзакции DMA

[Применимо только к KMDF]

После создания и инициализации транзакции DMA драйвер может вызвать метод WdfDmaTransactionExecute для запуска транзакции. Этот метод создает список scatter/gather для первой передачи 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;
}