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


Общие сведения о пути irP для ожидания и пробуждения через дерево устройств

В одном стеке устройств владелец политики управления питанием отправляет IRP ожидания и пробуждения, и все драйверы обрабатывают IRP ожидания и пробуждения, как описано в разделе Обзор операции ожидания и пробуждения и подробно описано в разделе Отправка iRP ожидания/пробуждения и Получение IRP ожидания/пробуждения соответственно.

В ветви дерева устройств (которая состоит из конечного devnode и devnodes его родителей, бабушек и дедушек и т. д.) водители должны сотрудничать, чтобы убедиться, что IRP ожидания или пробуждения достигает драйвера, который может включить все необходимое оборудование для пробуждения.

На компьютерах ACPI ACPI отвечает за включение регистра событий общего назначения для конкретной системы (GPE), связанного с сигналом пробуждения от каждого конечного устройства. Следовательно, драйверы должны запрашивать и переадресовывать irps ожидания и пробуждения, пока не достигнет либо драйвера фильтра ACPI (вставленного в стек устройств при запуске), либо базового драйвера Windows ACPI, Acpi.sys. В ответ ACPI включает регистр, удерживает IRP в ожидании, пока не поступит сигнал, а затем завершает IRP. Так как ACPI может реагировать на сигнал пробуждения, он не перенаправит IRP в более низкий драйвер.

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

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

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

схема, иллюстрирующая пример конфигурации USB.

В примере конфигурации клавиатура и модем являются дочерними элементами USB-концентратора, который, в свою очередь, является дочерним элементом контроллера УЗЛА USB, который перечисляется шиной PCI. На следующем рисунке показаны стеки устройств для клавиатуры в примере конфигурации.

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

Как показано на предыдущем рисунке, чтение снизу вверх:

  1. Драйвер Windows ACPI Acpi.sys создает PDO для PCI.

  2. Драйвер PCI создает FDO PCI и PDO контроллера узла USB и владеет политикой для стека устройств PCI.

  3. Драйвер USB-контроллера узла (пара портов узла и драйвера мини-порта) создает FDO контроллера УЗЛА USB и PDO концентратора USB. Ему принадлежит политика для стека устройств контроллера узла USB. Обратите внимание, что Acpi.sys также создает фильтр DO в этом стеке.

  4. Драйвер USB-концентратора создает FDO концентратора USB и PDO клавиатуры. Этот драйвер владеет политикой питания для стека устройств USB-концентратора.

  5. Драйвер-функция для клавиатуры — это пара usb HID класса driver/minidriver. Этот драйвер создает FDO для клавиатуры и владеет политикой управления питанием. Так как на клавиатуре нет дочерних устройств, этот драйвер не создает PDO.

Обратите внимание, что каждый стек устройств может включать дополнительные необязательные DOS фильтра, которые не отображаются.

Чтобы разрешить ввод с клавиатуры для пробуждения системы, владелец политики для клавиатуры запрашивает IRP_MN_WAIT_WAKE для ее PDO. Этот IRP создает цепочку других irp ожидания и пробуждения, как показано на следующем рисунке.

запросы irp wait/wake для примера конфигурации USB.

Когда водитель автобуса получает IRP_MN_WAIT_WAKE , предназначенный для созданного PDO, он должен запросить другой IRP_MN_WAIT_WAKE для стека устройств, для которого ему принадлежит политика управления питанием, и создан FDO.

