전송 작업 설정

AllocateAdapterChannel이 제어를 드라이버의 AdapterControl 루틴으로 전송할 때 맵 레지스터 집합을 할당했습니다. 그러나 드라이버는 다음과 같이 현재 IRP의 전송 요청에 대한 시스템 실제 메모리를 버스 마스터 어댑터의 논리 주소 범위에 매핑해야 합니다.

  1. Irp-MdlAddress>에서 MDL을 사용하여 MmGetMdlVirtualAddress를 호출하여 전송을 시작해야 하는 시스템 실제 주소에 대한 인덱스를 가져옵니다.

    반환 값은 MapTransfer에 필요한 매개 변수(CurrentVa)입니다.

  2. MapTransfer를 호출하여 IRP 버퍼의 시스템 실제 주소 범위를 버스 마스터 어댑터의 논리 주소 범위에 매핑합니다.

그런 다음 드라이버는 전송 작업에 대한 어댑터를 설정할 수 있습니다. 다음 그림에서는 전송 설정과 관련된 단계를 보여줍니다.

diagram illustrating setting up a transfer operation.

이전 그림과 같이 드라이버의 AdapterControl 루틴은 다음과 같이 버스 마스터 DMA 작업을 설정합니다.

  1. AdapterControl 루틴은 전송을 시작할 주소를 가져옵니다. IRP를 충족하는 데 필요한 초기 전송의 경우 AdapterControl 루틴은 MmGetMdlVirtualAddress를 호출하여 이 DMA 전송에 대한 버퍼를 설명하는 Irp-MdlAddress>의 MDL에 대한 포인터를 전달합니다.

    MmGetMdlVirtualAddress 는 드라이버가 전송을 시작해야 하는 시스템 실제 주소의 인덱스로 사용할 수 있는 가상 주소를 반환합니다.

    IRP에 둘 이상의 전송 작업이 필요한 경우 드라이버는 이 섹션의 뒷부분에 설명된 대로 업데이트된 시작 주소를 계산합니다.

  2. AdapterControl 루틴은 MmGetMdlVirtualAddress에서 반환되거나 1단계에서 계산된 주소를 저장합니다. 이 주소는 MapTransfer에 필요한 매개 변수(CurrentVa)입니다.

  3. AdapterControl 루틴은 MapTransfer를 호출하며, 드라이버가 버스 마스터 어댑터를 프로그래밍하여 전송 작업을 시작할 수 있는 논리적 주소를 반환합니다. MapTransfer 호출에서 드라이버는 다음 매개 변수를 제공합니다.

    • IoGetDmaAdapter에서 반환된 어댑터 개체 포인터

    • 현재 IRP에 대한 Irp-MdlAddress>의 MDL 에 대한 포인터

    • AllocateAdapterChannel에 의해 드라이버의 AdapterControl 루틴에 전달된 MapRegisterBase 핸들(Bus-Master 어댑터 개체 할당 참조)

    • 현재 IRP에 대한 MapTransfer에 대한 첫 번째 호출인 경우 MmGetMdlVirtualAddress에서 반환되는 값입니다.

      그렇지 않으면 드라이버가 업데이트된 CurrentVa 값을 제공하며, 이는 수행할 다음 물리적-논리적 매핑을 나타냅니다. 업데이트된 CurrentVa 를 계산하는 방법은 이 섹션의 뒷부분에 설명되어 있습니다.

    • 이 전송에 대한 바이트 수를 나타내는 변수(Length)에 대한 포인터입니다.

      드라이버에 요청된 모든 데이터를 단일 DMA 작업으로 전송하기에 충분한 맵 레지스터가 있고 해당 DMA 작업에 대한 디바이스별 제약 조건이 없는 경우 Length 는 드라이버의 IRP I/O 스택 위치에 있는 Length 값으로 설정할 수 있습니다. 최대 바이트 입력 길이는 (PAGE_SIZE * IoGetDmaAdapter에서 반환된 NumberOfMapRegisters)일 수 있습니다. 그렇지 않으면 드라이버는 전송 요청 분할에 설명된 대로 요청을 분할해야 하며, 현재 IRP에 대한 MapTransfer에 대한 후속 호출에서 Length 값을 업데이트해야 합니다.

    • 전송 작업의 방향을 나타내는 부울 값(WriteToDevice)입니다(메모리에서 디바이스로 데이터를 전송하려면 TRUE).

  4. AdapterControl 루틴은 DMA 작업에 대한 디바이스를 설정합니다.

  5. AdapterControl 루틴은 DeallocateObjectKeepRegisters를 반환합니다.

