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


Обработка irP Power-Down устройств

IRP выключения устройства указывает дополнительный код функции IRP_MN_SET_POWER и состояние питания устройства (PowerDeviceD0, PowerDeviceD1, PowerDeviceD2 или PowerDeviceD3), которое меньше питания или равно текущему состоянию питания устройства. Водители должны обрабатывать IRP с выключением питания, так как IRP перемещается вниз по стеку устройств. Драйверы более высокого уровня должны обрабатывать IRP перед драйверами более низкого уровня. Драйверы, у которых нет задач для конкретных устройств, должны оперативно передавать IRP следующему драйверу ниже.

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

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

Если IRP указывает PowerDeviceD3, драйвер функции обычно должен выполнять следующие задачи:

  • Вызовите IoAcquireRemoveLock, передав текущую IRP, чтобы убедиться, что драйвер не получит запрос IRP_MN_REMOVE_DEVICE PnP при обработке IRP питания.

    Если IoAcquireRemoveLock возвращает состояние сбоя, драйвер не должен продолжать обработку IRP. Вместо этого, начиная с Windows Vista, драйвер должен вызвать IoCompleteRequest , чтобы завершить IRP, а затем вернуть состояние сбоя. В Windows Server 2003, Windows XP и Windows 2000 драйвер должен вызвать IoCompleteRequest для завершения IRP, а затем вызвать PoStartNextPowerIrp для запуска следующего IRP питания, а затем вернуть состояние сбоя.

  • Выполните все задачи, относящиеся к конкретному устройству, которые необходимо выполнить перед отключением питания устройства, такие как закрытие устройства, завершение или очистка ожидающих операций ввода-вывода, отключение прерываний, постановка в очередь последующих входящих irP и сохранение контекста устройства для восстановления или повторной инициализации устройства.

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

    Драйвер должен ставить в очередь все входящие запросы ввода-вывода, пока устройство не вернется в рабочее состояние.

  • Возможно, проверка значение в Parameters.Power.ShutdownType. Если активна функция IRP для установки питания системы, параметр ShutdownType предоставляет сведения о системном IRP. Дополнительные сведения об этом значении см. в разделе System Power Actions.

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

  • Измените физическое состояние питания устройства, если драйвер может сделать это и если изменение является целесообразным.

  • Вызовите PoSetPowerState , чтобы уведомить диспетчер питания о новом состоянии питания устройства.

  • Вызовите IoCopyCurrentIrpStackLocationToNext , чтобы настроить расположение стека для следующего ниже драйвера.

  • Задайте подпрограмму IoCompletion , которая вызывает PoStartNextPowerIrp , которая указывает, что драйвер готов к обработке следующего IRP питания. Этот шаг не требуется в Windows 7 и Windows Vista.

  • Вызовите IoCallDriver (в Windows 7 и Windows Vista) или вызовите PoCallDriver (в Windows Server 2003, Windows XP и Windows 2000), чтобы передать IRP следующему драйверу ниже. IRP должен быть передан до водителя автобуса, который завершает IRP.

  • Вызовите IoReleaseRemoveLock , чтобы освободить ранее полученную блокировку.

  • Возврат STATUS_PENDING.

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

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

Однако если драйвер шины обслуживает устройство гибернации, он должен проверка, имеет ли значение ShutdownType в IRP значение PowerSystemHibernate. В этом случае водитель шины должен вызвать PoSetPowerState , чтобы сообщить о PowerDeviceD3, но не должен выключать устройство. Устройство выключится после сохранения файла гибернации вместе с остальной частью системы.

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

Если IRP указывает любое другое состояние (D0, D1 или D2), необходимые действия драйвера зависят от устройства. Как правило, устройства, поддерживающие эти состояния, могут быстро вернуться в рабочее состояние при поступлении запроса ввода-вывода. Драйвер для такого устройства должен выполнять все ожидающие запросы ввода-вывода, ставить в очередь все новые запросы и сохранять весь необходимый контекст перед перенаправлением IRP следующему драйверу ниже. Когда IRP достигает драйвера шины, он устанавливает оборудование в запрошенном состоянии. Драйвер не может получить доступ к устройству во время его сна.

В некоторых случаях драйвер функции или фильтра может получить IRP питания устройства с указанием PowerDeviceD0, когда устройство уже находится в состоянии D0. Драйвер должен обрабатывать этот IRP так же, как и любой другой IRP с установленной мощностью: выполнять ожидающие запросы ввода-вывода, ставить в очередь входящие запросы ввода-вывода, устанавливать подпрограмму IoCompletion и передавать IRP в следующий драйвер ниже. Однако драйвер не должен изменять параметры оборудования устройства. Когда водитель автобуса получает IRP, он должен просто завершить IRP. После завершения IRP драйверы функций и фильтров могут обрабатывать любые запросы в очереди. Постановка в очередь операций ввода-вывода до завершения IRP исключает любую возможность того, что более низкие драйверы пытаются изменить регистры устройств, в то время как более высокий драйвер пытается выполнить ввод-вывод.