Hardware de DMA de programação
[Aplica-se somente ao KMDF]
Este tópico descreve a funcionalidade que um driver KMDF para um dispositivo DMA master de barramento normalmente fornece em sua função de retorno de chamada de evento EvtProgramDma. Se o driver usar o suporte de DMA da estrutura, o driver deverá fornecer esse retorno de chamada. Essas informações também se aplicam a um driver KMDF para um dispositivo DMA no modo de sistema que tem uma interrupção de hardware.
A função de retorno de chamada EvtProgramDma , que é chamada em IRQL = DISPATCH_LEVEL, programa o dispositivo para iniciar uma transferência de DMA. Os parâmetros de entrada para essa função de retorno de chamada fornecem a direção da transferência (entrada ou saída) e uma lista de dispersão/coleta. Se a transferência consistir em um único pacote, a lista de dispersão/coleta conterá um único elemento.
A função de retorno de chamada EvtProgramDma programa o dispositivo usando os recursos de hardware que a função de retorno de chamada EvtDevicePrepareHardware do driver recebeu. Se a função de retorno de chamada EvtProgramDma programar com êxito o hardware, ela retornará TRUE.
Depois que o hardware concluir a transferência de DMA, normalmente o hardware emite uma interrupção e o sistema chama a função de retorno de chamada EvtInterruptIsr do driver. A função de retorno de chamada EvtInterruptIsr do driver geralmente:
Limpa a interrupção de hardware.
Salva as informações de contexto da interrupção se elas forem necessárias. Essas informações podem ser perdidas depois que a função de retorno de chamada retorna e o sistema reduz o IRQL (porque a redução do IRQL permite que interrupções adicionais ocorram).
Chama WdfInterruptQueueDpcForIsr para agendar uma função de retorno de chamada EvtInterruptDpc .
A função de retorno de chamada EvtInterruptDpcconclui a transferência de DMA usando informações de contexto que a função de retorno de chamada EvtInterruptIsr salvou.
Se a função de retorno de chamada EvtProgramDma detectar um erro, o driver poderá interromper a transação.
Para interromper uma transação quando o driver detectar um erro, a função de retorno de chamada EvtProgramDma deve:
Chame WdfObjectDelete para excluir o objeto de transação DMA ou chame WdfDmaTransactionRelease para liberar e reutilizar o objeto de transação DMA.
Requeira a solicitação de E/S ou conclua a solicitação de E/S, se a transação estiver associada a um objeto de solicitação de estrutura. Para recuperar um identificador para a solicitação, o driver pode chamar WdfDmaTransactionGetRequest.
Retornar FALSE.
As etapas 1 e 4 são ilustradas no exemplo de código a seguir, obtido da função de retorno de chamada EvtProgramDma da amostra PLX9x5x para solicitações de leitura no arquivo Read.c.
// If errors occur in the EvtProgramDma callback,
// release the DMA transaction object and complete the request.
if (errors) {
NTSTATUS status;
//
// Must abort the transaction before deleting.
//
(VOID) WdfDmaTransactionDmaCompletedFinal(Transaction, 0, &status);
ASSERT(NT_SUCCESS(status));
PLxReadRequestComplete( Transaction, STATUS_INVALID_DEVICE_STATE );
TraceEvents(TRACE_LEVEL_ERROR, DBG_READ,
"<-- PLxEvtProgramReadDma: errors ****");
return FALSE;
}
O exemplo chama a função PLxReadRequestComplete para executar as etapas 2 e 3:
VOID
PLxReadRequestComplete(
IN WDFDMATRANSACTION DmaTransaction,
IN NTSTATUS Status
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
WDFREQUEST request;
size_t bytesTransferred;
//
// Get the associated request from the transaction.
//
request = WdfDmaTransactionGetRequest(DmaTransaction);
ASSERT(request);
//
// Get the final bytes transferred count.
//
bytesTransferred = WdfDmaTransactionGetBytesTransferred( DmaTransaction );
TraceEvents(TRACE_LEVEL_INFORMATION, DBG_DPC,
"PLxReadRequestComplete: Request %p, Status %!STATUS!, "
"bytes transferred %d\n",
request, Status, (int) bytesTransferred );
WdfDmaTransactionRelease(DmaTransaction);
//
// Complete this Request.
//
WdfRequestCompleteWithInformation( request, Status, bytesTransferred);
}