Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Любой драйвер может потребоваться разделить запрос на передачу и выполнить несколько операций передачи DMA для удовлетворения заданного IRP в зависимости от следующего:
Количество регистров карты , возвращаемых IoGetDmaAdapter
Байты передаваемых данных, содержащиеся в элементе длины стека ввода-вывода драйвера для IRP
Количество границ страницы в системной физической памяти для буфера, из которого драйвер передает данные.
Ограничения на операции DMA драйвера, специфичные для устройств. Например, драйвер дисковой системы "AT" должен разделить запросы на передачу более 256 секторов из-за ограничений контроллера диска.
Драйвер может определить количество регистров карты, необходимых для передачи всех данных, указанных IRP, следующим образом:
Вызов MmGetMdlVirtualAddress, передавая указатель на MDL по адресу Irp->MdlAddress, чтобы получить начальный виртуальный адрес буфера. Обратите внимание, что драйвер не должен пытаться получить доступ к памяти с помощью этого виртуального адреса. Значение, возвращаемое MmGetMdlVirtualAddress , является индексом в MDL, а не обязательно допустимым адресом.
Передайте возвращённый индекс и значение Length, находящиеся в расположении стека ввода-вывода драйвера, в макрос ADDRESS_AND_SIZE_TO_SPAN_PAGES.
Если значение, возвращаемое ADDRESS_AND_SIZE_TO_SPAN_PAGES, больше значения NumberOfMapRegisters, возвращаемого IoGetDmaAdapter, драйвер не может передать все запрошенные данные для этого IRP в одной операции DMA. Вместо этого необходимо выполнить следующее:
Разделите буфер на части, размеры которых соответствуют количеству доступных регистров карты и учитывают любые ограничения DMA, специфичные для устройства.
Выполняйте столько операций DMA, сколько требуется для удовлетворения запроса на передачу.
Например, предположим, что ADDRESS_AND_SIZE_TO_SPAN_PAGES указывает, что для выполнения запроса на передачу необходимо двенадцать регистров карт, но значение NumberOfMapRegisters, возвращаемое IoGetDmaAdapter, составляет всего пять. (Предположим, нет ограничений DMA для конкретного устройства.) В этом случае драйвер должен выполнять три операции передачи DMA, вызывая MapTransfer три раза для передачи всех данных, запрошенных IRP.
Драйверы устройств DMA системы используют различные методы разделения передачи DMA, при недостаточности регистров карты для удовлетворения запроса IRP одной операцией ввода-вывода. Одним из способов использования является следующее:
Вызовите IoAllocateMdl , чтобы выделить MDL, описывающий часть пользовательского буфера.
Вызовите MmProbeAndLockPages, чтобы заблокировать эту часть буфера пользователя.
Передайте данные для этой части буфера.
Вызовите MmUnlockPages и выполните одно из следующих действий:
- Если MDL, выделенный драйвером на шаге 1, достаточно велик для следующей части передачи, вызовите MmPrepareMdlForReuse и повторите шаги 2–4.
- В противном случае вызовите IoFreeMdl и повторите шаги 1–4.
Вызовите MmUnlockPages и IoFreeMdl, когда все данные будут переданы.
Если драйвер наивысшего уровня не может заблокировать весь буфер пользователя с помощью MmProbeAndLockPages на компьютере с ограниченным объемом памяти, он может сделать следующее:
Вызовите IoBuildSynchronousFsdRequest, чтобы выделить IRP для частичной передачи и запретить доступ к части пользовательского буфера. Заблокированная область обычно кратна PAGE_SIZE или имеет размер, соответствующий пропускной способности базового устройства.
Вызовите IoCallDriver для частичной передачи IRP и вызовите KeWaitForSingleObject , чтобы ждать объекта события, который драйвер настраивает для связи с его частичным переносом IRP, если более низкие драйверы возвращают STATUS_PENDING.
Как только управление восстановлено, повторите шаги 1 и 2 до передачи всех данных, а затем завершите исходный процесс IRP.
Когда драйвер класса хранилища разбивает большие запросы на передачу для базовых драйверов портов или минипортов SCSI, он выделяет дополнительную IRP для каждого элемента запроса на передачу. Он регистрирует подпрограмму IoCompletion для каждого IRP, выделенного драйвером, чтобы отслеживать состояние всего запроса на передачу и освобождать IRP, выделенные драйвером. Затем он отправляет эти IRPs на драйвер порта с помощью IoCallDriver.
Другие драйверы классов и портов могут использовать этот метод, только если драйвер класса может определить, сколько регистров карт доступны драйверу порта. Драйвер порта должен сохранять эту конфигурационную информацию в реестре для связанного драйвера класса, или парные драйверы должны определить частный интерфейс, используя внутренние запросы управления устройством, чтобы передать информацию о количестве доступных регистров карты от драйвера порта к драйверу класса.
Монолитный драйвер (то есть драйвер, который не входит в пару классов и портов) для устройства DMA должен разделить большие запросы на передачу. Такие драйверы обычно разделяют большой запрос на части и выполняют последовательность операций DMA для удовлетворения IRP.
Если запрос на передачу слишком велик для обработки базового драйвера устройства, драйвер с более высоким уровнем может вызвать MmGetMdlVirtualAddress и IoBuildPartialMdl, а затем настроить последовательность частичных передачи irPs для базовых драйверов устройств.