Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Подпрограмма MapTransferEx инициализирует набор ранее выделенных ресурсов DMA и запускает передачу DMA. Эта подпрограмма доступна в интерфейсе операций DMA версии 3. Версия 3 этого интерфейса поддерживается начиная с Windows 8. Дополнительные сведения об интерфейсе операций DMA см. в DMA_OPERATIONS.
Сравнение MapTransferEx с MapTransfer
MapTransferEx — улучшенная версия подпрограммы MapTransfer . MapTransfer доступен во всех версиях интерфейса операций DMA, начиная с версии 1 в Windows 2000. Один вызов MapTransfer может сопоставить один смежный блок физической памяти из MDL. Однако буфер данных для сложной передачи DMA может быть описан цепочкой MDL, и каждый MDL в цепочке может описать несколько блоков физической непрерывной памяти. Чтобы использовать MapTransfer для передачи такого буфера, драйвер должен выполнять много вызовов к MapTransfer. Как правило, эти вызовы выполняются внутри пары вложенных циклов. Внутренний цикл выполняет итерацию из одного блока непрерывной физической памяти к следующему в каждом MDL, а внешний цикл выполняет итерацию от одного MDL до следующего в цепочке MDL.
В отличие от этого, один вызов MapTransferEx может передавать весь буфер данных для сложной передачи DMA. Следующие три параметра MapTransferEx описывают буферную память, используемую для передачи.
| Параметр | Описание |
|---|---|
| Mdl | Указатель на первый MDL в цепочке одного или нескольких MDL. Дополнительные сведения о цепочках MDL см. в разделе Использование MDL. |
| смещение | Смещение буфера в байтах от начала памяти, описанной цепочкой MDL. |
| длина | Указатель на расположение, содержащее длину буфера данных в байтах. |
В начале вызова MapTransferEx подпрограмма MapTransferEx проходит по цепочке MDL, чтобы найти начало буфера. Начало буфера указывается параметром Offset . Затем, работая с начала буфера до конца, MapTransferEx создает список точечного или сбора, в котором каждый фрагмент буфера в списке является физически смежным блоком памяти из цепочки MDL. Чтобы создать этот список, MapTransferEx выполняет шаги из одного физического непрерывного блока памяти к следующему в каждом MDL и от одного MDL до следующего в цепочке MDL. Построение списка завершается, когда общий объем буферной памяти, описанной в списке scatter/gather, равен числу байтов, заданных параметром ввода *Length. Порядок фрагментов буфера в результирующем списке разброса/сбора соответствует порядку физически смежных блоков в цепочке MDL.
Несколько вызовов MapTransferEx
MapTransferEx может не всегда передавать весь буфер данных DMA в одном вызове. В следующем списке описаны некоторые условия, которые могут потребовать вызова MapTransferEx несколько раз для завершения передачи:
- Адаптер DMA требует регистров карты, а количество регистров карты, назначенных адаптеру, недостаточно для описания всего буфера.
- Хранилище, выделенное драйвером для хранения списка scatter/gather, недостаточно велико, чтобы содержать этот список для всего буфера.
- Передача использует системный контроллер DMA, который ограничивает количество фрагментов буфера, которые можно указать в аппаратном списке разбрасывания/сбора.
Во всех этих случаях MapTransferEx сопоставляет большую часть буфера данных, как это возможно в одном вызове, и сообщает драйверу, сколько буфера сопоставлено вызовом. Предыдущий список не содержит других условий, таких как поведение кэша для конкретной платформы, для завершения передачи может потребоваться несколько вызовов MapTransferEx . Будущие аппаратные платформы могут наложить дополнительные ограничения на длину передачи DMA. По этим причинам разработчики драйверов должны разработать свои драйверы для правильной обработки ситуации, в которой MapTransferEx не может сопоставить весь буфер данных DMA в одном вызове.
Перед вызовом MapTransferEx вызывающий объект задает параметр *Length число байтов в буфере данных DMA, которое по-прежнему необходимо сопоставить. Перед возвратом MapTransferEx задает *Length число байтов в буфере, которое фактически сопоставлено вызовом. Если вызов MapTransferEx не может сопоставить всю длину буфера, как указано в входном значении *Length , выходное значение *Length меньше входного значения. Если для передачи DMA требуется два или более вызова MapTransferEx, вызывающий драйвер должен получить выходное значение *Length от одного вызова, прежде чем указать значение *Length для следующего вызова.
Например, если вызов MapTransferEx может передавать только X байтов в буфер, для которого Offset = B и *Length = N (в входных данных), то при возврате *Length = X. Для следующего вызова MapTransferEx драйвер должен задать Offset = B + X и *Length = N - X. В обоих вызовах одна и та же цепочка MDL используется без изменений.
Если вызывающий объект указывает DmaCompletionRoutine, MapTransferEx записывает выходное значение *Length перед тем, как запланировать DmaCompletionRoutine для выполнения. Это поведение гарантирует, что обновленное значение *Length всегда доступно перед запуском DmaCompletionRoutine . Например, если для передачи DMA требуется два вызова MapTransferEx, то DmaCompletionRoutine, запланированная первым вызовом, может получить выходное значение *Length из первого вызова. Затем подпрограмма может использовать это значение для вычисления входного значения *Length для второго вызова. Обычно параметр Length указывает на местоположение в значении *CompletionContext, которое передается в DmaCompletionRoutine в качестве параметра.