IRP_MJ_POWER设备电源管理
以下代码摘自TOASTER电源管理IRP_MJ_POWER的注释
The system dispatches different IRP_MJ_POWER IRPs to ToasterDispatchPower for different purposes:
- To query a driver to determine if the system can change its overall power state to a different power level.
- To notify a driver of a change in the overall system power state so that the driver can adjust the device power state of its hardware instance to an appropriate level.
- To respond to system wake-up events.
Most function and filter drivers perform some processing for each power IRP and then pass the IRP down the device stack without completing it. Eventually the power IRP reaches the bus driver, which physically changes the power to the hardware instance and completes the power IRP.
fdo和fido保留相关的信息之后,直接下传给PDO即可。
总线的PDO收到该IRP之后,更改设备的供电并完成IRP.
In general, a driver should not cause noticeable delays while processing power IRPs. If a driver cannot process a power in a short amount of time, it should mark the power IRP as pending, begin to queue any new non-power IRPs (until the driver completes the pending power IRP), and return STATUS_PENDING to the caller.
电源如无法完成时,应挂起IRP,并置IRP状态为STATUS_PENDING,并调用PoStartNextPowerIrp。
Processing power IRPs is a complex procedure which can involve I/O completion routines, power completion routines, and system worker thread work items. The following sequence demonstrates how a power policy owner (the function driver in this case) processes different power IRPs:
The power manager sends a IRP_MN_QUERY_POWER S-IRP (query power system-IRP) with a specific system power state to query the power policy owner if it can change its hardware instance to an appropriate device power state without disrupting work.
1a) -The function driver receives an IRP_MN_QUERY_POWER (query power system-IRP)
S-IRP.
-The function driver sets the system to call an I/O completion routine
because the function driver must process the IRP_MN_QUERY_POWER S-IRP on its
passage back up the device stack, after the underlying bus driver completes
it.
-The function driver passes the IRP_MN_QUERY_POWER S-IRP down the device
stack.
-The function driver returns STATUS_PENDING to the caller.
After the bus driver completes the IRP_MN_QUERY_POWER S-IRP, the system passes
the IRP back up the device stack and calls the I/O completion routine set
earlier:
1b) -The I/O completion routine requests that the power manager send a
IRP_MN_QUERY_POWER D-IRP (query power device-IRP) that corresponds to the
original pending IRP_MN_QUERY_POWER S-IRP. When the I/O completion routine
requests the corresponding D-IRP it also sets the system to call a power
completion routine after the function driver completes the corresponding
D-IRP.
-The I/O completion routine returns STATUS_MORE_PROCESSING_REQUIRED to the
caller.
1c) -The function driver receives the corresponding IRP_MN_QUERY_POWER D-IRP and
either completes it successfully to indicate that the hardware instance can
change to an appropriate device power state without data loss, or fails the
D-IRP to indicate that the hardware instance cannot change its device power
state without disrupting work.
The system then calls the power completion routine set to be called earlier
when the I/O completion requested the corresponding D-IRP:
1d) -The power completion routine copies the status of the corresponding completed
IRP_MN_QUERY_POWER D-IRP into the original pending IRP_MN_QUERY_POWER S-IRP.
-The power completion routine then completes the original pending
IRP_MN_QUERY_POWER S-IRP.
-The power completion routine returns to the caller.
If the function driver fails the original IRP_MN_QUERY_POWER S-IRP, then the
power manager might send another IRP_MN_QUERY_POWER S-IRP to specify a
different system power state, and the previous sequence repeats.
However, if the function driver succeeds the original IRP_MN_QUERY_POWER
S-IRP, then the power manager sends a IRP_MN_SET_POWER S-IRP (set power
system IRP) with the same system power state as the original
IRP_MN_QUERY_POWER S-IRP to notify the function driver to change its hardware
instance to the device power state appropriate for the system power state.
Alternately, even if the function driver fails the original IRP_MN_QUERY_POWER
S-IRP, the power manager can still send a IRP_MN_SET_POWER S-IRP to notify the
function driver that the system is preparing to change its power state. The
power manager might force a driver to change its hardware instance to a
specific device power state because a battery or UPS is going offline
----------------------------------------------------------------------------------
2a) -The function driver receives an IRP_MN_SET_POWER (set power system-IRP)
S-IRP.
-The function driver sets the system to call an I/O completion routine
because the function driver must process the IRP_MN_SET_POWER S-IRP on its
passage back up the device stack, after the underlying bus driver completes
it.
-The function driver passes the IRP_MN_SET_POWER S-IRP down the device
stack.
-The function driver returns STATUS_PENDING to the caller.
After the bus driver completes the IRP_MN_SET_POWER S-IRP, the system calls
the I/O completion routine set earlier:
2b) -The I/O completion routine requests that the power manager send a
IRP_MN_SET_POWER D-IRP (set power device-IRP) that corresponds to the
original pending IRP_MN_SET_POWER S-IRP. When the I/O completion routine
requests the corresponding D-IRP it also sets the system to call a power
completion routine after the function driver completes the corresponding
D-IRP.
-The I/O completion routine returns STATUS_MORE_PROCESSING_REQUIRED to the
caller.
----------------------------------------------------------------------------------
3) -The function driver receives the corresponding IRP_MN_SET_POWER D-IRP and
must determine if it is a power-down D-IRP or a power-up D-IRP.
4) If the original pending IRP_MN_SET_POWER S-IRP specifies a higher system power
state than the current system power state then the corresponding
IRP_MN_SET_POWER D-IRP is a power-up D-IRP. The underlying bus driver must
process power-up D-IRPs before the function driver because the bus driver must
supply power to the hardware instance before the function driver can use it.
However, the function driver cannot process the power-up D-IRP until every
pending IRP (if any) such as read, write, or device control operations
complete (in other threads of execution). Note that, however, the function
driver cannot wait in the thread processing the power-up D-IRP because that
might cause the system to stop responding.
Therefore, the function driver marks the power-up D-IRP as pending and sets
the system to call an I/O completion routine after the bus driver completes
the power-up D-IRP. Then, the function driver passes the power-up D-IRP down
the device stack. Next, the function driver returns STATUS_PENDING to the
caller. At this time, both the original IRP_MN_SET_POWER S-IRP and the
corresponding power-up D-IRP are pending.
After the bus driver completes the power-up D-IRP, the system calls the I/O
completion routine set earlier. Recall, that the function driver must still
wait until every pending IRP completes. However, because the function driver
cannot wait in the I/O completion routine for every IRP to complete, the I/O
completion routine queues a callback for the system worker thread to process
at IRQL = PASSIVE_LEVEL. Then the I/O completion routine returns
STATUS_MORE_PROCESSING_REQUIRED to the caller.
Finally, the system worker thread calls the callback routine at
IRQL = PASSIVE_LEVEL to finish processing the power-up D-IRP. The callback
routine can then wait until every pending IRP completes by suspending the
execution of the system worker thread (which will not cause a system deadlock
because the system worker thread calls the callback routine at
IRQL = PASSIVE_LEVEL), and then the callback routine finishes processing the
power-up D-IRP before it returns to the caller.
----------------------------------------------------------------------------------
5) Otherwise, if the original pending IRP_MN_SET_POWER S-IRP specifies the same
system power state as the current system power state, or a lower system power
state than the current system power state then the corresponding
IRP_MN_SET_POWER D-IRP is a power-down D-IRP. The function driver must process
power-down D-IRPs before passing them down the device stack to be processed by
the underlying bus driver because the function driver must save the hardware
instance's operating context before the hardware instance is powered-down (or
powered-off). The context can then be restored later when the hardware
instance is powered-up.
Therefore, the function driver queues a callback for the system worker thread
to process at IRQL = PASSIVE_LEVEL. Then the function routine returns
STATUS_PENDING to the caller.
Finally, the system worker thread calls the callback routine at
IRQL = PASSIVE_LEVEL to finish processing the power-down D-IRP. The callback
routine can then wait until every pending IRP completes by suspending the
execution of the system worker thread (which will not cause a system deadlock
because the system worker thread calls the callback routine at
IRQL = PASSIVE_LEVEL), and then the callback routine finishes processing the
power-down D-IRP before it returns to the caller.
Updated Return Value Description:
ToasterDispatchPower returns STATUS_NO_SUCH_DEVICE if the hardware instance
represented by DeviceObject has been removed. If the function driver
immediately processes the power IRP, then ToasterDispatchPower returns
STATUS_SUCCESS. If the function driver marked the power IRP as pending, then
ToasterDispatchPower returns STATUS_PENDING.