다음을 통해 공유


NDIS 분산/수집 DMA

주의

Arm 및 Arm64 프로세서의 경우 NDIS 드라이버 작성기가 NDIS 분산/수집 DMA 대신 WDF DMA 또는 WDM DMA를 사용하는 것이 좋습니다.

WDF DMA에 대한 자세한 내용은 KMDF 드라이버에서 DMA 작업 처리를 참조하세요.

WDM DMA에 대한 자세한 내용은 드라이버에 대한 입력/출력 관리의 DMA 관련 자식 topics 참조하세요.

NDIS 미니포트 드라이버는 SGDMA(분산/수집 DMA) 메서드를 사용하여 NIC와 시스템 메모리 간에 데이터를 전송할 수 있습니다. 성공적인 DMA 전송을 위해서는 데이터의 실제 주소가 NIC에서 지원하는 주소 범위에 있어야 합니다. HAL은 드라이버가 MDL 체인의 실제 주소 목록을 가져오는 메커니즘을 제공하며 필요한 경우 데이터를 실제 주소 범위로 두 번 버퍼링합니다.

NDIS 6.0 이전의 NDIS 버전에서는 미니포트 드라이버 및 NDIS의 SGDMA 지원이 어떤 면에서 제한되며, 특히 멀티패켓 송신 시나리오에서는 잘 작동하지 않습니다. NDIS 6.0 SGDMA 지원은 미니포트 드라이버에 대한 간단한 인터페이스를 제공하면서 이러한 제한을 극복합니다.

NDIS SGDMA의 기록

NDIS 6.0 이전의 NDIS 버전에서 NDIS는 패킷을 미니포트 드라이버로 보내기 전에 각 패킷에 대한 SG(분산 수집) 목록을 가져옵니다. 또한 NDIS는 과도한 조각화로 인해 SG 목록을 가져오기 위한 원래 시도가 실패하는 경우를 처리합니다. 이 경우 NDIS는 패킷을 연속 버퍼로 두 번 버퍼링하고 다시 시도합니다. HAL은 데이터의 실제 주소가 32비트 최댓값을 초과하고 NIC가 64비트 DMA를 지원하지 않는 경우 NIC가 지원하는 실제 주소로 데이터를 두 번 버퍼링할 수도 있습니다.

교착 상태를 방지하기 위해 NDIS는 패킷에 대한 SG 목록을 가져오고 한 번에 하나의 패킷을 보냅니다. NDIS가 미니포트 드라이버로 보내기 전에 모든 패킷을 매핑하려고 하면 시스템에서 리소스가 부족할 수 있습니다. 이 경우 NDIS는 전송되지 않은 패킷에 대해 일부 맵 레지스터가 잠겨 있는 동안 지도 레지스터를 사용할 수 있을 때까지 기다리고 있습니다. 잠긴 패킷을 다시 사용할 수 없습니다.

SGDMA 지원에 대한 이 접근 방식에는 다음과 같은 제한 사항이 있습니다.

  • 패킷이 미니포트 드라이버에 도착하기 전에 매핑되므로 드라이버는 너무 조각화된 작은 패킷 또는 패킷에 대해 최적화할 수 없습니다. 미니포트 드라이버는 패킷을 알려진 실제 주소로 두 배로 버퍼링할 수 없습니다.

  • NDIS가 미니포트 드라이버에 전달한 실제 주소 배열이 원래 데이터의 가상 주소에 매핑된다는 보장은 없습니다. 따라서 드라이버가 데이터를 보내기 전에 MDL 체인의 가상 주소에서 데이터를 변경하는 경우 데이터에 대한 수정 사항은 실제 주소의 데이터에 반영되지 않습니다. 이 경우 NIC는 수정되지 않은 데이터를 보냅니다.

  • NDIS는 리소스 문제로 인한 교착 상태를 방지하기 위해 한 번에 하나의 패킷을 보내는 것으로 제한됩니다. 이는 여러 패킷을 보내는 것만큼 효율적이지 않습니다.

  • NDIS는 미니포트 드라이버의 전송 기능을 확인할 수 없으므로 SG 목록 버퍼에 대한 스토리지를 미리 할당할 수 없습니다. 따라서 NDIS는 런타임에 필요한 스토리지를 할당해야 합니다. 이는 스토리지를 미리 할당하는 것만큼 효율적이지 않습니다.

  • SG 목록을 할당하는 HAL 함수는 IRQL = DISPATCH_LEVEL 호출해야 합니다. NDIS에는 현재 IRQL 정보가 없으므로 이미 DISPATCH_LEVEL 경우에도 IRQL을 DISPATCH_LEVEL 설정해야 합니다. IRQL이 이미 DISPATCH_LEVEL 있으면 효율적이지 않습니다.

NDIS SGDMA 지원의 이점

NDIS 6.0 이상 SGDMA 인터페이스에서 NDIS는 데이터 버퍼를 미니포트 드라이버로 보내기 전에 매핑하지 않습니다. 대신 NDIS는 드라이버가 네트워크 데이터를 매핑할 수 있는 인터페이스를 제공합니다.

