NDIS Точечная и сборная DMA

Внимание!

Для процессоров Arm и Arm64 мы настоятельно рекомендуем, чтобы записи драйверов NDIS использовали WDF DMA или WDM DMA вместо NDIS Scatter/Gather DMA.

Дополнительные сведения о WDF DMA см. в разделе Обработка операций DMA в драйверах KMDF.

Дополнительные сведения о WDM DMA см. в дочерних разделах, связанных с DMA статьи Управление входными и выходными данными для драйверов.

Для передачи данных между сетевой картой и системной памятью драйверы мини-портов NDIS могут использовать метод Точечная и сборная DMA (SGDMA). Для успешной передачи DMA требуется, чтобы физический адрес данных был в диапазоне адресов, который поддерживает сетевая карта. HAL предоставляет драйверу механизм для получения списка физических адресов для цепочки MDL и при необходимости выполняет двойную буферизацию данных в физический диапазон адресов.

В версиях NDIS до NDIS 6.0 поддержка SGDMA в драйверах мини-портов и NDIS в некоторых отношениях ограничена и, в частности, не работает хорошо в сценарии отправки с несколькими пакетами. Поддержка NDIS 6.0 SGDMA позволяет преодолеть эти ограничения, предоставляя простой интерфейс для драйверов мини-портов.

История NDIS SGDMA

В версиях NDIS до NDIS 6.0 NDIS получает список точечной сбора (SG) для каждого пакета перед отправкой пакета драйверу мини-порта. NDIS также обрабатывает случай, когда исходная попытка получить список SG завершается сбоем из-за чрезмерной фрагментации. В этом случае NDIS выполняет двойную буферизацию пакета в непрерывный буфер и пытается повторить попытку. HAL также может использовать двойную буферизацию данных в физический адрес, поддерживаемый сетевой картой, если, например, физический адрес данных превышает 32-разрядный максимум, а сетевой адаптер не поддерживает 64-разрядную DMA.

Чтобы избежать взаимоблокировки, NDIS получает список SG для пакета и отправляет по одному пакету за раз. Если NDIS попытается сопоставить все пакеты перед их отправкой драйверу мини-порта, система может исчерпнуть ресурсы. В этом случае NDIS будет ожидать, пока регистры карт станут доступными, в то время как некоторые регистры карт будут заблокированы для пакетов, которые не были отправлены. Заблокированные пакеты нельзя использовать повторно.

Этот подход к поддержке SGDMA имеет следующие ограничения:

  • Так как пакет сопоставляется до того, как он попадает в драйвер мини-порта, драйвер не может оптимизировать для небольших пакетов или пакетов, которые слишком фрагментированы. Драйвер мини-порта не может удвоить буфер пакета на известный физический адрес.

  • Нет никакой гарантии, что физический массив адресов, переданный NDIS драйверу мини-порта, сопоставляется с виртуальным адресом исходных данных. Таким образом, если драйвер изменяет данные по виртуальному адресу в цепочке MDL перед их отправкой, изменения, внесенные в данные, не отражаются в данных в физических адресах. В этом случае сетевой адаптер отправляет неизмененные данные.

  • NDIS ограничивается отправкой одного пакета за раз, чтобы избежать взаимоблокировки из-за проблем с ресурсами. Это не так эффективно, как отправка нескольких пакетов.

  • Поскольку NDIS не может определить возможности передачи драйверов мини-портов, он не может предварительно выделить хранилище для буфера списка SG. Поэтому NDIS должна выделить необходимое хранилище во время выполнения. Это не так эффективно, как предварительное выделение хранилища.

  • Функции HAL, которые выделяют список SG, должны вызываться по адресу IRQL = DISPATCH_LEVEL. NDIS не содержит текущих сведений IRQL, поэтому необходимо задать для irQL значение DISPATCH_LEVEL даже если он уже находится на DISPATCH_LEVEL. Это не эффективно, если IRQL уже находится на DISPATCH_LEVEL.

Преимущества поддержки NDIS SGDMA

В интерфейсе NDIS 6.0 и более поздних версий SGDMA NDIS не сопоставляет буфер данных перед отправкой в драйвер мини-порта. Вместо этого NDIS предоставляет драйверу интерфейс для сопоставления сетевых данных.

