Finalización de una transferencia DMA

[Solo se aplica a KMDF]

Normalmente, la función de devolución de llamada EvtInterruptDpc del controlador completa el procesamiento de cada transferencia DMA.

En primer lugar, dado que varias transacciones DMA pueden estar en curso simultáneamente, la función de devolución de llamada EvtInterruptDpc debe determinar con qué transacción DMA está asociada la transferencia completada. La función de devolución de llamada puede hacerlo recuperando el identificador de transacción que el controlador almacenó al iniciar la transacción DMA. Para recuperar la extensión del dispositivo, el ejemplo PLX9x5x define una función denominada PLxGetDeviceContext en su archivo de encabezado Private.h:

WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_EXTENSION, PLxGetDeviceContext)

A continuación, en la devolución de llamada EvtInterruptDpc del controlador, hace lo siguiente:

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

A continuación, la función de devolución de llamada EvtInterruptDpc debe informar al marco de trabajo de que se ha completado una transferencia llamando a uno de los siguientes métodos de finalización de transferencia:

  • WdfDmaTransactionDmaCompleted, si la transferencia se completó correctamente y el hardware no notifica un recuento de bytes transferidos.

  • WdfDmaTransactionDmaCompletedWithLength, si la transferencia se completó correctamente y el hardware informa de un recuento de bytes transferidos (o un recuento de bytes no transferidos), o si el controlador detectó un error y especifica un recuento de transferencias de cero para reintentar la transferencia. Si el controlador especifica un recuento de transferencias de cero, el marco resta cero del número de bytes que permanecen y, por tanto, envía la misma transferencia a la función de devolución de llamada EvtProgramDma .

  • WdfDmaTransactionDmaCompletedFinal, si el hardware notifica una condición de ejecución o error insuficiente.

El controlador puede llamar a WdfDmaTransactionGetCurrentDmaTransferLength para obtener la longitud original de la transferencia completada. Esta llamada es útil si el dispositivo notifica un recuento de bytes que no se han transferido, ya que el controlador puede restar el número de bytes no transferidos de la longitud de transferencia original y, a continuación, llamar a WdfDmaTransactionGetCurrentDmaTransferLength para notificar el tamaño de transferencia real.

Cada uno de los métodos de finalización de transferencia anteriores informa al marco de trabajo de que se ha completado una única transferencia DMA (no toda la transacción DMA). Después de que el controlador llame a uno de estos métodos, el controlador comprueba el valor devuelto del método para ver si la transacción requiere más transferencias:

  • Si el valor devuelto del método de finalización es FALSE, el marco ha determinado que se requieren transferencias DMA adicionales para finalizar el procesamiento de la transacción DMA.

    Normalmente, la función de devolución de llamada EvtInterruptDpc del controlador simplemente devuelve. El marco llama de nuevo a la función de devolución de llamada EvtProgramDma del controlador y la función de devolución de llamada puede programar el hardware para la siguiente transferencia.

    Los métodos de finalización de transferencia proporcionan un valor de estado, que siempre se STATUS_MORE_PROCESSING_REQUIRED en este caso.

  • Si el valor devuelto es TRUE, no se producirán más transferencias para la transacción DMA.

    Los métodos de finalización de transferencia proporcionan un valor de estado. Si el valor de estado es STATUS_SUCCESS, todas las transferencias de la transacción DMA se completan y el controlador debe completar la transacción DMA. Si el valor de estado es cualquier otra cosa, se produjo un error y es posible que la transacción DMA no se haya completado.

Si la función de devolución de llamada EvtInterruptDpc detecta un error, normalmente debido a una expiración del temporizador o a una interrupción de hardware que indica un error de transferencia, el controlador puede reiniciar la transferencia actual de la transacción.

Para reiniciar la transferencia actual de la transacción, la función de devolución de llamada EvtInterruptDpc del controlador puede llamar a WdfDmaTransactionDmaCompletedWithLength con el parámetro TransferedLength establecido en cero.