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


Добавление устройства PnP в выполняющуюся систему

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

Большая часть этого обсуждения также относится к настройке устройства PnP, которое присутствует при загрузке компьютера. В частности, устройства, драйверы которых помечены SERVICE_DEMAND_START в INF-файле, настраиваются по сути так же, независимо от того, добавляется ли устройство динамически или присутствует во время загрузки.

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

схема, иллюстрирующая перечисление и создание отчетов об устройстве plug and play.

Следующие примечания соответствуют обведенным числам на предыдущем рисунке:

  1. Пользователь подключает устройство PnP к бесплатному слоту на шине PnP.

    В этом примере пользователь подключает usb-джойстик PnP к концентратору на USB-контроллере узла. USB-концентратор является устройством шины PnP, так как к нему можно подключить дочерние устройства.

  2. Драйвер функции для устройства шины определяет, что новое устройство находится на его шине.

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

    В этом примере USB-шина поддерживает уведомление с горячим подключением, поэтому драйвер функции для USB-шины получает уведомление об изменении ее дочерних элементов.

  3. Драйвер функции для устройства шины уведомляет диспетчера PnP об изменении набора дочерних устройств.

    Драйвер функции уведомляет диспетчер PnP, вызывая IoInvalidateDeviceRelations с типомBusRelations.

  4. Диспетчер PnP запрашивает у водителей автобуса текущий список устройств в шине.

    Диспетчер PnP отправляет запрос IRP_MN_QUERY_DEVICE_RELATIONS в стек устройств для шины. Значение Parameters.QueryDeviceRelations.TypeBusRelations, указывающее, что диспетчер PnP запрашивает текущий список устройств, присутствующих в шине (связи с шиной).

    Диспетчер PnP отправляет IRP верхнему водителю в стеке устройств для шины. В соответствии с правилами для PnP IRP каждый драйвер в стеке обрабатывает IRP, если это необходимо, и передает IRP следующему драйверу.

  5. Драйвер функции для устройства шины обрабатывает IRP.

    Подробные сведения об обработке этого IRP см. на странице справочника по IRP_MN_QUERY_DEVICE_RELATIONS .

    В этом примере драйвер USB-концентратора обрабатывает это IRP для FDO концентратора. Драйвер концентратора создает PDO для устройства джойстика и включает указатель на PDO джойстика в свой список дочерних устройств, возвращаемых с помощью IRP.

    Когда драйвер родительской шины USB-концентратора (пара классов и драйверов миникласса USB-контроллера) завершает IRP, IRP перемещается в стек устройств с помощью любых подпрограмм IoCompletion , зарегистрированных драйверами концентратора.

Обратите внимание, что драйвер функции шины сообщает об изменении списка дочерних элементов, запрашивая у диспетчера PnP список дочерних устройств. Результирующий запрос IRP_MN_QUERY_DEVICE_RELATIONS просматривается всеми драйверами для устройства шины. Как правило, драйвер функции шины является единственным драйвером, который обрабатывает IRP и сообщает дочерние элементы. В некоторых стеках устройств присутствует драйвер фильтра шины, который участвует в создании списка связей между шинами. Одним из примеров является ACPI, который подключается в качестве драйвера фильтра шины для устройств ACPI. В некоторых стеках устройств драйверы фильтров, не являющихся шинами, обрабатывают запрос IRP_MN_QUERY_DEVICE_RELATIONS , но это не типично.

На этом этапе диспетчер PnP имеет текущий список устройств в шине. Затем диспетчер PnP определяет, были ли устройства вновь доставлены или удалены. В этом примере есть одно новое устройство. На следующем рисунке показано, как диспетчер PnP создает devnode для нового устройства и начинает настраивать устройство.

схема, иллюстрирующая создание devnode для нового устройства plug and play.

