isopwr.c
上传用户:leituo004
上传日期:2014-11-03
资源大小:159k
文件大小:40k
源码类别:

驱动编程

开发平台:

Visual C++

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4.     isopwr.c
  5. Abstract:
  6.     The power management related processing.
  7.     The Power Manager uses IRPs to direct drivers to change system
  8.     and device power levels, to respond to system wake-up events,
  9.     and to query drivers about their devices. All power IRPs have
  10.     the major function code IRP_MJ_POWER.
  11.     Most function and filter drivers perform some processing for
  12.     each power IRP, then pass the IRP down to the next lower driver
  13.     without completing it. Eventually the IRP reaches the bus driver,
  14.     which physically changes the power state of the device and completes
  15.     the IRP.
  16.     When the IRP has been completed, the I/O Manager calls any
  17.     IoCompletion routines set by drivers as the IRP traveled
  18.     down the device stack. Whether a driver needs to set a completion
  19.     routine depends upon the type of IRP and the driver's individual
  20.     requirements.
  21.     This code is not USB specific. It is essential for every WDM driver
  22.     to handle power irps.
  23. Environment:
  24.     Kernel mode
  25. Notes:
  26.     Copyright (c) 2000 Microsoft Corporation.  
  27.     All Rights Reserved.
  28. --*/
  29. #include "isousb.h"
  30. #include "isopnp.h"
  31. #include "isopwr.h"
  32. #include "isodev.h"
  33. #include "isowmi.h"
  34. #include "isousr.h"
  35. #include "isorwr.h"
  36. #include "isostrm.h"
  37. NTSTATUS
  38. IsoUsb_DispatchPower(
  39.     IN PDEVICE_OBJECT DeviceObject,
  40.     IN PIRP Irp
  41.     )
  42. /*++
  43.  
  44. Routine Description:
  45.     The power dispatch routine.
  46. Arguments:
  47.     DeviceObject - pointer to a device object.
  48.     Irp - pointer to an I/O Request Packet.
  49. Return Value:
  50.     NT status code
  51. --*/
  52. {
  53.     NTSTATUS           ntStatus;
  54.     PIO_STACK_LOCATION irpStack;
  55.     PUNICODE_STRING    tagString;
  56.     PDEVICE_EXTENSION  deviceExtension;
  57.     //
  58.     // initialize the variables
  59.     //
  60.     irpStack = IoGetCurrentIrpStackLocation(Irp);
  61.     deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
  62.     //
  63.     // We don't queue power Irps, we'll only check if the
  64.     // device was removed, otherwise we'll take appropriate
  65.     // action and send it to the next lower driver. In general
  66.     // drivers should not cause long delays while handling power
  67.     // IRPs. If a driver cannot handle a power IRP in a brief time,
  68.     // it should return STATUS_PENDING and queue all incoming
  69.     // IRPs until the IRP completes.
  70.     //
  71.     if(Removed == deviceExtension->DeviceState) {
  72.         //
  73.         // Even if a driver fails the IRP, it must nevertheless call
  74.         // PoStartNextPowerIrp to inform the Power Manager that it
  75.         // is ready to handle another power IRP.
  76.         //
  77.         PoStartNextPowerIrp(Irp);
  78.         Irp->IoStatus.Status = ntStatus = STATUS_DELETE_PENDING;
  79.         Irp->IoStatus.Information = 0;
  80.         IoCompleteRequest(Irp, IO_NO_INCREMENT);
  81.         return ntStatus;
  82.     }
  83.     if(NotStarted == deviceExtension->DeviceState) {
  84.         //
  85.         // if the device is not started yet, pass it down
  86.         //
  87.         PoStartNextPowerIrp(Irp);
  88.         IoSkipCurrentIrpStackLocation(Irp);
  89.         return PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
  90.     }
  91.     IsoUsb_DbgPrint(3, ("IsoUsb_DispatchPower::"));
  92.     IsoUsb_IoIncrement(deviceExtension);
  93.     
  94.     switch(irpStack->MinorFunction) {
  95.     
  96.     case IRP_MN_SET_POWER:
  97.         //
  98.         // The Power Manager sends this IRP for one of the
  99.         // following reasons:
  100.         // 1) To notify drivers of a change to the system power state.
  101.         // 2) To change the power state of a device for which
  102.         //    the Power Manager is performing idle detection.
  103.         // A driver sends IRP_MN_SET_POWER to change the power
  104.         // state of its device if it's a power policy owner for the
  105.         // device.
  106.         //
  107.         // Mark the Irp as pending and return STATUS_PENDING if we change the 
  108.         // nature of the irp in the completion routine (asynchroniticity).
  109.         // In such cases, do not return the status returned by the lower driver.
  110.         // returning STATUS_MORE_PROCESSING_REQUIRED in the completion routine 
  111.         // transforms the nature of the irp to asynchronous irp.
  112.         //
  113.         IoMarkIrpPending(Irp);
  114.         switch(irpStack->Parameters.Power.Type) {
  115.         case SystemPowerState:
  116.             HandleSystemSetPower(DeviceObject, Irp);
  117.             ntStatus = STATUS_PENDING;
  118.             break;
  119.         case DevicePowerState:
  120.             HandleDeviceSetPower(DeviceObject, Irp);
  121.             ntStatus = STATUS_PENDING;
  122.             break;
  123.         }
  124.         break;
  125.     case IRP_MN_QUERY_POWER:
  126.         //
  127.         // The Power Manager sends a power IRP with the minor
  128.         // IRP code IRP_MN_QUERY_POWER to determine whether it
  129.         // can safely change to the specified system power state
  130.         // (S1-S5) and to allow drivers to prepare for such a change.
  131.         // If a driver can put its device in the requested state,
  132.         // it sets status to STATUS_SUCCESS and passes the IRP down.
  133.         //
  134.         IoMarkIrpPending(Irp);
  135.     
  136.         switch(irpStack->Parameters.Power.Type) {
  137.         case SystemPowerState:
  138.             
  139.             HandleSystemQueryPower(DeviceObject, Irp);
  140.             ntStatus = STATUS_PENDING;
  141.             break;
  142.         case DevicePowerState:
  143.             HandleDeviceQueryPower(DeviceObject, Irp);
  144.             ntStatus = STATUS_PENDING;
  145.             break;
  146.         }
  147.         break;
  148.     case IRP_MN_WAIT_WAKE:
  149.         //
  150.         // The minor power IRP code IRP_MN_WAIT_WAKE provides
  151.         // for waking a device or waking the system. Drivers
  152.         // of devices that can wake themselves or the system
  153.         // send IRP_MN_WAIT_WAKE. The system sends IRP_MN_WAIT_WAKE
  154.         // only to devices that always wake the system, such as
  155.         // the power-on switch.
  156.         //
  157.         IoMarkIrpPending(Irp);
  158.         IoCopyCurrentIrpStackLocationToNext(Irp);
  159.         IoSetCompletionRoutine(
  160.                         Irp,
  161.                         (PIO_COMPLETION_ROUTINE)WaitWakeCompletionRoutine,
  162.                         deviceExtension, 
  163.                         TRUE, 
  164.                         TRUE, 
  165.                         TRUE);
  166.         PoStartNextPowerIrp(Irp);
  167.         ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
  168.         if(!NT_SUCCESS(ntStatus)) {
  169.             IsoUsb_DbgPrint(1, ("Lower drivers failed this Irpn"));
  170.         }
  171.         ntStatus = STATUS_PENDING;
  172.         //
  173.         // push back the count HERE and NOT in completion routine
  174.         // a pending Wait Wake Irp should not impede stopping the device
  175.         //
  176.         IsoUsb_DbgPrint(3, ("IRP_MN_WAIT_WAKE::"));
  177.         IsoUsb_IoDecrement(deviceExtension);
  178.         break;
  179.     case IRP_MN_POWER_SEQUENCE:
  180.         //
  181.         // A driver sends this IRP as an optimization to determine
  182.         // whether its device actually entered a specific power state.
  183.         // This IRP is optional. Power Manager cannot send this IRP.
  184.         //
  185.     default:
  186.         PoStartNextPowerIrp(Irp);
  187.         IoSkipCurrentIrpStackLocation(Irp);
  188.         ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
  189.         if(!NT_SUCCESS(ntStatus)) {
  190.             IsoUsb_DbgPrint(1, ("Lower drivers failed this Irpn"));
  191.         }
  192.         
  193.         IsoUsb_DbgPrint(3, ("IsoUsb_DispatchPower::"));
  194.         IsoUsb_IoDecrement(deviceExtension);
  195.         break;
  196.     }
  197.     return ntStatus;
  198. }
  199. NTSTATUS
  200. HandleSystemQueryPower(
  201.     IN PDEVICE_OBJECT DeviceObject,
  202.     IN PIRP Irp
  203.     )
  204. /*++
  205.  
  206. Routine Description:
  207.     This routine handles the irp with minor function of type IRP_MN_QUERY_POWER
  208.     for the system power states.
  209. Arguments:
  210.     DeviceObject - pointer to device object
  211.     Irp - I/O request packet sent by the power manager.
  212. Return Value:
  213.     NT status value
  214. --*/
  215. {
  216.     NTSTATUS           ntStatus;
  217.     PDEVICE_EXTENSION  deviceExtension;
  218.     SYSTEM_POWER_STATE systemState;
  219.     PIO_STACK_LOCATION irpStack;
  220.     
  221.     IsoUsb_DbgPrint(3, ("HandleSystemQueryPower - beginsn"));
  222.     //
  223.     // initialize variables
  224.     //
  225.     deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
  226.     irpStack = IoGetCurrentIrpStackLocation(Irp);
  227.     systemState = irpStack->Parameters.Power.State.SystemState;
  228.     IsoUsb_DbgPrint(3, ("Query for system power state S%Xn"
  229.                         "Current system power state S%Xn",
  230.                         systemState - 1,
  231.                         deviceExtension->SysPower - 1));
  232.     //
  233.     // Fail a query for a power state incompatible with waking up the system
  234.     //
  235.     if((deviceExtension->WaitWakeEnable) &&
  236.        (systemState > deviceExtension->DeviceCapabilities.SystemWake)) {
  237.         PoStartNextPowerIrp(Irp);
  238.         Irp->IoStatus.Status = ntStatus = STATUS_INVALID_DEVICE_STATE;
  239.         Irp->IoStatus.Information = 0;
  240.         IoCompleteRequest(Irp, IO_NO_INCREMENT);
  241.         IsoUsb_DbgPrint(3, ("HandleSystemQueryPower::"));
  242.         IsoUsb_IoDecrement(deviceExtension);
  243.         return ntStatus;
  244.     }
  245.     //
  246.     // if querying for a lower S-state, issue a wait-wake
  247.     //
  248.     if((systemState > deviceExtension->SysPower) &&
  249.        (deviceExtension->WaitWakeEnable)) {
  250.         IssueWaitWake(deviceExtension);
  251.     }
  252.     IoCopyCurrentIrpStackLocationToNext(Irp);
  253.     IoSetCompletionRoutine(
  254.             Irp, 
  255.             (PIO_COMPLETION_ROUTINE)SysPoCompletionRoutine,
  256.             deviceExtension, 
  257.             TRUE, 
  258.             TRUE, 
  259.             TRUE);
  260.     ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
  261.     IsoUsb_DbgPrint(3, ("HandleSystemQueryPower - endsn"));
  262.     return STATUS_PENDING;
  263. }
  264. NTSTATUS
  265. HandleSystemSetPower(
  266.     IN PDEVICE_OBJECT DeviceObject,
  267.     IN PIRP Irp
  268.     )
  269. /*++
  270.  
  271. Routine Description:
  272.     This routine services irps of minor type IRP_MN_SET_POWER
  273.     for the system power state
  274. Arguments:
  275.     DeviceObject - pointer to device object
  276.     Irp - I/O request packet sent by the power manager
  277. Return Value:
  278.     NT status value
  279. --*/
  280. {
  281.     NTSTATUS           ntStatus;
  282.     PDEVICE_EXTENSION  deviceExtension;
  283.     SYSTEM_POWER_STATE systemState;
  284.     PIO_STACK_LOCATION irpStack;
  285.     
  286.     IsoUsb_DbgPrint(3, ("HandleSystemSetPower - beginsn"));
  287.     //
  288.     // initialize variables
  289.     //
  290.     deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
  291.     irpStack = IoGetCurrentIrpStackLocation(Irp);
  292.     systemState = irpStack->Parameters.Power.State.SystemState;
  293.     IsoUsb_DbgPrint(3, ("Set request for system power state S%Xn"
  294.                         "Current system power state S%Xn",
  295.                         systemState - 1,
  296.                         deviceExtension->SysPower - 1));
  297.     IoCopyCurrentIrpStackLocationToNext(Irp);
  298.     IoSetCompletionRoutine(
  299.             Irp, 
  300.             (PIO_COMPLETION_ROUTINE)SysPoCompletionRoutine,
  301.             deviceExtension, 
  302.             TRUE, 
  303.             TRUE, 
  304.             TRUE);
  305.     ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
  306.     IsoUsb_DbgPrint(3, ("HandleSystemSetPower - endsn"));
  307.     return STATUS_PENDING;
  308. }
  309. NTSTATUS
  310. HandleDeviceQueryPower(
  311.     PDEVICE_OBJECT DeviceObject,
  312.     PIRP           Irp
  313.     )
  314. /*++
  315.  
  316. Routine Description:
  317.     This routine services irps of minor type IRP_MN_QUERY_POWER
  318.     for the device power state
  319. Arguments:
  320.     DeviceObject - pointer to device object
  321.     Irp - I/O request packet sent by the power manager
  322. Return Value:
  323.     NT status value
  324. --*/
  325. {
  326.     NTSTATUS           ntStatus;
  327.     PDEVICE_EXTENSION  deviceExtension;
  328.     PIO_STACK_LOCATION irpStack;
  329.     DEVICE_POWER_STATE deviceState;
  330.     IsoUsb_DbgPrint(3, ("HandleDeviceQueryPower - beginsn"));
  331.     //
  332.     // initialize variables
  333.     //
  334.     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  335.     irpStack = IoGetCurrentIrpStackLocation(Irp);
  336.     deviceState = irpStack->Parameters.Power.State.DeviceState;
  337.     IsoUsb_DbgPrint(3, ("Query for device power state D%Xn"
  338.                         "Current device power state D%Xn",
  339.                         deviceState - 1,
  340.                         deviceExtension->DevPower - 1));
  341.     if(deviceExtension->WaitWakeEnable &&
  342.        deviceState > deviceExtension->DeviceCapabilities.DeviceWake) {
  343.         PoStartNextPowerIrp(Irp);
  344.         Irp->IoStatus.Status = ntStatus = STATUS_INVALID_DEVICE_STATE;
  345.         Irp->IoStatus.Information = 0;
  346.         IoCompleteRequest(Irp, IO_NO_INCREMENT);
  347.         IsoUsb_DbgPrint(3, ("HandleDeviceQueryPower::"));
  348.         IsoUsb_IoDecrement(deviceExtension);
  349.         return ntStatus;
  350.     }
  351.     if(deviceState < deviceExtension->DevPower) {
  352.         ntStatus = STATUS_SUCCESS;
  353.     }
  354.     else {
  355.         ntStatus = HoldIoRequests(DeviceObject, Irp);
  356.         if(STATUS_PENDING == ntStatus) {
  357.             return ntStatus;
  358.         }
  359.     }
  360.     //
  361.     // on error complete the Irp.
  362.     // on success pass it to the lower layers
  363.     //
  364.     PoStartNextPowerIrp(Irp);
  365.     Irp->IoStatus.Status = ntStatus;
  366.     Irp->IoStatus.Information = 0;
  367.     if(!NT_SUCCESS(ntStatus)) {
  368.         IoCompleteRequest(Irp, IO_NO_INCREMENT);
  369.     }
  370.     else {
  371.         IoSkipCurrentIrpStackLocation(Irp);
  372.         ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
  373.     }
  374.     IsoUsb_DbgPrint(3, ("HandleDeviceQueryPower::"));
  375.     IsoUsb_IoDecrement(deviceExtension);
  376.     IsoUsb_DbgPrint(3, ("HandleDeviceQueryPower - endsn"));
  377.     return ntStatus;
  378. }
  379. NTSTATUS
  380. SysPoCompletionRoutine(
  381.     IN PDEVICE_OBJECT DeviceObject,
  382.     IN PIRP Irp,
  383.     IN PDEVICE_EXTENSION DeviceExtension
  384.     )
  385. /*++
  386.  
  387. Routine Description:
  388.     This is the completion routine for the system power irps of minor
  389.     function types IRP_MN_QUERY_POWER and IRP_MN_SET_POWER.
  390.     This completion routine sends the corresponding device power irp and
  391.     returns STATUS_MORE_PROCESSING_REQUIRED. The system irp is passed as a
  392.     context to the device power irp completion routine and is completed in
  393.     the device power irp completion routine.
  394. Arguments:
  395.     DeviceObject - pointer to device object
  396.     Irp - I/O request packet
  397.     DeviceExtension - pointer to device extension
  398. Return Value:
  399.     NT status value
  400. --*/
  401. {
  402.     NTSTATUS           ntStatus;
  403.   PIO_STACK_LOCATION irpStack;
  404.     //
  405.     // initialize variables
  406.     //
  407.     ntStatus = Irp->IoStatus.Status;
  408.     irpStack = IoGetCurrentIrpStackLocation(Irp);
  409.     IsoUsb_DbgPrint(3, ("SysPoCompletionRoutine - beginsn"));
  410.     //
  411.     // lower drivers failed this Irp
  412.     //
  413.     if(!NT_SUCCESS(ntStatus)) {
  414.         PoStartNextPowerIrp(Irp);
  415.         IsoUsb_DbgPrint(3, ("SysPoCompletionRoutine::"));
  416.         IsoUsb_IoDecrement(DeviceExtension);
  417.         return STATUS_SUCCESS;
  418.     }
  419.     //
  420.     // ..otherwise update the cached system power state (IRP_MN_SET_POWER)
  421.     //
  422.     if(irpStack->MinorFunction == IRP_MN_SET_POWER) {
  423.         DeviceExtension->SysPower = irpStack->Parameters.Power.State.SystemState;
  424.     }
  425.     //
  426.     // queue device irp and return STATUS_MORE_PROCESSING_REQUIRED
  427.     //
  428.     SendDeviceIrp(DeviceObject, Irp);
  429.     IsoUsb_DbgPrint(3, ("SysPoCompletionRoutine - endsn"));
  430.     return STATUS_MORE_PROCESSING_REQUIRED;
  431. }
  432. VOID
  433. SendDeviceIrp(
  434.     IN PDEVICE_OBJECT DeviceObject,
  435.     IN PIRP SIrp
  436.     )
  437. /*++
  438.  
  439. Routine Description:
  440.     This routine is invoked from the completion routine of the system power
  441.     irp. This routine will PoRequest a device power irp. The system irp is 
  442.     passed as a context to the the device power irp.
  443. Arguments:
  444.     DeviceObject - pointer to device object
  445.     SIrp - system power irp.
  446. Return Value:
  447.     None
  448. --*/
  449. {
  450.     NTSTATUS                  ntStatus;
  451.     POWER_STATE               powState;
  452.     PDEVICE_EXTENSION         deviceExtension;
  453.     PIO_STACK_LOCATION        irpStack;
  454.     SYSTEM_POWER_STATE        systemState;
  455.     DEVICE_POWER_STATE        devState;
  456.     PPOWER_COMPLETION_CONTEXT powerContext;
  457.     
  458.     //
  459.     // initialize variables
  460.     //
  461.     irpStack = IoGetCurrentIrpStackLocation(SIrp);
  462.     systemState = irpStack->Parameters.Power.State.SystemState;
  463.     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  464.     IsoUsb_DbgPrint(3, ("SendDeviceIrp - beginsn"));
  465.     //
  466.     // Read out the D-IRP out of the S->D mapping array captured in QueryCap's.
  467.     // we can choose deeper sleep states than our mapping but never choose
  468.     // lighter ones.
  469.     //
  470.     devState = deviceExtension->DeviceCapabilities.DeviceState[systemState];
  471.     powState.DeviceState = devState;
  472.     
  473.     powerContext = (PPOWER_COMPLETION_CONTEXT) 
  474.                    ExAllocatePool(NonPagedPool,
  475.                                   sizeof(POWER_COMPLETION_CONTEXT));
  476.     if(!powerContext) {
  477.         IsoUsb_DbgPrint(1, ("Failed to alloc memory for powerContextn"));
  478.         ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  479.     }
  480.     else {
  481.         powerContext->DeviceObject = DeviceObject;
  482.         powerContext->SIrp = SIrp;
  483.    
  484.         //
  485.         // in win2k PoRequestPowerIrp can take fdo or pdo.
  486.         //
  487.         ntStatus = PoRequestPowerIrp(
  488.                             deviceExtension->PhysicalDeviceObject, 
  489.                             irpStack->MinorFunction,
  490.                             powState,
  491.                             (PREQUEST_POWER_COMPLETE)DevPoCompletionRoutine,
  492.                             powerContext, 
  493.                             NULL);
  494.     }
  495.     if(!NT_SUCCESS(ntStatus)) {
  496.         if(powerContext) {
  497.             ExFreePool(powerContext);
  498.         }
  499.         PoStartNextPowerIrp(SIrp);
  500.         SIrp->IoStatus.Status = ntStatus;
  501.         SIrp->IoStatus.Information = 0;
  502.         
  503.         IoCompleteRequest(SIrp, IO_NO_INCREMENT);
  504.         IsoUsb_DbgPrint(3, ("SendDeviceIrp::"));
  505.         IsoUsb_IoDecrement(deviceExtension);
  506.     }
  507.     IsoUsb_DbgPrint(3, ("SendDeviceIrp - endsn"));
  508. }
  509. VOID
  510. DevPoCompletionRoutine(
  511.     IN PDEVICE_OBJECT DeviceObject, 
  512.     IN UCHAR MinorFunction,
  513.     IN POWER_STATE PowerState,
  514.     IN PVOID Context,
  515.     IN PIO_STATUS_BLOCK IoStatus
  516.     )
  517. /*++
  518.  
  519. Routine Description:
  520.     This is the PoRequest - completion routine for the device power irp.
  521.     This routine is responsible for completing the system power irp, 
  522.     received as a context.
  523. Arguments:
  524.     DeviceObject - pointer to device object
  525.     MinorFunction - minor function of the irp.
  526.     PowerState - power state of the irp.
  527.     Context - context passed to the completion routine.
  528.     IoStatus - status of the device power irp.
  529. Return Value:
  530.     None
  531. --*/
  532. {
  533.     PIRP                      sIrp;
  534.     PDEVICE_EXTENSION         deviceExtension;
  535.     PPOWER_COMPLETION_CONTEXT powerContext;
  536.     
  537.     //
  538.     // initialize variables
  539.     //
  540.     powerContext = (PPOWER_COMPLETION_CONTEXT) Context;
  541.     sIrp = powerContext->SIrp;
  542.     deviceExtension = powerContext->DeviceObject->DeviceExtension;
  543.     IsoUsb_DbgPrint(3, ("DevPoCompletionRoutine - beginsn"));
  544.     //
  545.     // copy the D-Irp status into S-Irp
  546.     //
  547.     sIrp->IoStatus.Status = IoStatus->Status;
  548.     //
  549.     // complete the system Irp
  550.     //
  551.     
  552.     PoStartNextPowerIrp(sIrp);
  553.     sIrp->IoStatus.Information = 0;
  554.     IoCompleteRequest(sIrp, IO_NO_INCREMENT);
  555.     //
  556.     // cleanup
  557.     //
  558.     
  559.     IsoUsb_DbgPrint(3, ("DevPoCompletionRoutine::"));
  560.     IsoUsb_IoDecrement(deviceExtension);
  561.     ExFreePool(powerContext);
  562.     IsoUsb_DbgPrint(3, ("DevPoCompletionRoutine - endsn"));
  563. }
  564. NTSTATUS
  565. HandleDeviceSetPower(
  566.     IN PDEVICE_OBJECT DeviceObject,
  567.     IN PIRP Irp
  568.     )
  569. /*++
  570.  
  571. Routine Description:
  572.     This routine services irps of minor type IRP_MN_SET_POWER
  573.     for the device power state
  574. Arguments:
  575.     DeviceObject - pointer to device object
  576.     Irp - I/O request packet sent by the power manager
  577. Return Value:
  578.     NT status value
  579. --*/
  580. {
  581.     KIRQL              oldIrql;
  582.     NTSTATUS           ntStatus;
  583.     POWER_STATE        newState;    
  584.     PIO_STACK_LOCATION irpStack;
  585.     PDEVICE_EXTENSION  deviceExtension;
  586.     DEVICE_POWER_STATE newDevState,
  587.                        oldDevState;
  588.     IsoUsb_DbgPrint(3, ("HandleDeviceSetPower - beginsn"));
  589.     //
  590.     // initialize variables
  591.     //
  592.     deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
  593.     irpStack = IoGetCurrentIrpStackLocation(Irp);
  594.     oldDevState = deviceExtension->DevPower;
  595.     newState = irpStack->Parameters.Power.State;
  596.     newDevState = newState.DeviceState;
  597.     IsoUsb_DbgPrint(3, ("Set request for device power state D%Xn"
  598.                         "Current device power state D%Xn",
  599.                         newDevState - 1,
  600.                         deviceExtension->DevPower - 1));
  601.     if(newDevState < oldDevState) {
  602.         //
  603.         // adding power
  604.         //
  605.         IsoUsb_DbgPrint(3, ("Adding power to the devicen"));
  606.         //
  607.         // send the power IRP to the next driver in the stack
  608.         //
  609.         IoCopyCurrentIrpStackLocationToNext(Irp);
  610.         IoSetCompletionRoutine(
  611.                 Irp, 
  612.                 (PIO_COMPLETION_ROUTINE)FinishDevPoUpIrp,
  613.                 deviceExtension, 
  614.                 TRUE, 
  615.                 TRUE, 
  616.                 TRUE);
  617.         ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
  618. }
  619.     else {
  620.         IsoUsb_DbgPrint(3, ("Removing power or SetD0n"));
  621.         //
  622.         // newDevState >= oldDevState 
  623.         //
  624.         // hold I/O if transition from D0 -> DX (X = 1, 2, 3)
  625.         // if transition from D1 or D2 to deeper sleep states, 
  626.         // I/O queue is already on hold.
  627.         //
  628.         if(PowerDeviceD0 == oldDevState && newDevState > oldDevState) {
  629.             //
  630.             // D0 -> DX transition
  631.             //
  632.             ntStatus = HoldIoRequests(DeviceObject, Irp);
  633.             if(!NT_SUCCESS(ntStatus)) {
  634.                 PoStartNextPowerIrp(Irp);
  635.                 Irp->IoStatus.Status = ntStatus;
  636.                 Irp->IoStatus.Information = 0;
  637.                 IoCompleteRequest(Irp, IO_NO_INCREMENT);
  638.                 IsoUsb_DbgPrint(3, ("HandleDeviceSetPower::"));
  639.                 IsoUsb_IoDecrement(deviceExtension);
  640.                 return ntStatus;
  641.             }
  642.             else {
  643.                 goto HandleDeviceSetPower_Exit;
  644.             }
  645.         }
  646.         else if(PowerDeviceD0 == oldDevState && PowerDeviceD0 == newDevState) {
  647.             //
  648.             // D0 -> D0
  649.             // unblock the queue which may have been blocked processing
  650.             // query irp
  651.             //
  652.             KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
  653.               
  654.             deviceExtension->QueueState = AllowRequests;
  655.             KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
  656.             ProcessQueuedRequests(deviceExtension);
  657.         }   
  658.         IoCopyCurrentIrpStackLocationToNext(Irp);
  659.         IoSetCompletionRoutine(
  660.                 Irp, 
  661.                 (PIO_COMPLETION_ROUTINE) FinishDevPoDnIrp,
  662.                 deviceExtension, 
  663.                 TRUE, 
  664.                 TRUE, 
  665.                 TRUE);
  666.         ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
  667.         if(!NT_SUCCESS(ntStatus)) {
  668.             IsoUsb_DbgPrint(1, ("Lower drivers failed a power Irpn"));
  669.         }
  670.     }
  671. HandleDeviceSetPower_Exit:
  672.     IsoUsb_DbgPrint(3, ("HandleDeviceSetPower - endsn"));
  673.     return STATUS_PENDING;
  674. }
  675. NTSTATUS
  676. FinishDevPoUpIrp(
  677.     IN PDEVICE_OBJECT DeviceObject,
  678.     IN PIRP Irp,
  679.     IN PDEVICE_EXTENSION DeviceExtension
  680.     )
  681. /*++
  682.  
  683. Routine Description:
  684.     completion routine for the device power UP irp with minor function
  685.     IRP_MN_SET_POWER.
  686. Arguments:
  687.     DeviceObject - pointer to device object
  688.     Irp - I/O request packet
  689.     DeviceExtension - pointer to device extension
  690. Return Value:
  691.     NT status value
  692. --*/
  693. {
  694.     NTSTATUS           ntStatus;
  695.                         
  696.     //
  697.     // initialize variables
  698.     //
  699.     ntStatus = Irp->IoStatus.Status;
  700.     IsoUsb_DbgPrint(3, ("FinishDevPoUpIrp - beginsn"));
  701.     if(Irp->PendingReturned) {
  702.         IoMarkIrpPending(Irp);
  703.     }
  704.     if(!NT_SUCCESS(ntStatus)) {
  705.         PoStartNextPowerIrp(Irp);
  706.         IsoUsb_DbgPrint(3, ("FinishDevPoUpIrp::"));
  707.         IsoUsb_IoDecrement(DeviceExtension);
  708.         return STATUS_SUCCESS;
  709.     }
  710.     SetDeviceFunctional(DeviceObject, Irp, DeviceExtension);
  711.     IsoUsb_DbgPrint(3, ("FinishDevPoUpIrp - endsn"));
  712.     return STATUS_MORE_PROCESSING_REQUIRED;
  713. }
  714. NTSTATUS
  715. SetDeviceFunctional(
  716.     IN PDEVICE_OBJECT DeviceObject,
  717.     IN PIRP Irp,
  718.     IN PDEVICE_EXTENSION DeviceExtension
  719.     )
  720. /*++
  721.  
  722. Routine Description:
  723.     This routine processes queue of pending irps.
  724. Arguments:
  725.     DeviceObject - pointer to device object
  726.     Irp - I/O request packet
  727.     DeviceExtension - pointer to device extension
  728. Return Value:
  729.     NT status value
  730. --*/
  731. {
  732.     KIRQL              oldIrql;
  733.     NTSTATUS           ntStatus;
  734.     POWER_STATE        newState;
  735.     PIO_STACK_LOCATION irpStack;
  736.     DEVICE_POWER_STATE newDevState,
  737.                        oldDevState;
  738.     //
  739.     // initialize variables
  740.     //
  741.     ntStatus = Irp->IoStatus.Status;
  742.     irpStack = IoGetCurrentIrpStackLocation(Irp);
  743.     newState = irpStack->Parameters.Power.State;
  744.     newDevState = newState.DeviceState;
  745.     oldDevState = DeviceExtension->DevPower;
  746.     IsoUsb_DbgPrint(3, ("SetDeviceFunctional - beginsn"));
  747.     //
  748.     // update the cached state
  749.     //
  750.     DeviceExtension->DevPower = newDevState;
  751.     //
  752.     // restore appropriate amount of state to our h/w
  753.     // this driver does not implement partial context
  754.     // save/restore.
  755.     //
  756.     PoSetPowerState(DeviceObject, DevicePowerState, newState);
  757.     if(PowerDeviceD0 == newDevState) {
  758.     //
  759.     // empty existing queue of all pending irps.
  760.     //
  761.         KeAcquireSpinLock(&DeviceExtension->DevStateLock, &oldIrql);
  762.         DeviceExtension->QueueState = AllowRequests;
  763.         
  764.         KeReleaseSpinLock(&DeviceExtension->DevStateLock, oldIrql);
  765.         ProcessQueuedRequests(DeviceExtension);
  766.     }
  767.     PoStartNextPowerIrp(Irp);
  768.     Irp->IoStatus.Status = STATUS_SUCCESS;
  769.     Irp->IoStatus.Information = 0;
  770.     IoCompleteRequest(Irp, IO_NO_INCREMENT);
  771.     IsoUsb_DbgPrint(3, ("SetDeviceFunctional::"));
  772.     IsoUsb_IoDecrement(DeviceExtension);
  773.     IsoUsb_DbgPrint(3, ("SetDeviceFunctional - endsn"));
  774.     return STATUS_SUCCESS;
  775. }
  776. NTSTATUS
  777. FinishDevPoDnIrp(
  778.     IN PDEVICE_OBJECT DeviceObject,
  779.     IN PIRP Irp,
  780.     IN PDEVICE_EXTENSION DeviceExtension
  781.     )
  782. /*++
  783.  
  784. Routine Description:
  785.     This routine is the completion routine for device power DOWN irp.
  786. Arguments:
  787.     DeviceObject - pointer to device object
  788.     Irp - I/O request packet
  789.     DeviceExtension - pointer to device extension
  790. Return Value:
  791.     NT status value
  792. --*/
  793. {
  794.     NTSTATUS           ntStatus;
  795.     POWER_STATE        newState;
  796.     PIO_STACK_LOCATION irpStack;
  797.     //
  798.     // initialize variables
  799.     //
  800.     ntStatus = Irp->IoStatus.Status;
  801.     irpStack = IoGetCurrentIrpStackLocation(Irp);
  802.     newState = irpStack->Parameters.Power.State;
  803.     IsoUsb_DbgPrint(3, ("FinishDevPoDnIrp - beginsn"));
  804.     if(NT_SUCCESS(ntStatus) && irpStack->MinorFunction == IRP_MN_SET_POWER) {
  805.         //
  806.         // update the cache;
  807.         //
  808.         IsoUsb_DbgPrint(3, ("updating cache..n"));
  809.         DeviceExtension->DevPower = newState.DeviceState;
  810.         PoSetPowerState(DeviceObject, DevicePowerState, newState);
  811.     }
  812.     PoStartNextPowerIrp(Irp);
  813.     IsoUsb_DbgPrint(3, ("FinishDevPoDnIrp::"));
  814.     IsoUsb_IoDecrement(DeviceExtension);
  815.     IsoUsb_DbgPrint(3, ("FinishDevPoDnIrp - endsn"));
  816.     return STATUS_SUCCESS;
  817. }
  818. NTSTATUS
  819. HoldIoRequests(
  820.     IN PDEVICE_OBJECT DeviceObject,
  821.     IN PIRP           Irp
  822.     )
  823. /*++
  824.  
  825. Routine Description:
  826.     This routine is called on query or set power DOWN irp for the device.
  827.     This routine queues a workitem.
  828. Arguments:
  829.     DeviceObject - pointer to device object
  830.     Irp - I/O request packet
  831. Return Value:
  832.     NT status value
  833. --*/
  834. {
  835.     NTSTATUS               ntStatus;
  836.     PIO_WORKITEM           item;
  837.     PDEVICE_EXTENSION      deviceExtension;
  838.     PWORKER_THREAD_CONTEXT context;
  839.     //
  840.     // initialize variables
  841.     //
  842.     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  843.     IsoUsb_DbgPrint(3, ("HoldIoRequests - beginsn"));
  844.     deviceExtension->QueueState = HoldRequests;
  845.     context = ExAllocatePool(NonPagedPool, sizeof(WORKER_THREAD_CONTEXT));
  846.     if(context) {
  847.         item = IoAllocateWorkItem(DeviceObject);
  848.         context->Irp = Irp;
  849.         context->DeviceObject = DeviceObject;
  850.         context->WorkItem = item;
  851.         if(item) {
  852.             IoMarkIrpPending(Irp);
  853.             
  854.             IoQueueWorkItem(item, HoldIoRequestsWorkerRoutine,
  855.                             DelayedWorkQueue, context);
  856.             
  857.             ntStatus = STATUS_PENDING;
  858.         }
  859.         else {
  860.             IsoUsb_DbgPrint(3, ("Failed to allocate memory for workitemn"));
  861.             ExFreePool(context);
  862.             ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  863.         }
  864.     }
  865.     else {
  866.         IsoUsb_DbgPrint(1, ("Failed to alloc memory for worker thread contextn"));
  867.         ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  868.     }
  869.     IsoUsb_DbgPrint(3, ("HoldIoRequests - endsn"));
  870.     return ntStatus;
  871. }
  872. VOID
  873. HoldIoRequestsWorkerRoutine(
  874.     IN PDEVICE_OBJECT DeviceObject,
  875.     IN PVOID          Context
  876.     )
  877. /*++
  878.  
  879. Routine Description:
  880.     This routine waits for the I/O in progress to finish and then
  881.     sends the device power irp (query/set) down the stack.
  882. Arguments:
  883.     DeviceObject - pointer to device object
  884.     Context - context passed to the work-item.
  885. Return Value:
  886.     None
  887. --*/
  888. {
  889.     PIRP                   irp;
  890.     NTSTATUS               ntStatus;
  891.     PDEVICE_EXTENSION      deviceExtension;
  892.     PWORKER_THREAD_CONTEXT context;
  893.     IsoUsb_DbgPrint(3, ("HoldIoRequestsWorkerRoutine - beginsn"));
  894.     //
  895.     // initialize variables
  896.     //
  897.     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  898.     context = (PWORKER_THREAD_CONTEXT) Context;
  899.     irp = (PIRP) context->Irp;
  900.     //
  901.     // wait for I/O in progress to finish.
  902.     // the stop event is signalled when the counter drops to 1.
  903.     // invoke IsoUsb_IoDecrement twice: once each for the S-Irp and D-Irp.
  904.     //
  905.     IsoUsb_DbgPrint(3, ("HoldIoRequestsWorkerRoutine::"));
  906.     IsoUsb_IoDecrement(deviceExtension);
  907.     IsoUsb_DbgPrint(3, ("HoldIoRequestsWorkerRoutine::"));
  908.     IsoUsb_IoDecrement(deviceExtension);
  909.     KeWaitForSingleObject(&deviceExtension->StopEvent, Executive,
  910.                           KernelMode, FALSE, NULL);
  911.     //
  912.     // Increment twice to restore the count
  913.     //
  914.     IsoUsb_DbgPrint(3, ("HoldIoRequestsWorkerRoutine::"));
  915.     IsoUsb_IoIncrement(deviceExtension);
  916.     IsoUsb_DbgPrint(3, ("HoldIoRequestsWorkerRoutine::"));
  917.     IsoUsb_IoIncrement(deviceExtension);
  918.     // 
  919.     // now send the Irp down
  920.     //
  921.     IoCopyCurrentIrpStackLocationToNext(irp);
  922.     IoSetCompletionRoutine(irp, (PIO_COMPLETION_ROUTINE) FinishDevPoDnIrp,
  923.                            deviceExtension, TRUE, TRUE, TRUE);
  924.     ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, irp);
  925.     if(!NT_SUCCESS(ntStatus)) {
  926.         IsoUsb_DbgPrint(1, ("Lower driver fail a power Irpn"));
  927.     }
  928.     IoFreeWorkItem(context->WorkItem);
  929.     ExFreePool((PVOID)context);
  930.     IsoUsb_DbgPrint(3, ("HoldIoRequestsWorkerRoutine - endsn"));
  931. }
  932. NTSTATUS
  933. QueueRequest(
  934.     IN OUT PDEVICE_EXTENSION DeviceExtension,
  935.     IN PIRP Irp
  936.     )
  937. /*++
  938.  
  939. Routine Description:
  940.     Queue the Irp in the device queue
  941. Arguments:
  942.     DeviceExtension - pointer to device extension
  943.     Irp - I/O request packet.
  944. Return Value:
  945.     NT status value
  946. --*/
  947. {
  948.     KIRQL    oldIrql;
  949.     NTSTATUS ntStatus;
  950.     //
  951.     // initialize variables
  952.     //
  953.     ntStatus = STATUS_PENDING;
  954.     IsoUsb_DbgPrint(3, ("QueueRequests - beginsn"));
  955.     ASSERT(HoldRequests == DeviceExtension->QueueState);
  956.     KeAcquireSpinLock(&DeviceExtension->QueueLock, &oldIrql);
  957.     InsertTailList(&DeviceExtension->NewRequestsQueue, 
  958.                    &Irp->Tail.Overlay.ListEntry);
  959.     IoMarkIrpPending(Irp);
  960.     //
  961.     // Set the cancel routine
  962.     //
  963.     IoSetCancelRoutine(Irp, CancelQueued);
  964.     KeReleaseSpinLock(&DeviceExtension->QueueLock, oldIrql);
  965.     IsoUsb_DbgPrint(3, ("QueueRequests - endsn"));
  966.     return ntStatus;
  967. }
  968. VOID
  969. CancelQueued(
  970.     IN PDEVICE_OBJECT DeviceObject,
  971.     IN PIRP           Irp
  972.     )
  973. /*++
  974.  
  975. Routine Description:
  976.     This routine removes the irp from the queue and completes it with
  977.     STATUS_CANCELLED
  978. Arguments:
  979.     DeviceObject - pointer to device object
  980.     Irp - I/O request packet
  981. Return Value:
  982.     None.
  983. --*/
  984. {
  985.     PDEVICE_EXTENSION deviceExtension;
  986.     KIRQL             oldIrql;
  987.     //
  988.     // initialize variables
  989.     //
  990.     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  991.     oldIrql = Irp->CancelIrql;
  992.     IsoUsb_DbgPrint(3, ("CancelQueued - beginsn"));
  993.     //
  994.     // Release the cancel spin lock
  995.     //
  996.     IoReleaseCancelSpinLock(Irp->CancelIrql);
  997.     //
  998.     // Acquire the queue lock
  999.     //
  1000.     KeAcquireSpinLockAtDpcLevel(&deviceExtension->QueueLock);
  1001.     //
  1002.     // Remove the cancelled Irp from queue and release the lock
  1003.     //
  1004.     RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
  1005.     KeReleaseSpinLock(&deviceExtension->QueueLock, oldIrql);
  1006.     //
  1007.     // complete with STATUS_CANCELLED
  1008.     //
  1009.     Irp->IoStatus.Status = STATUS_CANCELLED;
  1010.     Irp->IoStatus.Information = 0;
  1011.     IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1012.     IsoUsb_DbgPrint(3, ("CancelQueued - endsn"));
  1013.     return;
  1014. }
  1015. NTSTATUS
  1016. IssueWaitWake(
  1017.     IN PDEVICE_EXTENSION DeviceExtension
  1018.     )
  1019. /*++
  1020.  
  1021. Routine Description:
  1022.     This routine will PoRequest a WAIT WAKE irp for the device
  1023. Arguments:
  1024.     DeviceExtension - pointer to device extension
  1025. Return Value:
  1026.     NT status value.
  1027. --*/
  1028. {
  1029.     POWER_STATE poState;
  1030.     NTSTATUS    ntStatus;
  1031.     IsoUsb_DbgPrint(3, ("IssueWaitWake - beginsn"));
  1032.     if(InterlockedExchange(&DeviceExtension->FlagWWOutstanding, 1)) {
  1033.         return STATUS_DEVICE_BUSY;
  1034.     }
  1035.     InterlockedExchange(&DeviceExtension->FlagWWCancel, 0);
  1036.     //
  1037.     // lowest state from which this Irp will wake the system
  1038.     //
  1039.     poState.SystemState = DeviceExtension->DeviceCapabilities.SystemWake;
  1040.     ntStatus = PoRequestPowerIrp(DeviceExtension->PhysicalDeviceObject, 
  1041.                                  IRP_MN_WAIT_WAKE,
  1042.                                  poState, 
  1043.                                  (PREQUEST_POWER_COMPLETE) WaitWakeCallback,
  1044.                                  DeviceExtension, 
  1045.                                  &DeviceExtension->WaitWakeIrp);
  1046.     if(!NT_SUCCESS(ntStatus)) {
  1047.         InterlockedExchange(&DeviceExtension->FlagWWOutstanding, 0);
  1048.     }
  1049.     IsoUsb_DbgPrint(3, ("IssueWaitWake - endsn"));
  1050.     return ntStatus;
  1051. }
  1052. VOID
  1053. CancelWaitWake(
  1054.     IN PDEVICE_EXTENSION DeviceExtension
  1055.     )
  1056. /*++
  1057. Routine Description:
  1058.     This routine cancels the Wait Wake request.
  1059. Arguments:
  1060.     DeviceExtension - pointer to the device extension
  1061. Return Value:
  1062.     None.
  1063. --*/
  1064. {
  1065.     PIRP Irp;
  1066.     IsoUsb_DbgPrint(3, ("CancelWaitWake - beginsn"));
  1067.     Irp = (PIRP) InterlockedExchangePointer(&DeviceExtension->WaitWakeIrp, 
  1068.                                             NULL);
  1069.     if(Irp) {
  1070.         IoCancelIrp(Irp);
  1071.         if(InterlockedExchange(&DeviceExtension->FlagWWCancel, 1)) {
  1072.             PoStartNextPowerIrp(Irp);
  1073.             Irp->IoStatus.Status = STATUS_CANCELLED;
  1074.             Irp->IoStatus.Information = 0;
  1075.             IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1076.         }    
  1077.     }
  1078.     IsoUsb_DbgPrint(3, ("CancelWaitWake - endsn"));
  1079. }
  1080. NTSTATUS
  1081. WaitWakeCompletionRoutine(
  1082.     IN PDEVICE_OBJECT DeviceObject,
  1083.     IN PIRP Irp,
  1084.     IN PDEVICE_EXTENSION DeviceExtension
  1085.     )
  1086. /*++
  1087.  
  1088. Routine Description:
  1089.     This is the IoSet completion routine for the wait wake irp.
  1090. Arguments:
  1091.     DeviceObject - pointer to device object
  1092.     Irp - I/O request packet
  1093.     DeviceExtension - pointer to device extension
  1094. Return Value:
  1095.     NT status value
  1096. --*/
  1097. {
  1098.     IsoUsb_DbgPrint(3, ("WaitWakeCompletionRoutine - beginsn"));
  1099.     if(Irp->PendingReturned) {
  1100.         IoMarkIrpPending(Irp);
  1101.     }
  1102.     //
  1103.     // Nullify the WaitWakeIrp pointer-the Irp is released 
  1104.     // as part of the completion process. If it's already NULL, 
  1105.     // avoid race with the CancelWaitWake routine.
  1106.     //
  1107.     if(InterlockedExchangePointer(&DeviceExtension->WaitWakeIrp, NULL)) {
  1108.         PoStartNextPowerIrp(Irp);
  1109.         return STATUS_SUCCESS;
  1110.     }
  1111.     //
  1112.     // CancelWaitWake has run. 
  1113.     // If FlagWWCancel != 0, complete the Irp.
  1114.     // If FlagWWCancel == 0, CancelWaitWake completes it.
  1115.     //
  1116.     if(InterlockedExchange(&DeviceExtension->FlagWWCancel, 1)) {
  1117.         PoStartNextPowerIrp(Irp);
  1118.         return STATUS_CANCELLED;
  1119.     }
  1120.     IsoUsb_DbgPrint(3, ("WaitWakeCompletionRoutine - endsn"));
  1121.     return STATUS_MORE_PROCESSING_REQUIRED;
  1122. }
  1123. VOID
  1124. WaitWakeCallback( 
  1125.     IN PDEVICE_OBJECT DeviceObject,
  1126.     IN UCHAR MinorFunction,
  1127.     IN POWER_STATE PowerState,
  1128.     IN PVOID Context,
  1129.     IN PIO_STATUS_BLOCK IoStatus
  1130.     )
  1131. /*++
  1132.  
  1133. Routine Description:
  1134.     This is the PoRequest completion routine for the wait wake irp.
  1135. Arguments:
  1136.     DeviceObject - pointer to device object
  1137.     MinorFunction - irp minor function
  1138.     PowerState - power state of the irp.
  1139.     Context - context passed to the completion routine.
  1140.     IoStatus - status block.
  1141. Return Value:
  1142.     None
  1143. --*/
  1144. {
  1145.     NTSTATUS               ntStatus;
  1146.     POWER_STATE            powerState;
  1147.     PDEVICE_EXTENSION      deviceExtension;
  1148.     IsoUsb_DbgPrint(3, ("WaitWakeCallback - beginsn"));
  1149.     deviceExtension = (PDEVICE_EXTENSION) Context;
  1150.     InterlockedExchange(&deviceExtension->FlagWWOutstanding, 0);
  1151.     if(!NT_SUCCESS(IoStatus->Status)) {
  1152.         return;
  1153.     }
  1154.     //
  1155.     // wake up the device
  1156.     //
  1157.     if(deviceExtension->DevPower == PowerDeviceD0) {
  1158.         IsoUsb_DbgPrint(3, ("device already powered up...n"));
  1159.         return;
  1160.     }
  1161.     IsoUsb_DbgPrint(3, ("WaitWakeCallback::"));
  1162.     IsoUsb_IoIncrement(deviceExtension);
  1163.     powerState.DeviceState = PowerDeviceD0;
  1164.     ntStatus = PoRequestPowerIrp(deviceExtension->PhysicalDeviceObject, 
  1165.                                  IRP_MN_SET_POWER, 
  1166.                                  powerState, 
  1167.                                  (PREQUEST_POWER_COMPLETE) WWIrpCompletionFunc,
  1168.                                  deviceExtension, 
  1169.                                  NULL);
  1170.     if(deviceExtension->WaitWakeEnable) {
  1171.     
  1172.         IssueWaitWake(deviceExtension);
  1173.     }
  1174.     IsoUsb_DbgPrint(3, ("WaitWakeCallback - endsn"));
  1175.     return;
  1176. }
  1177. PCHAR
  1178. PowerMinorFunctionString (
  1179.     IN UCHAR MinorFunction
  1180.     )
  1181. /*++
  1182.  
  1183. Routine Description:
  1184. Arguments:
  1185. Return Value:
  1186. --*/
  1187. {
  1188.     switch (MinorFunction) {
  1189.         case IRP_MN_SET_POWER:
  1190.             return "IRP_MN_SET_POWERn";
  1191.         case IRP_MN_QUERY_POWER:
  1192.             return "IRP_MN_QUERY_POWERn";
  1193.         case IRP_MN_POWER_SEQUENCE:
  1194.             return "IRP_MN_POWER_SEQUENCEn";
  1195.         case IRP_MN_WAIT_WAKE:
  1196.             return "IRP_MN_WAIT_WAKEn";
  1197.         default:
  1198.             return "IRP_MN_?????n";
  1199.     }
  1200. }