드라이버가 현재 IRP를 충족하기 위해 MapTransfer를 두 번 이상 호출해야 하는 경우 MapTransfer에 대한 모든 호출에서 동일한 어댑터 개체 포인터, Mdl 포인터, MapRegisterBase 핸들 및 전송 방향을 제공합니다. 그러나 드라이버는 MapTransfer에 대한 두 번째 및 후속 호출에서 업데이트된 CurrentVaLength 값을 제공해야 합니다. 다음 수식을 사용하여 이러한 값을 계산합니다.

  • CurrentVa = CurrentVa +(MapTransfer에 대한 이전 호출에서 요청된 길이)

  • Length = Minimum(전송할 남은 길이, (PAGE_SIZE * IoGetDmaAdapter에서 반환된 NumberOfMapRegisters))

각 드라이버가 DMA 전송에 대해 유지 관리해야 하는 컨텍스트 정보는 특정 디바이스의 요구 사항에 따라 달라집니다. 일반적인 컨텍스트에는 MDL(CurrentVa)의 현재 가상 주소, 지금까지 전송된 바이트 수, 전송할 남은 바이트 수 및 현재 IRP에 대한 포인터가 포함될 수 있습니다.

분산/수집 기능이 있는 디바이스 드라이버의 경우 MapTransfer에 대한 Length 매개 변수는 입력 및 출력 매개 변수입니다. MapTransfer에서 반환할 때 시스템이 매핑한 데이터의 바이트 수를 나타냅니다. 즉, 반환된 논리 주소와 함께 Length의 반환 값은 버스 마스터 어댑터가 이 DMA 작업에서 이 전송에 사용할 수 있는 논리 주소 범위를 나타냅니다.

참고LengthMapTransfer에 의해 덮어쓰여지으므로 다음 구현 지침을 따릅니다. 디바이스가 분산/수집을 지원하는 경우 IRP의 드라이버 I/O 스택 위치에 있는 Length 에 대한 포인터를 Length 매개 변수로 MapTransfer 에 전달하지 마세요.

이렇게 하면 현재 IRP의 값이 삭제되어 드라이버가 요청된 모든 데이터를 전송했는지 여부를 확인할 수 없습니다.

각 DMA 작업이 끝나면 드라이버는 유효한 어댑터 개체 포인터와 MapRegisterBase 핸들을 사용하여 FlushAdapterBuffers를 호출하여 모든 데이터가 전송되었는지 확인하고 현재 DMA 작업에 대한 물리적-논리 매핑을 해제해야 합니다. 드라이버가 현재 IRP를 충족하도록 추가 DMA 작업을 설정해야 하는 경우 각 전송 작업이 완료된 후 FlushAdapterBuffers 를 호출해야 합니다.

요청된 모든 전송이 완료되거나 드라이버가 IRP에 대한 오류 상태를 반환해야 하는 경우 드라이버는 버스 마스터 어댑터에 대해 가능한 최상의 처리량을 얻기 위해 FlushAdapterBuffers에 대한 마지막 호출 직후 FreeMapRegisters를 호출해야 합니다. FreeMapRegisters에 대한 호출에서 드라이버는 AllocateAdapterChannel에 대한 이전 호출에서 전달한 어댑터 개체 포인터를 전달해야 합니다.