Compartilhar via


Função WdfDmaTransactionInitialize (wdfdmatransaction.h)

[Aplica-se somente ao KMDF]

O método WdfDmaTransactionInitialize inicializa uma transação de DMA especificada.

Sintaxe

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
);

Parâmetros

[in] DmaTransaction

Um identificador para um objeto de transação DMA que o driver obteve de uma chamada anterior para WdfDmaTransactionCreate.

[in] EvtProgramDmaFunction

Um ponteiro para a função de retorno de chamada de evento EvtProgramDma do driver.

[in] DmaDirection

Um valor de tipo WDF_DMA_DIRECTION.

[in] Mdl

Um ponteiro para uma MDL (lista de descritores de memória) que descreve o buffer que será usado para a transação de DMA. Veja mais informações em Comentários.

[in] VirtualAddress

O endereço virtual do buffer que será usado para a transação de DMA.

[in] Length

O número de bytes a serem transferidos.

Retornar valor

WdfDmaTransactionInitialize retornará STATUS_SUCCESS se a operação for bem-sucedida. Caso contrário, o método pode retornar um dos valores a seguir.

Código de retorno Descrição
STATUS_INSUFFICIENT_RESOURCES
Não foi possível alocar uma lista de dispersão/coleta.
STATUS_INVALID_PARAMETER
Um parâmetro inválido foi detectado.
STATUS_WDF_TOO_FRAGMENTED
O número de elementos de dispersão/coleta necessários para lidar com a transação foi maior do que o valor especificado pela chamada do driver para WdfDmaEnablerSetMaximumScatterGatherElements .

Para transações que foram definidas para transferência única, uma maneira de corrigir isso é copiar os dados para um buffer fisicamente contíguo e, em seguida, inicializar a transação com esse buffer. Por exemplo, chame MmAllocateContiguousMemory, copie os buffers originais para o novo e chame WdfDmaTransactionInitialize novamente.

STATUS_WDF_NOT_ENOUGH_MAP_REGISTERS
Esse valor retornado aplica-se somente a transações que foram definidas para transferência única.

O número de registros de mapa necessários para mapear a transação é maior do que o número reservado pelo adaptador de DMA.

Para corrigir, o driver pode reduzir o número de registros de mapa necessários combinando uma cadeia de MDL em um único MDL.

Os drivers que usam o DMA do sistema e pacote podem chamar WdfDmaTransactionAllocateResources para reservar vários registros de mapa do total alocado para o dispositivo. Suponha que o driver tenha reservado 4 de 8 registros totais de mapa, mas a transferência de DMA requer 6. Nesse caso, wdfDmaTransactionInitialize falha. Para corrigir, chame WdfDmaTransactionFreeResources e chame WdfDmaTransactionInitialize novamente.

Os drivers que usam o AMD de dispersão/coleta não podem reservar registros de mapa.

STATUS_WDF_TOO_MANY_TRANSFERS
Esse valor retornado aplica-se somente a transações que foram definidas para transferência única.

O tamanho total da transação excede o tamanho máximo de transferência do dispositivo.

 

Esse método também pode retornar outros valores NTSTATUS.

Um bug marcar ocorrerá se o driver fornecer um identificador de objeto inválido.

Comentários

O método WdfDmaTransactionInitialize prepara uma operação de DMA para execução, executando operações de inicialização, como alocar a lista de dispersão/coleta de uma transação. Depois que o driver chamar WdfDmaTransactionInitialize, o driver deverá chamar WdfDmaTransactionExecute para começar a executar a transação.

Drivers baseados em estrutura normalmente chamam WdfDmaTransactionInitialize de dentro de uma função de retorno de chamada de evento de fila de E/S.

Se você estiver criando uma transação de DMA baseada em informações que um objeto de solicitação de estrutura contém, seu driver deverá chamar WdfDmaTransactionInitializeUsingRequest. Se você estiver criando uma transação DMA que não se baseia em um objeto de solicitação, use WdfDmaTransactionInitialize ou WdfDmaTransactionInitializeUsingOffset.

O driver pode especificar uma cadeia MDL no parâmetro Mdl desse método. Uma cadeia MDL é uma sequência de estruturas MDL que o driver encadeou usando o membro Next da estrutura MDL. Em versões de estrutura anteriores à 1.11, somente transferências de DMA de dispersão/coleta podem usar cadeias de MDL. A partir da versão 1.11, se o driver estiver usando o DMA versão 3, as transferências de pacote único também poderão usar MDLs encadeados.

Se o buffer especificado pelo driver for maior que o comprimento máximo de transferência especificado pelo driver quando ele chamou WdfDmaEnablerCreate ou WdfDmaTransactionSetMaximumLength, a estrutura dividirá a transação em várias transferências.

Para obter mais informações sobre transações de DMA, consulte Criando e inicializando uma transação de DMA.

Exemplos

O exemplo de código a seguir é do driver de exemplo PLX9x5x . Primeiro, o exemplo inicializa uma estrutura WDF_OBJECT_ATTRIBUTES e cria um objeto de transação DMA. Em seguida, ele obtém um MDL que representa o buffer de entrada de uma solicitação de E/S recebida e obtém o endereço virtual e o comprimento do buffer. Por fim, o exemplo chama WdfDmaTransactionInitialize para inicializar a transação.

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

Requisitos

Requisito Valor
Plataforma de Destino Universal
Versão mínima do KMDF 1.0
Cabeçalho wdfdmatransaction.h (include Wdf.h)
Biblioteca Wdf01000.sys (consulte Controle de versão da biblioteca de estrutura.)
IRQL <=DISPATCH_LEVEL
Regras de conformidade da DDI DeferredRequestCompleted(kmdf), DriverCreate(kmdf), KmdfIrql(kmdf), KmdfIrql2(kmdf), KmdfIrqlExplicit(kmdf), MdlAfterReqCompletedIntIoctlA(kmdf), MdlAfterReqCompletedIoctlA(kmdf), MdlAfterReqCompletedReadA(kmdf), MdlAfterReqCompletedWriteA(kmdf), RequestCompleted(kmdf), RequestCompletedLocal(kmdf)

Confira também

EvtProgramDma

MmGetMdlByteCount

MmGetMdlVirtualAddress

WDF_DMA_DIRECTION

WdfDmaEnablerSetMaximumScatterGatherElements

WdfDmaTransactionCreate

WdfDmaTransactionExecute

WdfDmaTransactionInitializeUsingRequest