Такой подход дает следующие преимущества:

  • Так как NDIS предоставляет интерфейс HAL для сопоставления сетевых данных, NDIS защищает драйверы минипорта от сложности и деталей процесса сопоставления.

  • Драйверы мини-портов имеют доступ к данным перед их сопоставлением. Поэтому любые изменения, внесенные в исходные данные, отражаются в данных, представленных списком SG, даже если NDIS или HAL дважды буферизируют данные.

  • Драйверы минипорта могут оптимизировать передачу небольших или сильно фрагментированных пакетов, копируя их в предварительно размещенный буфер с известным физическим адресом. Такой подход позволяет избежать необязательного сопоставления и, следовательно, повысить производительность системы.

  • NDIS может безопасно отправлять несколько буферов в драйвер мини-порта. Это приводит к уменьшению числа вызовов драйверов мини-портов и, следовательно, повышает производительность системы.

  • Драйверы мини-портов могут предварительно выделить память для списка SG в составе блоков дескриптора передачи. Поэтому драйверы NDIS или мини-порта не обязаны выделять память для списков SG во время выполнения.

  • Так как драйверы мини-портов могут работать в среде IRQL = DISPATCH_LEVEL, драйверы минипорта могут избежать ненужных вызовов для вызова IRQL для DISPATCH_LEVEL. Например, так как отправка выполняется в контексте прерывания DPC, драйверы мини-портов могут освободить список SG без вызова IRQL.

Регистрация и отмена регистрации каналов DMA

Драйвер мини-порта NDIS вызывает функцию NdisMRegisterScatterGatherDma из функции MiniportInitializeEx для регистрации канала DMA с помощью NDIS.

Драйвер мини-порта передает описание DMA в NdisMRegisterScatterGatherDma в параметре DmaDescription . NdisMRegisterScatterGatherDma возвращает размер буфера, который должен быть достаточно большим, чтобы вместить точечный/собирательный список. Драйверы мини-портов должны использовать этот размер для предварительного выделения хранилища для точечных и сборных списков.

Драйвер мини-порта также передает NdisMRegisterScatterGatherDma точки входа для функций MiniportXxx, которые NDIS вызывает для обработки списка точечной и сборной. NDIS вызывает функцию MiniportProcessSGList драйвера минипорта после того, как HAL настроит список точечной и сборной для буфера. NdisMRegisterScatterGatherDma предоставляет дескриптор в параметре pNdisMiniportDmaHandle , который драйвер мини-порта должен использовать в последующих вызовах функций DMA NDIS scatter/gather.

Драйвер мини-порта NDIS вызывает функцию NdisMDeregisterScatterGatherDma из своей функции MiniportHaltEx , чтобы освободить точечные и собирательные ресурсы DMA.

Выделение и освобождение точечных и собирающихся списков

Драйвер мини-порта NDIS вызывает функцию NdisMAllocateNetBufferSGList в функции MiniportSendNetBufferLists . Драйвер мини-порта вызывает NdisMAllocateNetBufferSGList один раз для каждой NET_BUFFER структуры, которую он должен сопоставить. Когда ресурсы станут доступными и HAL подготовит список SG, NDIS вызывает функцию MiniportProcessSGList драйвера. NDIS может вызывать MiniportProcessSGList до или после вызова NdisMAllocateNetBufferSGList .

Для повышения производительности системы список точечной и сборной создается на основе сетевых данных, начиная с начала MDL, указанного в элементе CurrentMdl связанной структуры NET_BUFFER_DATA . Начало сетевых данных в списке SG смещается от начала списка SG на значение, указанное в элементе CurrentMdlOffset связанной структуры NET_BUFFER_DATA .

При обработке DPC для прерывания отправки и завершения и после того, как драйверу мини-порта больше не нужен список SG, драйвер мини-порта должен вызвать функцию NdisMFreeNetBufferSGList , чтобы освободить список SG.

Примечание Не вызывайте NdisMFreeNetBufferSGList , пока драйвер или оборудование по-прежнему обращается к памяти, описанной структурой NET_BUFFER, связанной со списком точечной и сборной. 

Перед доступом к полученным данным драйверы мини-портов должны вызвать NdisMFreeNetBufferSGList для очистки кэша памяти.