Следующие примечания соответствуют обведенным числам на предыдущем рисунке:

  1. Диспетчер PnP создает devnodes для всех новых дочерних устройств в шине.

    Диспетчер PnP сравнивает список связей автобусов, возвращенных в IRP_MN_QUERY_DEVICE_RELATIONS IRP, со списком дочерних элементов для шины, зарегистрированных в дереве устройств PnP. Диспетчер PnP создает devnode для каждого нового устройства и инициирует обработку удаления для всех удаленных устройств.

    В этом примере есть одно новое устройство (джойстик), поэтому диспетчер PnP создает devnode для джойстика. На этом этапе единственным драйвером, настроенным для джойстика, является родительский драйвер шины USB-концентратора, который создал PDO джойстика. Любые необязательные драйверы фильтров шины также будут присутствовать в стеке устройств, но в примере драйверы фильтров шины пропускаются для простоты.

    Широкая стрелка между двумя devnodes на предыдущем рисунке указывает, что джойстик devnode является дочерним элементом devnode usb hub.

  2. Диспетчер PnP собирает сведения о новом устройстве и начинает настройку устройства.

    Диспетчер PnP отправляет последовательность irP в стек устройств для сбора сведений об устройстве. На этом этапе стек устройств состоит только из PDO, созданного родительским драйвером шины устройства, и объектов DOS фильтра для любых дополнительных драйверов фильтров шины. Таким образом, водитель автобуса и водители фильтров автобуса являются единственными водителями, которые реагируют на эти IRP. В этом примере единственным драйвером в стеке джойстиков является драйвер родительской шины, драйвер концентратора USB.

    Диспетчер PnP собирает сведения о новом устройстве, отправляя irp в стек устройств. К этим irP относятся следующие:

    Диспетчер PnP отправляет перечисленные выше irP на этом этапе обработки нового устройства PnP, но не обязательно в указанном порядке, поэтому не следует делать предположений о порядке отправки irP. Кроме того, не следует предполагать, что диспетчер PnP отправляет только указанные выше irP.

    Диспетчер PnP проверяет реестр, чтобы определить, было ли устройство установлено на этом компьютере ранее. Диспетчер PnP проверяет наличие подраздела <перечислителя>\<deviceID> для устройства в ветви Enum . В этом примере устройство является новым и должно быть настроено "с нуля".

  3. Диспетчер PnP сохраняет сведения об устройстве в реестре.

    Ветвь Перечисления реестра зарезервирована для использования компонентами операционной системы, и ее макет может измениться. Средства записи драйверов должны использовать системные подпрограммы для извлечения сведений, связанных с драйверами. Не получайте доступ к ветви Enum напрямую из драйвера. Приведенные ниже сведения о перечислении отображаются только в целях отладки.

    • Диспетчер PnP создает подраздел для устройства под ключом перечислителя устройства.

      Диспетчер PnP создает подраздел с именем HKLM\System\CurrentControlSet\Enum\<enumerator>\<deviceID>. Он создает < подраздел перечислителя>, если он еще не существует.

      Перечислитель — это компонент, который обнаруживает устройства PnP на основе аппаратного стандарта PnP. Задачи перечислителя выполняются водителем автобуса PnP в партнерстве с менеджером PnP. Устройство обычно перечисляется его родительским драйвером шины, например PCI или PCMCIA. Некоторые устройства перечисляются драйвером фильтра шины, например ACPI.

    • Диспетчер PnP создает подраздел для этого экземпляра устройства.

      Если параметр Capabilities.UniqueID возвращается как TRUE для IRP_MN_QUERY_CAPABILITIES, уникальный идентификатор устройства уникален в системе. В противном случае диспетчер PnP изменяет идентификатор таким образом, чтобы он был уникальным для всей системы.

      Диспетчер PnP создает подраздел с именем HKLM\System\CurrentControlSet\Enum\<enumerator>\<deviceID>\<instanceID>.

    • Диспетчер PnP записывает сведения об устройстве в подраздел экземпляра устройства.

      Диспетчер PnP хранит следующие сведения, если они были предоставлены для устройства:

      DeviceDesc — из IRP_MN_QUERY_DEVICE_TEXT

      Расположение — из IRP_MN_QUERY_DEVICE_TEXT

      Возможности — флаги из IRP_MN_QUERY_CAPABILITIES

      UINumber — из IRP_MN_QUERY_CAPABILITIES

      HardwareID — из IRP_MN_QUERY_ID

      Совместимые идентификаторы — из IRP_MN_QUERY_ID

      ContainerID — из IRP_MN_QUERY_ID

      LogConf\BootConfig — из IRP_MN_QUERY_RESOURCES

      LogConf\BasicConfigVector — из IRP_MN_QUERY_RESOURCE_REQUIREMENTS

На этом этапе диспетчер PnP готов найти драйвер функции и фильтровать драйверы для устройства, если таковые есть. (См. следующий рисунок.)

схема, иллюстрирующая поиск драйверов функций и фильтров.

