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.