Как показано на предыдущем рисунке:

  1. Драйвер клавиатуры вызывает PoRequestPowerIrp для отправки IRP ожидания и пробуждения (IRP1) в свой PDO.

    Диспетчер питания выделяет IRP и отправляет его через диспетчер ввода-вывода в верхнюю часть стека устройств для клавиатуры. Драйверы устанавливают процедуры IoCompletion и передают IRP вниз по стеку, пока не достигнет PDO клавиатуры. Драйвер USB-концентратора, который выступает в качестве драйвера шины для клавиатуры, содержит IRP1 в ожидании.

  2. Так как драйвер USB-концентратора не может разбудить систему при поступлении сигнала пробуждения, драйвер концентратора USB должен вызвать PoRequestPowerIrp , чтобы запросить IRP(IRP2) ожидания и пробуждения (IRP2) для стека устройств концентратора USB.

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

  3. Аналогичным образом драйвер usb-контроллера узла не может разбудить систему, поэтому драйвер хост-контроллера USB вызывает PoRequestPowerIrp для отправки IRP-запроса ожидания и пробуждения (IRP3) в стек устройств usb-контроллера узла.

    Диспетчер питания отправляет этот IRP в верхнюю часть стека устройств контроллера узла USB, где драйверы устанавливают процедуры IoCompletion и передают IRP драйверу PCI (который выступает в качестве драйвера шины для USB-концентратора). Драйвер PCI удерживает IRP3 в ожидании, пока клавиатура не сигнализирует о событии пробуждения.

  4. Драйвер PCI не может разбудить систему, поэтому драйвер PCI вызывает PoRequestPowerIrp для отправки IRP ожидания и пробуждения (IRP4) в стек устройств PCI. Его родительским является корневое устройство, для которого ACPI является водителем автобуса.

    Диспетчер питания отправляет IRP в верхнюю часть стека устройств шины PCI; его драйверы задают процедуры завершения и передают IRP драйверу Windows ACPI Acpi.sys.

  5. Acpi.sys может разбудить систему, поэтому не отправляет IRP ожидания или пробуждения другим PDO. Acpi.sys удерживает IRP4 в ожидании, пока не поступит сигнал пробуждения.

Когда клавиатура утверждает сигнал пробуждения, Acpi.sys перехватывает его. AcPI, однако, не может определить, что клавиатура подтвердила сигнал, только то, что сигнал поступил через корневое устройство. Acpi.sys затем завершает IRP4, и диспетчер ввода-вывода вызывает подпрограммы IoCompletion для резервного копирования стека устройств PCI. После завершения IRP4 и выполнения всех подпрограмм IoCompletion вызывается процедура обратного вызова драйвера PCI. В своей процедуре обратного вызова драйвер PCI определяет, что сигнал поступил через usb-контроллер узла. Затем драйвер PCI завершает IRP3. Та же последовательность выполняется в стеке хост-контроллера USB и стеке концентратора USB, пока драйвер клавиатуры не получит IRP1. На этом этапе драйвер клавиатуры может обслуживать событие пробуждения при необходимости.

Каждый раз, когда драйвер отправляет IRP ожидания или пробуждения родительскому PDO, он должен задать подпрограмму Отмены для своего собственного IRP. Настройка процедуры отмены дает драйверу возможность отменить новый IRP, если функция IRP, которая ее активировала, отменена. В примере USB, если драйвер клавиатуры отменяет IRP ожидания и пробуждения (таким образом, отключает пробуждение клавиатуры), концентратор USB, USB-контроллер узла и драйверы PCI должны отменить irP, отправленные в результате ввода-вывода клавиатуры. Дополнительные сведения см. в разделе Отмена подпрограмм для irP ожидания и пробуждения.

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

Например, в конфигурации USB, показанной ранее на рисунке Пример конфигурации USB , USB-концентратор перечисляет два устройства: клавиатуру и модем. Когда драйвер USB-концентратора получает IRP ожидания/пробуждения для PDO клавиатуры, он увеличивает количество irP ожидания и пробуждения, прежде чем запрашивать IRP для собственного PDO. Если позже владелец политики модема включит пробуждение для модема, драйвер USB-концентратора подает новое IRP для PDO модема и увеличивает количество ссылок на ожидание и пробуждение. Тем не менее, поскольку PDO концентратора USB не может иметь два одновременно ожидающих выполнения irP ожидания или пробуждения, драйвер USB-концентратора не запрашивает новый IRP ожидания или пробуждения для PDO-концентратора USB.

Когда сигнал пробуждения поступает с клавиатуры или модема, драйвер USB-концентратора определяет, какое устройство сигнализирует, завершает соответствующее IRP и уменьшает его количество ссылок. Так как оба устройства были включены для пробуждения (и, следовательно, их число ссылок не равно нулю), оно должно отправить свой собственный стек устройств еще один IRP ожидания/пробуждения, чтобы "перенаправить" свой собственный PDO для пробуждения. (То же самое относится и к контроллеру УЗЛА USB и драйверу PCI.)

Однако драйвер не отправляет себе IRP для повторного включения ожидания/пробуждения на том же устройстве, на котором только что поступил сигнал пробуждения. Это может сделать только диспетчер политик питания устройств. Повторное ожидание и пробуждение не выполняется автоматически.