Следующие примечания соответствуют нумерованным кругам на предыдущем рисунке:

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

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

  2. Компоненты настройки пользовательского режима направляют диспетчер PnP в режиме ядра для загрузки драйверов функций и фильтров.

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

На следующем рисунке показано, как диспетчер PnP загружает драйверы (при необходимости), вызывает их процедуры AddDevice и направляет драйверы на запуск устройства.

схема, иллюстрирующая вызов процедур adddevice и запуск нового устройства.

Следующие примечания соответствуют нумерованным кругам на предыдущем рисунке:

  1. Драйверы нижнего фильтра

    Перед подключением драйвера функции к стеку устройств диспетчер PnP обрабатывает все драйверы с более низким фильтром. Для каждого драйвера нижнего фильтра диспетчер PnP вызывает подпрограмму DriverEntry драйвера, если драйвер еще не загружен. Затем диспетчер PnP вызывает подпрограмму AddDevice драйвера. В подпрограмме AddDevice драйвер фильтра создает объект устройства фильтра (фильтр DO) и присоединяет его к стеку устройств (IoAttachDeviceToDeviceStack). После присоединения объекта устройства к стеку устройств драйвер будет задействован в качестве драйвера для устройства.

    В примере джойстика USB существует один драйвер нижнего фильтра для устройства.

  2. Драйвер функции

    После подключения более низких фильтров диспетчер PnP обрабатывает драйвер функции. Диспетчер PnP вызывает подпрограмму DriverEntry драйвера функции, если драйвер еще не загружен, и вызывает подпрограмму AddDevice драйвера функции. Драйвер функции создает объект устройства-функции (FDO) и присоединяет его к стеку устройств.

    В этом примере драйвер-функция для джойстика USB фактически представляет собой пару драйверов: драйвер класса HID и драйвер мини-класса HID. Эти два драйвера работают вместе, чтобы служить в качестве драйвера функции. Пара драйверов создает только одно FDO и присоединяет его к стеку устройств.

  3. Драйверы верхнего фильтра

    После подключения драйвера функции диспетчер PnP обрабатывает все драйверы верхнего фильтра.

    В этом примере имеется один драйвер верхнего фильтра для устройства.

  4. Назначение ресурсов и запуск устройства

    При необходимости диспетчер PnP назначает ресурсы устройству и выдает IRP для запуска устройства.

    • Назначение ресурсов

      Ранее в процессе настройки диспетчер PnP собрал требования к аппаратным ресурсам для устройства из родительского драйвера шины устройства. После загрузки полного набора драйверов для устройства диспетчер PnP отправляет запрос IRP_MN_FILTER_RESOURCE_REQUIREMENTS в стек устройств. Все драйверы в стеке могут обработать этот IRP и при необходимости изменить список требований к ресурсам устройства.

      Диспетчер PnP назначает ресурсы устройству, если они требуются устройству, в зависимости от требований устройства и доступных в настоящее время ресурсов.

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

      В примере usb-джойстика USB-устройствам не требуются аппаратные ресурсы, поэтому диспетчер PnP задает для списка ресурсов значение NULL.

    • Запуск устройства (IRP_MN_START_DEVICE)

      После того как диспетчер PnP назначает ресурсы устройству, он отправляет IRP_MN_START_DEVICE IRP в стек устройств, чтобы направить драйверы на запуск устройства.

    После запуска устройства диспетчер PnP отправляет еще три IRP в драйверы для устройства:

    • IRP_MN_QUERY_CAPABILITIES

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

    • IRP_MN_QUERY_PNP_DEVICE_STATE

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

    • IRP_MN_QUERY_DEVICE_RELATIONS для связей между автобусами

      Диспетчер PnP отправляет этот IRP, чтобы определить, есть ли у устройства дочерние устройства. В этом случае диспетчер PnP настраивает каждое дочернее устройство.

Использование GUID_PNP_LOCATION_INTERFACE

Интерфейс GUID_PNP_LOCATION_INTERFACE предоставляет свойство устройства SPDRP_LOCATION_PATHS Plug and Play (PnP).

Чтобы реализовать этот интерфейс в драйвере, обработайте IRP_MN_QUERY_INTERFACE IRP с InterfaceType = GUID_PNP_LOCATION_INTERFACE. Драйвер предоставляет указатель на структуру PNP_LOCATION_INTERFACE, которая содержит указатели на отдельные подпрограммы интерфейса. Подпрограмма PnpGetLocationString предоставляет зависят от устройства часть свойства SPDRP_LOCATION_PATHS устройства.