Concluindo uma transferência de DMA

[Aplica-se somente ao KMDF]

Normalmente, a função de retorno de chamada EvtInterruptDpc do driver conclui o processamento de cada transferência de DMA.

Primeiro, como várias transações de DMA podem estar em andamento simultaneamente, a função de retorno de chamada EvtInterruptDpc deve determinar a qual transação de DMA a transferência concluída está associada. A função de retorno de chamada pode fazer isso recuperando o identificador de transação que o driver armazenou quando iniciou a transação de DMA. Para recuperar a extensão do dispositivo, o exemplo PLX9x5x define uma função chamada PLxGetDeviceContext em seu arquivo de cabeçalho Private.h:

WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_EXTENSION, PLxGetDeviceContext)

Em seguida, no retorno de chamada EvtInterruptDpc do driver, ele faz o seguinte:

WDFDMATRANSACTION   dmaTransaction;
PDEVICE_EXTENSION   devExt;
...
devExt  = PLxGetDeviceContext(WdfInterruptGetDevice(Interrupt));
...
dmaTransaction = devExt->WriteDmaTransaction;

Em seguida, a função de retorno de chamada EvtInterruptDpc deve informar à estrutura que uma transferência foi concluída chamando um dos seguintes métodos de conclusão de transferência:

  • WdfDmaTransactionDmaCompleted, se a transferência for concluída com êxito e o hardware não relatar uma contagem de bytes transferidos.

  • WdfDmaTransactionDmaCompletedWithLength, se a transferência foi concluída com êxito e o hardware relata uma contagem de bytes transferidos (ou uma contagem de bytes não transferidos) ou se o driver detectou um erro e especifica uma contagem de transferência de zero para repetir a transferência. Se o driver especificar uma contagem de transferência de zero, a estrutura subtrairá zero do número de bytes restantes e, portanto, enviará a mesma transferência para a função de retorno de chamada EvtProgramDma .

  • WdfDmaTransactionDmaCompletedFinal, se o hardware relatar uma condição de falha ou de execução insuficiente.

Seu driver pode chamar WdfDmaTransactionGetCurrentDmaTransferLength para obter o comprimento original da transferência concluída. Essa chamada será útil se o dispositivo relatar uma contagem de bytes que não foram transferidos, pois o driver pode subtrair o número de bytes não transferidos do comprimento da transferência original e, em seguida, chamar WdfDmaTransactionGetCurrentDmaTransferLength para relatar o tamanho real da transferência.

Cada um dos métodos de conclusão de transferência anteriores informa à estrutura que uma única transferência de DMA (não toda a transação de DMA) foi concluída. Depois que o driver chama um desses métodos, o driver verifica o valor retornado do método para ver se a transação requer mais transferências:

  • Se o valor retornado do método de conclusão for FALSE, a estrutura determinou que transferências adicionais de DMA são necessárias para concluir o processamento da transação de DMA.

    Normalmente, a função de retorno de chamada EvtInterruptDpc do driver retorna apenas. A estrutura chama a função de retorno de chamada EvtProgramDma do driver novamente e a função de retorno de chamada pode programar o hardware para a próxima transferência.

    Os métodos de conclusão de transferência fornecem um valor status, que é sempre STATUS_MORE_PROCESSING_REQUIRED nesse caso.

  • Se o valor retornado for TRUE, não ocorrerá mais transferências para a transação DMA.

    Os métodos de conclusão de transferência fornecem um valor status. Se o valor status for STATUS_SUCCESS, todas as transferências para a transação de DMA serão concluídas e o driver deverá concluir a transação de DMA. Se o valor status for qualquer outra coisa, ocorreu um erro e a transação de AMD pode não ter sido concluída.

Se a função de retorno de chamada EvtInterruptDpc detectar um erro, normalmente devido a um temporizador expirando ou uma interrupção de hardware sinalizando um erro de transferência, o driver poderá reiniciar a transferência atual da transação.

Para reiniciar a transferência atual da transação, a função de retorno de chamada EvtInterruptDpc do driver pode chamar WdfDmaTransactionDmaCompletedWithLength com o parâmetro TransferredLength definido como zero.