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


Базовый шаблон вызовов для подпрограмм DMA версии 3

Чтобы выполнить передачу DMA, которая использует подпрограммы в интерфейсе операций DMA версии 3, драйвер должен выполнить действия, описанные в следующем списке. Эти действия являются общими как для подчиненных устройств, так и для устройств с master шиной. Версия 3 этого интерфейса доступна начиная с Windows 8. Дополнительные сведения о подпрограммах в этом интерфейсе см. в разделе DMA_OPERATIONS.

Шаг 1. Получение объекта адаптера DMA

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

Шаг 2. Получение описания необходимых ресурсов DMA

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

Входные параметры для этого вызова описывают буфер памяти, используемый для передачи, и направление (чтение или запись) передачи.

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

Шаг 3. Запрос необходимых ресурсов DMA

Драйвер вызывает подпрограмму AllocateAdapterChannelEx для выделения ресурсов для назначения объекту адаптера DMA. К этим ресурсам относятся канал DMA и регистры карт.

Вызов AllocateAdapterChannelEx может быть асинхронным или синхронным.

Если флаг DMA_SYNCHRONOUS_CALLBACK не задан, вызов является асинхронным. В этом случае параметр ExecutionRoutine указывает на предоставленную вызывающим объектом подпрограмму выполнения, которая вызывается при наличии запрошенных ресурсов. В случае успешного выполнения асинхронный вызов AllocateAdapterChannelEx возвращает STATUS_SUCCESS, не дожидаясь выполнения процедуры выполнения.

Если установлен флаг DMA_SYNCHRONOUS_CALLBACK, вызов AllocateAdapterChannelEx является синхронным. В этом случае параметр ExecutionRoutine в вызове является необязательным, а AllocateAdapterChannelEx ведет себя следующим образом:

  • Если свойство ExecutionRoutine не равно NULL и ресурсы DMA могут быть выделены немедленно, Метод AllocateAdapterChannelEx вызывает подпрограмму выполнения в контексте вызывающего потока. После завершения выполнения подпрограммы AllocateAdapterChannelEx возвращает STATUS_SUCCESS. Если ресурсы недоступны сразу, функция AllocateAdapterChannelEx завершается сбоем и возвращает код состояния ошибки STATUS_INSUFFICIENT_RESOURCES.

  • Если executionRoutine имеет значение NULL и AllocateAdapterChannelEx может немедленно выделить ресурсы DMA, Функция AllocateAdapterChannelEx возвращает STATUS_SUCCESS. Если все ресурсы недоступны сразу, вызов завершается сбоем с кодом состояния ошибки STATUS_INSUFFICIENT_RESOURCES.

Для синхронных вызовов, возвращающих STATUS_SUCCESS, если параметр MapRegisterBase для Объекта AllocateAdapterChannelEx не равен NULL, AllocateAdapterChannelEx записывает базовый адрес выделенных регистров карты в адрес, на который указывает параметр MapRegisterBase . Если ExecutionRoutine имеет значение NULL, MapRegisterBase должен иметь значение, отличное от NULL. Если свойство ExecutionRoutine не равно NULL, параметр MapRegisterBase для Параметра AllocateAdapterChannelEx является необязательным, а подпрограмма выполнения получает базовый адрес регистра карты в качестве входного параметра.

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

В последующих вызовах подпрограммы MapTransferEx (см. шаг 5) драйвер предоставляет базовый адрес регистра карты в качестве входного параметра.

Если значение ExecutionRoutine не равно NULL, подпрограмма выполнения возвращает значение состояния, указывающее на ликвидацию выделенных ресурсов. Для системных передач DMA это возвращаемое значение должно иметь значение KeepObject. Это значение информирует операционную систему о том, что объект адаптера (и все его выделенные ресурсы) используется и не должен освобождаться. Если подпрограмма выполнения не указана, драйвер должен вместо этого вызвать подпрограмму FreeAdapterObject и указать KeepObject в качестве параметра AllocationOption .

Шаг 4. При необходимости отмена ожидающего запроса ресурса

После того как вызов AllocateAdapterChannelEx помещает адаптер DMA в очередь для ожидания ресурсов DMA, драйвер может при необходимости вызвать подпрограмму CancelAdapterChannel , чтобы отменить ожидающий запрос ресурса.

Если CancelAdapterChannel возвращает значение TRUE, запрос ресурса успешно отменен. Если подпрограмма выполнения была предоставлена в вызове AllocateAdapterChannelEx , эта подпрограмма не выполняется.

Если CancelAdapterChannel возвращает значение FALSE, запрос ресурса нельзя отменить, так как он уже был предоставлен. Если подпрограмма выполнения была указана в вызове AllocateAdapterChannelEx , будет вызвана эта подпрограмма.

Шаг 5. Инициализация ресурсов DMA и запуск передачи DMA

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

MapTransferEx поддерживает цепочки многомерных выражений в качестве входных параметров. Каждый MDL описывает область буфера DMA, которая является непрерывной в виртуальной памяти. Когда MapTransferEx создает список точечной и сборной, он автоматически обрабатывает переходы из одной практически непрерывной буферной области в другую без вмешательства драйвера. Дополнительные сведения см. в разделе Использование процедуры MapTransferEx.

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

Если MapTransferEx не может сопоставить весь запрошенный размер передачи, он установит выходной параметр *Length на сопоставленную длину и вернет STATUS_SUCCESS.

Шаг 6. При необходимости выполните операции, связанные с оборудованием

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

Подпрограммы в интерфейсе операций DMA поддерживают когерентность кэша для передачИ DMA таким образом, чтобы они были прозрачны для драйверов, использующих эти подпрограммы. На платформах, которые не обеспечивают когерентность кэша в оборудовании, MapTransferEx обеспечивает очистку кэшей данных процессора перед записью (из памяти на устройство). Для операций чтения (с устройства в память) кэши становятся недействительными во время вызова процедуры FlushAdapterBuffersEx (см. шаг 8), которая следует за каждым вызовом MapTransferEx .

Шаг 7. Получение уведомления о завершении передачи DMA

После завершения передачи DMA драйвер получает уведомление одним из следующих двух способов:

  • Прерывание драйвера устройства для устройства с master шиной
  • Выполнение процедуры завершения, предоставляемой драйвером, для подчиненного устройства, использующего системный контроллер DMA.

Для передачи системного DMA драйвер может предоставить в MapTransferEx подпрограмму завершения в качестве входного параметра.

Шаг 8. Очистка всех данных, которые остаются в кэше

После завершения передачи DMA драйвер должен вызвать подпрограмму FlushAdapterBuffersEx для очистки всех данных, которые остаются в кэше. Драйвер должен вызывать FlushAdapterBuffersEx после каждого вызова MapTransferEx .

Если вызов MapTransferEx сопоставляет только часть буфера данных DMA, драйвер должен снова вызвать MapTransferEx , чтобы сопоставить оставшиеся данные. Для сложной передачи может потребоваться несколько вызовов MapTransferEx . Для каждого дополнительного вызова MapTransferEx повторите шаги 5–8.

Шаг 9. Освобождение каналов DMA и регистров карт

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

Шаг 10. Освобождение объекта адаптера DMA

После завершения всех передач DMA и освобождения всех ранее выделенных регистров карты драйвер вызывает подпрограмму PutDmaAdapter , чтобы освободить объект адаптера.