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

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

Так как эта подпрограмма обратного вызова задается от имени драйвера, который создал IRP, а не для драйвера, обрабатывающего IRP, она не должна вызывать PoStartNextPowerIrp; Только подпрограммы IoCompletion, заданные в качестве драйверов, передают IRP вниз по стеку, должны запускать следующий 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 может быть включено ожидание и пробуждение для модема и сетевой карты (NIC). Если сетевой адаптер разбудит систему (таким образом, завершает IRP), PCI FDO должен отправить себе другой IRP ожидания или пробуждения, чтобы модем по-прежнему мог проснуться.

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