Handling Power Requests

Handling Power Requests

Wearing its FDO hat, a controller or a multifunction driver handles IRP_MJ_POWER requests exactly as described in Chapter 8, with one small exception that I ll discuss presently in connection with IRP_MN_WAIT_WAKE. Wearing its PDO hat, the controller or the driver unconditionally causes to succeed power requests, other than IRP_MN_WAIT_WAKE, for which special processing is required. Table 11-3 summarizes these actions.

Table 11-3. Parent Driver Handling of Power Requests

PnP Request

FDO Hat

PDO Hat

IRP_MN_POWER_SEQUENCE

Normal

Complete

IRP_MN_QUERY_POWER

Normal

Succeed

IRP_MN_SET_POWER

Normal

Special handling

IRP_MN_WAIT_WAKE

Complete child IRPs; otherwise normal

Special handling

Other

Normal

Complete

In the remainder of this section, I ll describe the mechanics of handling power requests, insofar as they re different from standard function driver handling.

The Complete Action

Wearing the PDO hat, the parent driver completes any power IRP it doesn t understand with whatever Status and Information value are already in the IRP. Part of the Driver Verifier s initialization for I/O Verification is to make sure you do this.

NTSTATUS DefaultPowerHandler(PDEVICE_OBJECT fdo, PIRP Irp) { PoStartNextPowerIrp(Irp); NTSTATUS status = Irp->IoStatus.Information; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; }

The Succeed Action

When the parent driver causes an IRP_MJ_POWER request for a child PDO to succeed, it calls PoStartNextPowerIrp and then completes the IRP, as in this fragment:

NTSTATUS HandleQueryPower(PDEVICE_OBJECT pdo, PIRP Irp) { PoStartNextPowerIrp(Irp); return CompleteRequest(Irp, STATUS_SUCCESS, 0); }

The way this fragment differs from what a function driver would do is that the parent driver, being the end of the line, has no one to pass the IRP down to and must, therefore, complete the request.

You should not repeat an IRP_MN_QUERY_POWER on the parent device stack. Doing so in Windows 98/Me causes the Configuration Manager to query the child devices recursively in an infinite loop that eventually exhausts the execution stack. In either system, the Power Manager is already aware of the parent-child relationships between devices and orchestrates the necessary queries on its own.

Handling Device IRP_MN_SET_POWER

An IRP_MN_SET_POWER for a child PDO requires extra work if it specifies a device power state. If it s possible for the parent device to independently control the power state of a child device, the parent driver needs to make that happen. Regardless of whether the child device has a power state independent of the parent, the parent driver should call PoSetPowerState to notify the Power Manager of the new power state. Then it should call PoStartNextPowerIrp and complete the IRP.

NTSTATUS HandleSetPower(IN PDEVICE_OBJECT pdo, IN PIRP Irp) { PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp); if (stack->Parameters.Power.Type == DevicePowerState) { <set child power level> PoSetPowerState(pdo, DevicePowerState, stack->Parameters.Power.State); } PoStartNextPowerIrp(pdo); CompleteRequest(Irp, STATUS_SUCCESS, 0); <possibly change parent power level> return STATUS_SUCCESS; }

In addition, the parent driver might want to change the power level of the parent device to the lowest level consistent with the power levels of all the child devices. For example, if all child devices are in the D3 state, it s likely that the parent device should be in D3 as well. If any child device is in the D0 state, it s likely that the parent device should be in D0 as well. Note that MULFUNC doesn t illustrate this behavior.

Handling IRP_MN_WAIT_WAKE

A child device s system wake-up feature will likely depend on the parent device having wake-up capability too. For this reason, a controller or a multifunction driver has additional responsibilities for handling IRP_MN_WAIT_WAKE that an ordinary function driver wouldn t have.

When a parent driver receives an IRP_MN_WAIT_WAKE for a child PDO, it should take the following actions:

  • If the device capabilities indicate that the parent device is incapable of waking the system under any circumstances, the parent should cause the request to fail with STATUS_NOT_SUPPORTED. (This is what MULFUNC does.)

  • If an IRP_MN_WAIT_WAKE is already outstanding for the same child device, the parent should have the new request fail with STATUS_DEVICE_BUSY.

  • If the child device is already in so low a power state that it couldn t wake the system, or if the device can t wake the system from the power state specified in the IRP, the parent driver should cause the IRP to fail with STATUS_INVALID_DEVICE_STATE. Strictly speaking, the function driver shouldn t originate a WAIT_WAKE request if either of these predicates is true, but it s still up to the parent driver to enforce these rules.

  • Otherwise, the parent driver should mark the IRP pending, cache the IRP in a cancel-safe way, and return STATUS_PENDING. You can, for example, adapt the I/O control (IOCTL) caching scheme discussed in Chapter 9, or you can use a cancel-safe queue (see Chapter 5) as a parking place. This case will be the normal one for a device that actually supports wake-up.

In the last case, the parent driver should also originate its own WAIT_WAKE request on the parent device stack if it hasn t already done so. In this respect, the parent driver is simply doing what any wake-up-capable function driver would do except that it treats the pendency of a child WAIT_WAKE as an additional trigger for sending its own IRP.

If the parent driver s WAIT_WAKE subsequently completes with a success status, the parent should complete one or more of the outstanding child WAIT_WAKE requests. If the parent can determine that a particular child woke up, the parent should complete just that child s IRP. Otherwise, it should complete the IRPs belonging to all children. This step ensures that affected child function drivers handle the wake-up signal appropriately.

If the parent s WAIT_WAKE subsequently completes with an error, the parent driver should ordinarily complete all child WAIT_WAKE requests with the same code. This advice sounds like a more all-encompassing rule than it really is. Only two failure codes should occur in practice. STATUS_CANCELLED means that the parent driver itself has decided to cancel its outstanding WAIT_WAKE in preparation for shutting down or because the end user has disabled the parent device s wake-up feature. STATUS_INVALID_DEVICE_STATE indicates that the system or parent device power state is too low to support wake-up. In either case, the parent should alert all children that their own wake-up features are being disabled by causing their WAIT_WAKE requests to fail.

Case Study in Multifunction Wake-Up

I once wrote a driver for the standard USB SmartCard reader (CCID) class. The CCID specification allows for multiple card slots, and the natural way to implement that functionality is by means of a multifunction driver that creates multiple, identical, child SmartCard reader devices. Many reader manufacturers decided to add system wake-up to their feature set, such that inserting or removing a card would bring the computer out of standby.

I deemed it unlikely that an end user would want to exercise independent control over each of the slots in a multislot reader. Accordingly, I decided to hide the child devices in the Device Manager using the technique described earlier in this chapter. Consequently, the Device Manager property page for the parent device would be the only way for the end user to control whether the wake-up feature was enabled or disabled.

In this driver, then, the primary responsibility for wake-up rested with the parent driver in its FDO role. The child function driver (which was actually embedded in the same executable file as the parent driver) went through the motions of creating and handling WAIT_WAKE requests, but the parent driver essentially ignored these requests beyond simply caching and completing them.

The only quirk in this driver related to how the child driver picked a power state. Since the standard Device Manager hookup for enabling the children s wake-up feature was missing, the child driver had to find out through a back door that the parent was enabled for wake-up and select a compatible device power state. Because I decided to package the child function driver in the same executable with the parent driver, this was easy to arrange.



Programming the Microsoft Windows Driver Model
Programming the Microsoft Windows Driver Model
ISBN: 0735618038
EAN: 2147483647
Year: 2003
Pages: 119
Authors: Walter Oney

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