Процедуры обратного вызова ожидания и пробуждения

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

Так как эта подпрограмма обратного вызова устанавливается от имени драйвера, инициировавшего IRP, и не для драйвера, обрабатывающего IRP, она не должна вызывать PoStartNextPowerIrp; Только подпрограммы IoCompletion, установленные, когда драйверы передают IRP вниз по стеку, должны начинать следующую Power IRP. Имейте в виду, что владелец политики управления не только отправляет IRP, но и обрабатывает его, и поэтому может задать подпрограмму IoCompletion, когда передает IRP вниз по стеку, а также настроить подпрограмму обратного вызова при запросе IRP режима ожидания/пробуждения.

Подпрограмма обратного вызова имеет следующие обязанности:

  1. Если драйвер управляет несколькими устройствами, определите, какие из его устройств сигнализирует о пробуждении.

  2. Обработайте событие, вызвавшее сигнал пробуждения.

  3. Задайте устройство, которое сигнализирует о пробуждении в состоянии D0, вызвав PoRequestPowerIrp для отправки запроса PowerDeviceD0 . Драйвер также должен вызвать PoSetPowerState , чтобы сообщить диспетчеру питания о новом состоянии питания устройства. Дополнительные сведения см. в статье "Отправка IRP_MN_QUERY_POWER или IRP_MN_SET_POWER для состояний питания устройств".

  4. Если драйвер устанавливает подпрограмму Отмены для IRP, вызовите IoSetCancelRoutine, чтобы сбросить подпрограмму Отмены до NULL.

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

    Например, устройство PCI может включить ожидание / пробуждение для модема и сетевой карты. Если сетевой адаптер пробудит систему (таким образом, завершив IRP), PCI FDO должен отправить ещё один IRP ожидания/пробуждения самому себе, чтобы модем по-прежнему мог проснуться.

Так как драйвер, запрашивающий iRP ожидания и пробуждения, управляет политикой питания для стека устройств, он отвечает за возвращение устройства в рабочее состояние после завершения IRP. Хотя нижестоящие драйверы уже могли физически подключить питание к устройству, владелец политики должен вызвать PoRequestPowerIrp, чтобы отправить запрос IRP_MN_SET_POWER на установку состояния питания устройства D0. Только после того, как все драйверы в стеке устройств обработают этот IRP включения питания, устройство будет возвращено в рабочее состояние.