Поделиться через


Использование Common-Buffer Bus-Master DMA

Как описано в разделе Использование Bus-Master DMA, некоторые драйверы для устройств DMA с master шинами используют DMA исключительно с общим буфером, а некоторые используют DMA с общим буфером в сочетании с DMA на основе пакетов.

Экономичное использование DMA с общим буфером. Настройка общего буфера может связать некоторые (или все, в зависимости от размера запрошенного буфера) регистров карты, связанных с объектом адаптера, который представляет адаптер master шины.

Экономическая настройка общих буферных областей, например с помощью PAGE_SIZE блоков или одного выделения, оставляет больше регистров карты доступными для операций DMA на основе пакетов. Он также оставляет больше системной памяти свободным для других целей, что обеспечивает лучшую общую производительность драйвера и системы.

Чтобы настроить общий буфер для master шиной DMA, драйвер устройства DMA master шины должен вызвать AllocateCommonBuffer с указателем на объект адаптера, возвращенным IoGetDmaAdapter. Как правило, драйвер выполняет этот вызов из своей подпрограммы DispatchPnP для IRP_MN_START_DEVICE запросов. Драйвер должен выделять общий буфер только в том случае, если он будет многократно использовать буфер для операций DMA, пока драйвер остается загруженным. На следующей схеме показан такой вызов Метода AllocateCommonBuffer.

Схема, иллюстрирующая выделение общего буфера для шин master dma.

Запрошенный размер буфера, показанный на предыдущей схеме Как LengthForBuffer, определяет, сколько регистров карты необходимо использовать для предоставления виртуально-логического сопоставления для общего буфера. Используйте макрос BYTES_TO_PAGES , чтобы определить максимальное необходимое количество страниц (BYTES_TO_PAGES (LengthForBuffer)). Это значение не может быть больше значения NumberOfMapRegisters, возвращаемого IoGetDmaAdapter.

Кроме того, вызывающий объект должен предоставить следующее:

  • Логическое значение, указывающее, следует ли включить кэширование.

    Примечание Это значение игнорируется. Операционная система определяет, следует ли включать кэшированную память в общем буфере, который должен быть выделен. Это решение основано на архитектуре процессора и шине устройства.

    На компьютерах с процессорами x86, x64 и Itanium включена кэшированная память.

    На компьютерах с процессорами arm или Arm 64 операционная система не включает кэшированную память для всех устройств автоматически. Система использует метод ACPI_CCA для каждого устройства, чтобы определить, является ли устройство согласованным в кэше.

  • Указатель на переменную, определяемую драйвером, которая будет содержать доступный устройству базовый логический адрес для буфера (BufferLogicalAddress на предыдущей схеме) при возвращении из AllocateCommonBuffer

Если вызов выполнен успешно, Функция AllocateCommonBuffer возвращает базовый виртуальный адрес буфера , доступный драйверу (BufferVirtualAddress на предыдущей схеме), который драйвер должен сохранить в расширении устройства, расширении контроллера или другой доступной драйверу резидентной области хранения данных (непагированный пул, выделенный драйвером).

Функция AllocateCommonBuffer возвращает значение NULL , если не может выделить память для буфера. Если возвращенный базовый виртуальный адрес имеет значение NULL, драйвер должен либо использовать исключительно поддержку DMA на основе пакетов в системе, либо драйвер должен завершить запрос IRP_MN_START_DEVICE , возвращая STATUS_INSUFFICIENT_RESOURCES.

В противном случае драйвер может использовать выделенный общий буфер в качестве доступной для драйвера и адаптера области хранения для передачи данных DMA.

Когда диспетчер PnP отправляет IRP, который останавливает или удаляет устройство, драйвер должен вызвать FreeCommonBuffer , чтобы освободить каждый общий буфер, который он выделил.