OnNow Initiative

< BACK  NEXT >
[oR]

In an attempt to standardize (read: abstract) the various approaches to power management, Microsoft developed the OnNow Initiative. This specification builds on the capabilities of the hardware, providing a common platform for the various Microsoft operating systems to exploit.

The OnNow initiative abstracts the power management capabilities of the system (mainboard) and devices. While individual devices may incorporate many clever powering schemes, the OnNow model describes distinct power states that a device or system can occupy at any given time.

Power States

A system exists in one of six power states, designated S0 through S5. The meanings are described in Table 10.1. The overall state of the system largely restricts the maximum power state of individual devices.

Devices, meanwhile, occupy one of four power states, D0 through D3. The meanings are described in Table 10.2. Device power state primarily determines whether or not the hardware is capable of retaining its internal context at the designated Dx level.

Table 10.1. System Power States Defined by OnNow
System Power State Meaning
S0 CPU fully on Devices may occupy any power state
S1 CPU halted; RAM refreshed
S2 CPU without power; RAM refreshed
S3 CPU without power; RAM in slow refresh mode Power supply output reduced
S4 System off; RAM saved to disk
S5 System off and shutdown; full reboot necessary to restore operation

Table 10.2. Device Power States Defined by OnNow
Device Power State Meaning
D0 Device fully on
D1 Device in low-power mode
Device context probably retained
D2 Device in low-power mode
Device context probably not valid
D3 Device is without power; context lost

A confusing terminology point arises from the power state designations. As the system or device moves to a lower power state, its power state designation increases. For example, a device that moves from fully on to fully off has its power state increase from D0 to D3. The problem is compounded by the fact that the header file defining the enumeration of the states (wdm.h) specifies increasing enumeration values for the decreasing power-consuming states. For example, D0, enumerated symbolically as PowerDeviceD0, has the ordinal value 1. PowerDeviceD3 has the ordinal value 4. Thus, ordinal comparisons of power states are confusing. For example, a test of newState < oldState is a check to see if the new state consumes more power than the old state.

To further confuse the issue, PowerDeviceMaxium is defined to be the maximum power consumption state of a device. As currently defined within <wdm.h>, its ordinal value is 5.

Power Policies

Devices of the same class share a common power policy. The policy is owned by a single driver, typically a high-level driver common to all device stacks of the class (e.g., a class driver). The policy owner makes power decisions for the entire class of devices and is responsible for communicating with the operating system to confirm or reject power state changes.

Once the policy owner decides on a power state change, it issues IRP requests to individual devices or stacks to enact the decision. Such an IRP might pass between many drivers (down to the bus driver, up to the PDO, back to filters and FDO) before the entire request is realized.

Regardless of which driver assumes the role of policy owner, each device stack driver is responsible for acting on individual power requests. This means that each FDO is responsible for the device-specific power manipulation, while the PDO bus drivers take responsibility for manipulating power to the bus slot.

Power State Matrix

The system power states (S0-S5) dictate a maximum power state for devices (D0-D3). Since this maximum power state varies from system to system and device to device, a dynamic configuration occurs each time a driver is loaded. The results of this configuration are maintained within a device structure, DEVICE_CAPABILITIES, primarily within an array substructure, DEVICE_POWER_STATE (offset: DeviceState). Each element of the array corresponds to a system power state, Sx, and contains the maximum device power state, Dx, that is allowed.

On a given system, the collection of all DeviceState arrays forms a power state matrix that governs device power state transitions as the system power state changes.

The DeviceState array is filled using the following algorithm:

  1. After a WDM AddDevice function is called, the PnP Manager issues a request, IRP_MN_QUERY_CAPABILITIES, to each created device stack.

  2. The FDO (and any intervening filters) forward the request to the bus driver (PDO).

  3. Using whatever means the bus allows, the bus driver fills in the DeviceState array. It also fills in "wake" fields that specify the minimum system and device states at which a device can still issue a wake event. (DeviceWake and SystemWake)

  4. The IRP is returned to the higher levels. The FDO is permitted to degrade the bus determinations (e.g., stating that at S1, the device cannot support D1) and then complete the IRP.

The primary consumer of the power state matrix is a policy owner, which issues a PnP request, IRP_MN_SET_POWER, to a device stack to alter a device's power state. A policy owner should not violate the constraints of the power matrix and, therefore, must issue its own PnP request, IRP_MN_QUERY_CAPABILITIES, to obtain the relevant array entries.

Power State Changes

When a system power state change is requested, all power policy owners are notified with an IRP_MN_SET_POWER PnP request. The policy owner invokes the PnP Manager call PoRequestPowerIrp, described in Table 10.3, to construct a new PnP IRP request. The new IRP is sent to the device stack specified by the target FDO (or PDO).

An FDO, upon receiving the request to change power states, alters its power state using whatever device-specific means are available to it. It then issues the PnP Manager call PoSetPowerState to acknowledge accomplishment of the state change request. PoSetPowerState is described in Table 10.4.

