다음을 통해 공유


DMA 전송 완료

[KMDF에만 적용]

일반적으로 드라이버의 EvtInterruptDpc 콜백 함수는 각 DMA 전송 처리를 완료합니다.

첫째, 여러 DMA 트랜잭션이 동시에 진행될 수 있으므로 EvtInterruptDpc 콜백 함수는 완료된 전송이 연결된 DMA 트랜잭션을 결정해야 합니다. 콜백 함수는 DMA 트랜잭션을 시작할 때 드라이버가 저장한 트랜잭션 핸들을 검색하여 이 작업을 수행할 수 있습니다. 디바이스 확장을 검색하기 위해 PLX9x5x 샘플은 Private.h 헤더 파일에서 PLxGetDeviceContext 라는 함수를 정의합니다.

WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DEVICE_EXTENSION, PLxGetDeviceContext)

그런 다음 드라이버의 EvtInterruptDpc 콜백에서 다음을 수행합니다.

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

다음으로, EvtInterruptDpc 콜백 함수는 다음 전송 완료 방법 중 하나를 호출하여 전송이 완료되었다는 것을 프레임워크에 알려야 합니다.

  • 전송이 성공적으로 완료되고 하드웨어가 전송된 바이트 수를 보고하지 않는 경우 WdfDmaTransactionDmaCompleted.

  • WdfDmaTransactionDmaCompletedWithLength, 전송이 성공적으로 완료되고 하드웨어가 전송된 바이트 수(또는 전송되지 않은 바이트 수)를 보고하거나 드라이버가 오류를 감지하고 전송을 다시 시도할 전송 횟수를 0으로 지정하는 경우. 드라이버가 전송 횟수를 0으로 지정하면 프레임워크는 남아 있는 바이트 수에서 0을 빼서 동일한 전송을 EvtProgramDma 콜백 함수로 보냅니다.

  • 하드웨어가 언더런 또는 실패 조건을 보고하는 경우 WdfDmaTransactionDmaCompletedFinal입니다.

드라이버는 WdfDmaTransactionGetCurrentDmaTransferLength 를 호출하여 완료된 전송의 원래 길이를 가져올 수 있습니다. 이 호출은 드라이버가 원래 전송 길이에서 전송되지 않은 바이트 수를 빼고 WdfDmaTransactionGetCurrentDmaTransferLength 를 호출하여 실제 전송 크기를 보고할 수 있기 때문에 디바이스에서 전송되지 않은 바이트 수를 보고하는 경우에 유용합니다.

위의 각 전송 완료 메서드는 전체 DMA 트랜잭션이 아닌 단일 DMA 전송이 완료되었다는 것을 프레임워크에 알릴 수 있습니다. 드라이버가 이러한 메서드 중 하나를 호출한 후 드라이버는 메서드의 반환 값을 확인하여 트랜잭션에 더 많은 전송이 필요한지 확인합니다.

  • 완료 메서드의 반환 값이 FALSE이면 프레임워크는 DMA 트랜잭션 처리를 완료하기 위해 추가 DMA 전송이 필요하다고 결정했습니다.

    일반적으로 드라이버의 EvtInterruptDpc 콜백 함수는 반환됩니다. 프레임워크는 드라이버의 EvtProgramDma 콜백 함수를 다시 호출하고 콜백 함수는 다음 전송을 위해 하드웨어를 프로그래밍할 수 있습니다.

    전송 완료 메서드는 이 경우 항상 STATUS_MORE_PROCESSING_REQUIRED 상태 값을 제공합니다.

  • 반환 값이 TRUE이면 DMA 트랜잭션에 대한 전송이 더 이상 발생하지 않습니다.

    전송 완료 메서드는 상태 값을 제공합니다. 상태 값이 STATUS_SUCCESS 경우 DMA 트랜잭션에 대한 모든 전송이 완료되고 드라이버는 DMA 트랜잭션을 완료해야 합니다. 상태 값이 다른 경우 오류가 발생하고 DMA 트랜잭션이 완료되지 않았을 수 있습니다.

EvtInterruptDpc 콜백 함수가 일반적으로 타이머 만료 또는 전송 오류를 알리는 하드웨어 인터럽트로 인해 오류를 감지하는 경우 드라이버는 트랜잭션의 현재 전송을 다시 시작할 수 있습니다.

트랜잭션의 현재 전송을 다시 시작하기 위해 드라이버의 EvtInterruptDpc 콜백 함수는 TransferedLength 매개 변수가 0으로 설정된 WdfDmaTransactionDmaCompletedWithLength를 호출할 수 있습니다.