Книга: Writing Windows WDM Device Drivers

Device Capabilities

Device Capabilities

Another piece of the Power Management puzzle is the IRP_MN_QUERY_CAPABILITIES Plug and Play IRP minor function code. The bus driver usually fills in a DEVICE_CAPABILITIES structure. Several of these fields relate to Power Management. Function or filter drivers can inspect or modify the values set by the bus driver.

Listing 10.9 shows how PnpQueryCapabilitiesHandler handles the Query Capabilities PnP IRP for Wdm2. It first forwards the IRP down the stack and waits for it to complete. It then alters the DEVICE_CAPABILITIES structure, if necessary.

The DeviceState field is an array that indicates the corresponding device power state for each system power state. Or more precisely, it specifies the most powered state that a device can be in at a system power level. For example, when the system is fully on in S0, the device can be fully on in D0 or it may have idled into D3.

PnpQueryCapabilitiesHandler ensures that the correct "most powered device state" is specified by the bus driver. The SetMostPoweredState macro checks to see if a device state has been set and ups the DeviceState entry if appropriate.

Listing 10.9 PnpQueryCapabilitiesHandler routine

#define SetMostPoweredState(SystemState, OurDeviceState)
 dps = deviceCapabilities->DeviceState[SystemState];
 if (dps==PowerDeviceUnspecified || dps>OurDeviceState)
  deviceCapabilities->DeviceState[SystemState] = OurDeviceState
NTSTATUS PnpQueryCapabilitiesHandler(IN PDEVICE_OBJECT fdo, IN PIRP Irp) {
 NTSTATUS status = ForwardIrpAndWait(fdo, Irp);
 if (NT_SUCCESS(status)) {
  PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
  PDEVICE_CAPABILITIES deviceCapabilities;
  deviceCapabilities = IrpStack-Parameters->DeviceCapabilities.Capabilities;
#if DBG
  for (int ds=PowerSystemWorking; ds<PowerSystemMaximum; ds++)
   DebugPrint("Capabilities from bus: DeviceState[%d]=%d",
    ds, deviceCapabilities->DeviceState[ds]);
#endif
  DEVICE_POWER_STATE dps;
  SetMostPoweredState(PowerSystemWorking, PowerDeviceD0); // S0
  SetMostPoweredState(PowerSystemSleeping1, PowerDeviceD3); // S1
  SetMostPoweredState(PowerSystemSleeping2, PowerDeviceD3); // S2
  SetMostPoweredState(PowerSystemSleeping3, PowerDeviceD3); // S3
  SetMostPoweredState(PowerSystemHibernate, PowerDeviceD3); // S4
  SetMostPoweredState(PowerSystemShutdown, PowerDeviceD3); // S5
 }
 return CompleteIrp(Irp, status, Irp->IoStatus.Information);
}

The bus driver for the Wdm2 device sets different values in DeviceState in Windows 98 and Windows 2000 Beta 2, as shown in Table 10.4. Windows 98 sets the most powered device state for S0–S4 to D0 and for S5 to D3. The most powered values for Wdm2 do not alter these values. In contrast, Windows 2000 Beta 2 sets the most powered device state for S1-S3 to D3 but does not set values for the other system states. PnpQueryCapabilitiesHandler will, therefore, modify DeviceState tor S0, S4, and S5.

Table 10.4 DeviceState values

System state S0 S1 S2 S3 S4 S5
W98 D0 D0 D0 D0 D0 D3
W2000 ? D3 D3 D3 ? ?
Wdm2 D0 D3 D3 D3 D3 D3

The SystemWake and DeviceWake fields in the DEVICE_CAPABILITIES structure indicate the lowest powered state from which a device can wake the system. These fields are set to PowerSystemUndefined (0) if the device cannot wake the system. If necessary, alter the values that the bus driver has set.

The D1Latency, D2Latency, and D3Latency fields indicate the approximate time in 100-microsecond units that the device takes to return to the fully on DO state for each sleeping state. Increase the values set by the bus driver, if necessary.

Finally, note that another PnP IRP, IRP_MN_QUERY_RELATIONS, has a PowerRelations subtype that asks for the PDOs of the devices that are related to the current device. These other devices are powered down when this device powers down.

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


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