Функция WdfDmaTransactionInitialize (wdfdmatransaction.h)

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

Метод WdfDmaTransactionInitialize инициализирует указанную транзакцию DMA.

Синтаксис

NTSTATUS WdfDmaTransactionInitialize(
  [in] WDFDMATRANSACTION   DmaTransaction,
  [in] PFN_WDF_PROGRAM_DMA EvtProgramDmaFunction,
  [in] WDF_DMA_DIRECTION   DmaDirection,
  [in] PMDL                Mdl,
  [in] PVOID               VirtualAddress,
  [in] size_t              Length
);

Параметры

[in] DmaTransaction

Дескриптор объекта транзакции DMA, полученного драйвером при предыдущем вызове WdfDmaTransactionCreate.

[in] EvtProgramDmaFunction

Указатель на функцию обратного вызова события EvtProgramDma драйвера.

[in] DmaDirection

WDF_DMA_DIRECTION типизированное значение.

[in] Mdl

Указатель на список дескрипторов памяти (MDL), описывающий буфер, который будет использоваться для транзакции DMA. Дополнительные сведения см. в разделе Примечания.

[in] VirtualAddress

Виртуальный адрес буфера, который будет использоваться для транзакции DMA.

[in] Length

Число передаваемых байтов.

Возвращаемое значение

WdfDmaTransactionInitialize возвращает STATUS_SUCCESS, если операция выполнена успешно. В противном случае метод может вернуть одно из следующих значений.

Код возврата Описание
STATUS_INSUFFICIENT_RESOURCES
Не удалось выделить точечный или собирающий список.
STATUS_INVALID_PARAMETER
Обнаружен недопустимый параметр.
STATUS_WDF_TOO_FRAGMENTED
Количество элементов точечной и сборной, необходимых для обработки транзакции, больше значения, указанного в вызове драйвера wdfDmaEnablerSetMaximumScatterGatherElements .

Для транзакций, которые были настроены для одной передачи, один из способов исправить это — скопировать данные в физически непрерывный буфер, а затем инициализировать транзакцию этим буфером. Например, вызовите MmAllocateContiguousMemory, скопируйте исходные буферы в новый, а затем снова вызовите WdfDmaTransactionInitialize .

STATUS_WDF_NOT_ENOUGH_MAP_REGISTERS
Это возвращаемое значение применяется только к транзакциям, которые были заданы для одной передачи.

Количество регистров карты, необходимых для сопоставления транзакции, больше, чем количество зарезервированных адаптером DMA.

Чтобы устранить эту проблему, драйвер может уменьшить количество необходимых регистров карты, объединяя цепочку MDL в один MDL.

Драйверы, использующие пакетные и системные DMA, могут вызывать WdfDmaTransactionAllocateResources , чтобы зарезервировать количество регистров карты из общего объема, выделенного устройству. Предположим, что ваш драйвер зарезервировал 4 из 8 регистров карты, но для передачи DMA требуется 6. В этом случае происходит сбой WdfDmaTransactionInitialize . Чтобы исправить это, вызовите WdfDmaTransactionFreeResources , а затем снова вызовите WdfDmaTransactionInitialize .

Драйверы, использующие точечную или сборную DMA, не могут резервировать регистры карт.

STATUS_WDF_TOO_MANY_TRANSFERS
Это возвращаемое значение применяется только к транзакциям, которые были заданы для одной передачи.

Общая длина транзакции превышает максимальный размер передачи устройства.

 

Этот метод также может возвращать другие значения NTSTATUS.

Ошибка проверка возникает, если драйвер предоставляет недопустимый дескриптор объекта.

Комментарии

Метод WdfDmaTransactionInitialize подготавливает операцию DMA к выполнению путем выполнения операций инициализации, таких как выделение точечных и сборных списков транзакций. После вызова драйвером WdfDmaTransactionInitialize драйвер должен вызвать WdfDmaTransactionExecute , чтобы начать выполнение транзакции.