Table 10.3. Function Prototype for PoRequestPowerIrp
NTSTATUS PoRequestPowerIrp IRQL <=DISPATCH_LEVEL
Parameter Description
IN PDEVICE_OBJECT pDeviceObject Pointer to target FDO or PDO
IN UCHAR MinorFunction IRP_MN_QUERY_POWER
IRP_MN_SET_POWER
IRP_MN_WAIT_WAKE
IN POWER_STATE PowerState New device or system power state request
IN PREQUEST_POWER_COMPLETE Function called when new IRP has completed CompletionRoutine
IN PVOID pContext Argument passed to Completion routine
OUT PIRP *pIrp Optional pointer to newly allocated IRP
Return value STATUS_PENDING
STATUS_INSUFFICIENT_RESOURCES
STATUS_INVALID_PARAMETER_2

The power state change request must also be forwarded to lower-level devices in the stack, especially to the bus driver. If the device power state is being increased (i.e., moving to a lower consumption state), the device should act first on the request, then forward the request to the bus driver. If the device power state is being lowered (i.e., moving toward the "fully on" condition), the device should forward the request first to the bus driver, await completion, and then act on the request. The order of acting vs. forwarding varies because the bus needs to power up a slot before the device can act. Conversely, the device must enter a quiescent state before the slot is powered down.

Table 10.4. Function Prototype for PoSetPowerState
POWER_STATE PoSet PowerState IRQL <= DISPATCH_LEVEL
Parameter Description
IN PDEVICE_OBJECT pDeviceObject Pointer to target FDO or PDO
IN POWER_STATE_TYPE Type Must be DevicePowerState for FDOs
IN POWER_STATE PowerState New device power state being entered PowerDeviceDn (n = 0 to 3)
Return value Previous power state (Windows 2000 only)

Table 10.5. Function Prototype for PoStartNextPowerIrp
VOID PoStartNextPowerIrp IRQL <= DISPATCH_LEVEL
Parameter Description
IN PRIP pIrp Pointer to current IRP
Return value - void -

Forwarding a PnP Power Request IRP to lower-layer drivers is different from forwarding other PnP IRPs. Two special functions, PoStartNextPowerIrp and PoCallDriver, are provided for this purpose. PoStartNextPowerIrp, described in Table 10.5, alerts the requestor that the current device stack level has completed work on the power IRP and is ready for another. This function must be called from every device driver within the device stack. PoCallDriver, described in Table 10.6, then forwards the current IRP to the lower-level driver.

The action of forwarding Power IRPs when increasing or decreasing power states is shown in Figure 10.1. An example of handling PnP Power IRP requests is shown below (along with the requisite Completion routine when awaiting lower levels to complete first).

Figure 10.1. Forwarding Power IRP requests.
graphics/10fig01.gif

Table 10.6. Function Prototype for PoCallDriver
NTSTATUS PoCallDriver IRQL <= PASSIVE_LEVEL (in some cases, DISPATCH_LEVEL is OK)
Parameter Description
IN PDEVICE_OBJECT pDevObj Pointer to next lower-level device object (i.e., next recipient)
IN OUT PRIP pIrp Pointer to current IRP
Return value STATUS_SUCCESS
STATUS_PENDING

 NTSTATUS OnPowerIrp(PDEVICE_OBJECT pDevObj, PIRP pIrp) {      NTSTATUS status;      PIO_STACK_LOCATION stack =           IoGetCurrentIrpStackLocation( pIrp );      PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)             pDevObj -> DeviceExtension;      ULONG subCode = stack->MinorFunction;      switch (subCode) {      ...      case IRP_MN_SET_POWER:           POWER_STATE_TYPE type =                stack->Parameters.Power.Type;           if (type != DevicePowerState)                // System power state change notification                // Driver can prepare for eventual device                // power change - sent later                ForwardPowerIrp(pDevObj, pIrp);           DEVICE_POWER_STATE newState =                stack->Parameters.Power.State;           if (newState < pDevExt->currentPowerState) {                // Request to raise power - tell PDO first.                // Set a completion routine so that we can                // regain control after lower-level finishes                IoCopyCurrentIrpStackLocationToNext( pIrp );                IoSetCompletionRoutine( pIrp, PowerUpFinish,                     NULL, TRUE, TRUE, TRUE);                PoCallDriver( pDevExt->LowerDriver, pIrp );                     Return STATUS_PENDING;                } else {                     // request to reduce power - do it first.          // Perform device-specific power-up ops.          // Tell Power Mgr device has changed state          PoSetPowerState( pDevObj, type, newState);          // Tell Power Mgr OK to send this level          // another Power IRP          PoStartNextPowerIrp( pIrp );          // And pass the Power IRP down...          return          PoCallDriver( pDevExt->LowerDriver, pIrp );          }          break;          ... NTSTATUS PowerUpFinish( PDEVICE_OBJECT pDevObj,                          PIRP pIrp, PVOID pContext) {      PIO_STACK_LOCATION stack =           IoGetCurrentIrpStackLocation( pIrp );      PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)           pDevObj  -> DeviceExtension;      DEVICE_POWER_STATE newState =           stack->Parameters.Power.State;      // Perform device-specific power-up now that the bus      // has supplied the device with power      // Inform the Power Mgr of the state change      PoSetPowerState( pDevObj, DevicePowerState, newState);      // And signal an OK for more Power IRPs      PoStartNextPowerIrp( pIrp );      return STATUS_SUCCESS; } 
< BACK  NEXT >


The Windows 2000 Device Driver Book(c) A Guide for Programmers
The Windows 2000 Device Driver Book: A Guide for Programmers (2nd Edition)
ISBN: 0130204315
EAN: 2147483647
Year: 2000
Pages: 156

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net