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


Функция 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

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

[in] DmaDirection

Значение типа WDF_DMA_DIRECTION.

[in] Mdl

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

[in] VirtualAddress

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

[in] Length

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

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

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

Код возврата Описание
СТАТУС_НЕДОСТАТОЧНЫЕ_РЕСУРСЫ
Не удалось выделить список точечной и сборной.
СТАТУС_НЕДЕЙСТВИТЕЛЬНЫЙ_ПАРАМЕТР
Обнаружен недопустимый параметр.
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 — это последовательность структур MDL, которые драйвер объединяет с помощью Next член структуры MDL. В версиях платформы до версии 1.11 передача DMA может использовать только цепочки MDL. Начиная с версии 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 (include 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