Драйверы на основе платформы обычно вызывают WdfDmaTransactionInitialize из функции обратного вызова событий очереди ввода-вывода.

Если вы создаете транзакцию DMA, основанную на сведениях, содержащихся в объекте запроса платформы, драйвер должен вызвать WdfDmaTransactionInitializeUsingRequest. Если вы создаете транзакцию DMA, которая не основана на объекте запроса, используйте WdfDmaTransactionInitialize или WdfDmaTransactionInitializeUsingOffset.

Драйвер может указать цепочку MDL в параметре Mdl этого метода. Цепочка MDL — это последовательность структур MDL, связанных драйвером с помощью элемента Next структуры MDL. В версиях платформ до 1.11 цепочки MDL могут использоваться только передачи точечной и сборной DMA. Начиная с версии 1.11, если драйвер использует DMA версии 3, передача одного пакета также может использовать связанные многомерные выражения.

Если указанный драйвером буфер больше максимальной длины передачи, указанной драйвером при вызове WdfDmaEnablerCreate или WdfDmaTransactionSetMaximumLength, платформа разбивает транзакцию на несколько передач.

Дополнительные сведения о транзакциях DMA см. в статье Создание и инициализация транзакции DMA.

Примеры

Следующий пример кода из примера драйвера PLX9x5x . Сначала в примере инициализируется структура WDF_OBJECT_ATTRIBUTES и создается объект транзакции DMA. Затем он получает MDL, представляющий входной буфер полученного запроса ввода-вывода, и получает виртуальный адрес и длину буфера. Наконец, в примере вызывается WdfDmaTransactionInitialize для инициализации транзакции.

WDF_OBJECT_ATTRIBUTES  attributes;
PMDL  mdl;
PVOID  virtualAddress;
ULONG  length;
NTSTATUS  status;

WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(
                                        &attributes,
                                        TRANSACTION_CONTEXT
                                        );

status = WdfDmaTransactionCreate(
                                 devExt->DmaEnabler,
                                 &attributes,
                                 &dmaTransaction
                                 );
if(!NT_SUCCESS(status)) {
    goto CleanUp;
}

status = WdfRequestRetrieveInputWdmMdl(
                                       Request,
                                       &mdl
                                       );
if (!NT_SUCCESS(status)) {
    goto CleanUp;
}

virtualAddress = MmGetMdlVirtualAddress(mdl);
length = MmGetMdlByteCount(mdl);

status = WdfDmaTransactionInitialize(
                                     dmaTransaction,
                                     PLxEvtProgramWriteDma,
                                     WdfDmaDirectionWriteToDevice,
                                     mdl,
                                     virtualAddress,
                                     length
                                     );
if(!NT_SUCCESS(status)) {
    goto CleanUp;
}

Требования

Требование Значение
Целевая платформа Универсальное
Минимальная версия KMDF 1,0
Верхняя часть wdfdmatransaction.h (включая Wdf.h)
Библиотека Wdf01000.sys (см. раздел Управление версиями библиотеки платформы).
IRQL <=DISPATCH_LEVEL
Правила соответствия DDI DeferredRequestCompleted(kmdf), DriverCreate(kmdf), KmdfIrql(kmdf), KmdfIrql2(kmdf), KmdfIrqlExplicit(kmdf), MdlAfterReqCompletedIntIoctlA(kmdf), MdlAfterReqCompletedIoctlA(kmdf), MdlAfterReqCompletedReadA(kmdf), MdlAfterReqCompletedWriteA(kmdf), RequestCompleted(kmdf), RequestCompletedLocal(kmdf)

См. также раздел

EvtProgramDma

MmGetMdlByteCount

MmGetMdlVirtualAddress

WDF_DMA_DIRECTION

WdfDmaEnablerSetMaximumScatterGatherElements

WdfDmaTransactionCreate

WdfDmaTransactionExecute

WdfDmaTransactionInitializeUsingRequest