[Previous] [Next]

Ограничения, накладываемые на WDM драйверы спецификацией PnP

Для того чтобы соответствовать драйверной модели WDM, драйвер обязан поддерживать обработку специфичных PnP IRP пакетов, каких конкретно — это определяется конкретным типом объекта устройства — не-шинный FDO, шинный FDO и PDO. Во всяком случае, IRP пакеты с приведенными в таблице кодами IRP_MN_Xxx должны поддерживаться драйверами всех типов.

Таблица 9.11. Суб-коды IRP_MN_Xxx

IRP_MN_Xxx Значение
IRP_MN_START_DEVICE (Ре)Инициализация устройства с заданными ресурсами
IRP_MN_QUERY_STOP_DEVICE Осуществима ли остановка устройства для возможного переопределения ресурсов?
IRP_MN_STOP_DEVICE Остановка устройства с потенциальной возможностью перезапуска или удаления из системы
IRP_MN_CANCEL_STOP_DEVICE Уведомляет, что предыдущий запрос QUERY_STOP не получит дальнейшего развития
IRP_MN_QUERY_REMOVE_DEVICE Может ли быть выполнено безопасное удаление устройства в текущий момент?
IRP_MN_REMOVE_DEVICE Выполнить работу, обратную работе AddDevice
IRP_MN_CANCEL_REMOVE_DEVICE Уведомляет, что предыдущий запрос QUERY_REMOVE не получит дальнейшего развития
IRP_MN_SURPRISE_REMOVAL

Уведомляет, что устройство было удалено без предварительного предупреждения

Передача 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->DeviceExtension;
IoCallDriver( pThisDeviceExtension ->pUnderlyingDevice, pIrp );
...

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

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

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

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

Device Enumeration — всеобщая перепись устройств

Как было сказано ранее, Менеджер конфигурирования PnP ответственен за выполнение переписи устройств, обнаруженных в системе. Стартовало ли устройство при загрузке системы, или оно добавляется/удаляется позже, шинный драйвер отвечает за идентификацию и ведение списка подключенной аппаратуры. Аппаратные ресурсы, необходимые устройству, предоставляются драйверу этого устройства, когда ему отправляется сообщение (IRP пакет) с кодом IRP_MJ_PNP и с суб-кодом IRP_MN_START_DEVICE. Весьма показателен в этом отношении пример из пакета DDK, посвященный драйверам шины и устройств TOASTER.