이 방법은 다음과 같은 이점을 얻을 수 있습니다.

  • NDIS는 네트워크 데이터를 매핑하기 위해 HAL에 인터페이스를 제공하므로 NDIS는 매핑 프로세스의 복잡성 및 세부 정보로부터 드라이버를 보호합니다.

  • 미니포트 드라이버는 매핑되기 전에 데이터에 액세스할 수 있습니다. 따라서 NDIS 또는 HAL이 데이터를 두 번 버퍼링하더라도 원래 데이터에 대한 모든 변경 내용이 SG 목록으로 표시되는 데이터에 반영됩니다.

  • 미니포트 드라이버는 알려진 물리적 주소를 사용하여 미리 할당된 버퍼에 복사하여 작거나 고도로 조각화된 패킷의 전송을 최적화할 수 있습니다. 이 방법은 필요하지 않은 매핑을 방지하므로 시스템 성능이 향상됩니다.

  • NDIS는 미니포트 드라이버에 여러 버퍼를 안전하게 보낼 수 있습니다. 이로 인해 드라이버를 최소화하기 위한 호출이 줄어들어 시스템 성능이 향상됩니다.

  • 미니포트 드라이버는 전송 설명자 블록의 일부로 SG 목록에 대한 메모리를 미리 할당할 수 있습니다. 따라서 런타임에 NDIS 또는 미니포트 드라이버는 SG 목록에 메모리를 할당할 필요가 없습니다.

  • 미니포트 드라이버는 IRQL = DISPATCH_LEVEL 실행할 수 있으므로 미니포트 드라이버는 IRQL을 DISPATCH_LEVEL 발생하도록 불필요한 호출을 방지할 수 있습니다. 예를 들어 보내기 완료는 인터럽트 DPC의 컨텍스트에서 발생하므로 미니포트 드라이버는 IRQL을 발생하지 않고 SG 목록을 해제할 수 있습니다.

DMA 채널 등록 및 등록 취소

NDIS 미니포트 드라이버는 MiniportInitializeEx 함수에서 NdisMRegisterScatterGatherDma 함수를 호출하여 DMA 채널을 NDIS에 등록합니다.

미니포트 드라이버는 DmaDescription 매개 변수의 NdisMRegisterScatterGatherDma에 DMA 설명을 전달합니다. NdisMRegisterScatterGatherDma 는 분산/수집 목록을 저장할 수 있을 만큼 커야 하는 버퍼의 크기를 반환합니다. 미니포트 드라이버는 이 크기를 사용하여 분산/수집 목록에 대한 스토리지를 미리 할당해야 합니다.

또한 미니포트 드라이버는 NDIS가 분산/수집 목록을 처리하기 위해 호출하는 MiniportXxx 함수의 진입점인 NdisMRegisterScatterGatherDma를 전달합니다. HAL이 버퍼에 대한 분산/수집 목록을 빌드한 후 NDIS는 미니포트 드라이버의 MiniportProcessSGList 함수를 호출합니다. NdisMRegisterScatterGatherDmapNdisMiniportDmaHandle 매개 변수에 핸들을 제공합니다. 이 매개 변수는 미니포트 드라이버가 NDIS 분산/수집 DMA 함수에 대한 후속 호출에 사용해야 합니다.

NDIS 미니포트 드라이버는 MiniportHaltEx 함수에서 NdisMDeregisterScatterGatherDma 함수를 호출하여 분산/수집 DMA 리소스를 해제합니다.

분산/수집 목록 할당 및 해제

NDIS 미니포트 드라이버는 MiniportSendNetBufferLists 함수에서 NdisMAllocateNetBufferSGList 함수를 호출합니다. 미니포트 드라이버는 매핑해야 하는 각 NET_BUFFER 구조에 대해 NdisMAllocateNetBufferSGList를 한 번 호출합니다. 리소스를 사용할 수 있고 HAL에 SG 목록이 준비되면 NDIS는 드라이버의 MiniportProcessSGList 함수를 호출합니다 . NDIS는 Miniport 드라이버의 NdisMAllocateNetBufferSGList 호출이 반환되기 전이나 후에 MiniportProcessSGList를 호출할 수 있습니다.

시스템 성능을 향상시키기 위해 분산/수집 목록은 연결된 NET_BUFFER_DATA 구조체의 CurrentMdl 멤버에 지정된 MDL의 시작 부분에서 시작하는 네트워크 데이터에서 생성됩니다. SG 목록에서 네트워크 데이터의 시작은 연결된 NET_BUFFER_DATA 구조체의 CurrentMdlOffset 멤버에 지정된 값으로 SG 목록의 시작 부분에서 오프셋됩니다.

송신 완료 인터럽트용 DPC를 처리하는 동안 미니포트 드라이버에 SG 목록이 더 이상 필요하지 않은 경우 미니포트 드라이버는 NdisMFreeNetBufferSGList 함수를 호출하여 SG 목록을 해제해야 합니다.

참고 드라이버 또는 하드웨어가 분산/수집 목록과 연결된 NET_BUFFER 구조에서 설명하는 메모리에 계속 액세스하는 동안에는 NdisMFreeNetBufferSGList를 호출하지 마세요. 

받은 데이터에 액세스하기 전에 미니포트 드라이버는 NdisMFreeNetBufferSGList 를 호출하여 메모리 캐시를 플러시해야 합니다.