Программирование драйверов Windows

Передача PnP IRP пакетов нижним драйверным слоям


Все запросы PnP инициируются PnP Менеджером, и он всегда направляет эти запросы драйверу, находящемуся в стеке устройств на вершине стека.

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

Трансляция PnP запросов вниз по стеку устройств необходима по многим причинам. Некоторые драйверы в стеке могут вносить свою лепту в обработку запроса, но не один драйвер не должен подразумевать, что запрос может быть полностью завершен на данном уровне. Например, уведомление об остановке устройства является критичным для всех слоев драйверных объектов.

Чтобы передать PnP запрос вниз, драйвер помечает IRP пакет как "завершенный" установкой соответствующих значений в полях IoStatus.Status и IoStatus.Information, а затем производит вызовы IoCopyCurrentStackLocationToNext

и IoCallDriver. Нижележащий драйвер известен еще при выполнении AddDevice (из вызова IoAttachDeviceToDeviceStack), а указатель на него рекомендуется сохранять в структуре расширении объекта устройства. Пример кода, выполняющего эти действия, приводится ниже.

... IoCopyCurrentIrpStackLocationToNext( pIrp ); PDEVICE_EXTENSION pThisDeviceExtension = (PDEVICE_EXTENSION) pThisDeviceObject-&#62DeviceExtension; IoCallDriver( pThisDeviceExtension -&#62pUnderlyingDevice, pIrp ); ...

В случае, если у драйвера нет необходимости ожидать окончания обработки переданного вниз запроса драйверами нижних уровней, то может быть использован более эффективный механизм для пропуска участка текущего IRP стека. Функция IoSkipCurrentIrpStackLocation

просто удаляет участок текущего стека IRP пакета из участия в обработке. Этот механизм предлагается для обращения с PnP запросами, которые не обрабатываются данным драйвером и которые должны быть просто переданы следующему нижележащему драйверу:

NTSTATUS OnlyTranslateIrpDown(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp) { IoSkipCurrentIrpStackLocation( pIrp ); PDEVICE_EXTENSION pDeviceExtension = (PDEVICE_EXTENSION) pDeviceObject -&#62DeviceExtension; return IoCallDriver(pThisDeviceExtension-&#62pUnderlyingDevice, pIrp); }

Бывают случаи, когда драйвер вынужден пропускать вниз PnP запросы раньше, чем он завершает собственную работу над ними. Например, при обработке запроса с кодом IRP_MN_START_DEVICE драйверу, как правило, необходимо дождаться, пока стартуют низкоуровневые драйверы перед началом работы их собственного аппаратного обеспечения. Шина и любое низкоуровневое аппаратное обеспечение инициализируется до старта отдельных устройств. Таким образом, высокоуровневые драйвера должны сначала транслировать вниз запрос и затем дождаться завершения низкоуровневой обработки перед продолжением своей работы.

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



Содержание раздела