Книга: Writing Windows WDM Device Drivers

Device Power Policy Owner

Device Power Policy Owner

In most device stacks, there is one driver that knows if the device is being used and its power state. This driver is deemed the device power policy owner. There is nothing to stop more than one driver trying to set power policy. In most cases, the first function driver for a device is the power policy owner. However, the bus driver may well play an important part in power management, or even be the power policy owner.

The device power policy owner should call PoSetPowerState to set the current device power state. This device power state is stored for a device by the Power Manager. However, there is no call to retrieve the current device power state, so you must keep a copy of this value.

The Wdm2 driver defines the following two extra fields in its device extension to support Power Management.

DEVICE_POWER_STATE PowerState; // Our device power state
PULONG PowerIdleCounter; // Device idle counter

The AddDevice routine initializes these variables as follows. PoSetPowerState can only be used by drivers to set the device power state. Do not try to set the system power state.

dx->PowerState = PowerDeviceD3;
dx->PowerIdleCounter = NULL;
POWER_STATE NewState;
NewState.DeviceState = dx->PowerState;
PoSetPowerState(fdo, DevicePowerState, NewState);

An AddDevice routine can also set some extra bits in the FDO Flags. If DO_POWER_INRUSH is set, this device needs an inrush of power when it is powered up. Devices with this bit set are powered up one at a time. If the DO_POWER_PAGABLE flag bit is set, the Power handling routines are called at PASSIVE_LEVEL IRQL. Otherwise, they are called at DISPATCH_LEVEL IRQL. Inrush Power IRPs are sent at DISPATCH_LEVEL, so the power routines for these devices must not be pageable.

The device power policy owner must process Query and Set Power IRPs using the technique described previously. The following Wdm2 example shows how to do this in detail.

It is recommended that a device is fully powered up by the time the Plug and Play StartDevice IRP has completed. As you will get only the full list of resources with this Start Device IRP, you will have to power up the device once the resources have been found and allocated. There might well be no need to power down a device during resource reassignment.

You may decide that the device can be powered off when it has been idle for a while. The easiest way to do this is to call the PoRegisterDeviceForIdleDetection function. After a time-out, the Power Manager sends a Set device power IRP to power down the device. Alternatively, you can generate a similar IRP yourself whenever you deem it appropriate. To avoid an idle time-out, you must keep resetting an idle counter using PoSetDeviceBusy every time an I/O operation takes place.

The following line at the end of AddDevice shows how to register for idle notification. The two ULONG parameters are the time-outs in seconds. The first applies when the system is trying to conserve power. The second applies when best performance is the goal. The final parameter to PoRegisterDeviceForIdleDetection is the device state that must be set when a device powers down. Wdm2 powers down to device state D3. Call PoRegisterDeviceForIdleDetection with zeroes for the time-outs to disable idle notification.

dx->PowerIdleCounter = PoRegisterDeviceForIdleDetection(pdo, 30, 60, PowerDeviceD3);

The following code snippet shows how PoSetDeviceBusy is used to reset the idle counter at the beginning of each I/O operation.

if (dx->PowerIdleCounter) PoSetDeviceBusy(dx->PowerIdleCounter);

At the beginning of every I/O operation, you must check to see if the device is powered up. If it is not, most drivers will simply power up the device before starting the request. An alternative strategy is to queue the IRP until the device powers up at some other time.

Make sure that you do not accidentally power down a device during a lengthy I/O operation.

Оглавление книги


Генерация: 1.117. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз