Поделиться через


Запуск транзакции 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;
}