ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

fbtpwr.c
Go to the documentation of this file.
00001 // Copyright (c) 2004, Antony C. Roberts
00002 
00003 // Use of this file is subject to the terms
00004 // described in the LICENSE.TXT file that
00005 // accompanies this file.
00006 //
00007 // Your use of this file indicates your
00008 // acceptance of the terms described in
00009 // LICENSE.TXT.
00010 //
00011 // http://www.freebt.net
00012 
00013 #include "fbtusb.h"
00014 #include "fbtpwr.h"
00015 #include "fbtpnp.h"
00016 #include "fbtdev.h"
00017 #include "fbtrwr.h"
00018 #include "fbtwmi.h"
00019 
00020 #include "fbtusr.h"
00021 
00022 // Handle power events
00023 NTSTATUS FreeBT_DispatchPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
00024 {
00025     NTSTATUS           ntStatus = STATUS_SUCCESS;
00026     PIO_STACK_LOCATION irpStack;
00027     //PUNICODE_STRING    tagString;
00028     PDEVICE_EXTENSION  deviceExtension;
00029 
00030     irpStack = IoGetCurrentIrpStackLocation(Irp);
00031     deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
00032 
00033     // We don't queue power Irps, we'll only check if the
00034     // device was removed, otherwise we'll take appropriate
00035     // action and send it to the next lower driver. In general
00036     // drivers should not cause long delays while handling power
00037     // IRPs. If a driver cannot handle a power IRP in a brief time,
00038     // it should return STATUS_PENDING and queue all incoming
00039     // IRPs until the IRP completes.
00040     if (Removed == deviceExtension->DeviceState)
00041     {
00042 
00043         // Even if a driver fails the IRP, it must nevertheless call
00044         // PoStartNextPowerIrp to inform the Power Manager that it
00045         // is ready to handle another power IRP.
00046         PoStartNextPowerIrp(Irp);
00047         Irp->IoStatus.Status = ntStatus = STATUS_DELETE_PENDING;
00048         Irp->IoStatus.Information = 0;
00049         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00050 
00051         return ntStatus;
00052 
00053     }
00054 
00055     if (NotStarted == deviceExtension->DeviceState)
00056     {
00057         // if the device is not started yet, pass it down
00058         PoStartNextPowerIrp(Irp);
00059         IoSkipCurrentIrpStackLocation(Irp);
00060 
00061         return PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
00062 
00063     }
00064 
00065     FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower::"));
00066     FreeBT_IoIncrement(deviceExtension);
00067 
00068     switch(irpStack->MinorFunction)
00069     {
00070     case IRP_MN_SET_POWER:
00071         // The Power Manager sends this IRP for one of the
00072         // following reasons:
00073 
00074         // 1) To notify drivers of a change to the system power state.
00075         // 2) To change the power state of a device for which
00076         //    the Power Manager is performing idle detection.
00077 
00078         // A driver sends IRP_MN_SET_POWER to change the power
00079         // state of its device if it's a power policy owner for the
00080         // device.
00081         FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_SET_POWER\n"));
00082         IoMarkIrpPending(Irp);
00083 
00084         switch(irpStack->Parameters.Power.Type)
00085         {
00086         case SystemPowerState:
00087             HandleSystemSetPower(DeviceObject, Irp);
00088             ntStatus = STATUS_PENDING;
00089             break;
00090 
00091         case DevicePowerState:
00092             HandleDeviceSetPower(DeviceObject, Irp);
00093             ntStatus = STATUS_PENDING;
00094             break;
00095 
00096         }
00097 
00098         break;
00099 
00100     case IRP_MN_QUERY_POWER:
00101         // The Power Manager sends a power IRP with the minor
00102         // IRP code IRP_MN_QUERY_POWER to determine whether it
00103         // can safely change to the specified system power state
00104         // (S1-S5) and to allow drivers to prepare for such a change.
00105         // If a driver can put its device in the requested state,
00106         // it sets status to STATUS_SUCCESS and passes the IRP down.
00107         FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_QUERY_POWER\n"));
00108         IoMarkIrpPending(Irp);
00109 
00110         switch(irpStack->Parameters.Power.Type)
00111         {
00112         case SystemPowerState:
00113             HandleSystemQueryPower(DeviceObject, Irp);
00114             ntStatus = STATUS_PENDING;
00115             break;
00116 
00117         case DevicePowerState:
00118             HandleDeviceQueryPower(DeviceObject, Irp);
00119             ntStatus = STATUS_PENDING;
00120             break;
00121 
00122         }
00123 
00124         break;
00125 
00126     case IRP_MN_WAIT_WAKE:
00127         // The minor power IRP code IRP_MN_WAIT_WAKE provides
00128         // for waking a device or waking the system. Drivers
00129         // of devices that can wake themselves or the system
00130         // send IRP_MN_WAIT_WAKE. The system sends IRP_MN_WAIT_WAKE
00131         // only to devices that always wake the system, such as
00132         // the power-on switch.
00133         FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_WAIT_WAKE\n"));
00134         IoMarkIrpPending(Irp);
00135         IoCopyCurrentIrpStackLocationToNext(Irp);
00136         IoSetCompletionRoutine(
00137                         Irp,
00138                         (PIO_COMPLETION_ROUTINE)WaitWakeCompletionRoutine,
00139                         deviceExtension,
00140                         TRUE,
00141                         TRUE,
00142                         TRUE);
00143 
00144         PoStartNextPowerIrp(Irp);
00145         ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
00146         if(!NT_SUCCESS(ntStatus))
00147         {
00148             FreeBT_DbgPrint(1, ("FBTUSB: Lower drivers failed the wait-wake Irp\n"));
00149 
00150         }
00151 
00152         ntStatus = STATUS_PENDING;
00153 
00154         // push back the count HERE and NOT in completion routine
00155         // a pending Wait Wake Irp should not impede stopping the device
00156         FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_WAIT_WAKE::"));
00157         FreeBT_IoDecrement(deviceExtension);
00158         break;
00159 
00160     case IRP_MN_POWER_SEQUENCE:
00161         // A driver sends this IRP as an optimization to determine
00162         // whether its device actually entered a specific power state.
00163         // This IRP is optional. Power Manager cannot send this IRP.
00164         FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower: IRP_MN_POWER_SEQUENCE\n"));
00165 
00166     default:
00167         PoStartNextPowerIrp(Irp);
00168         IoSkipCurrentIrpStackLocation(Irp);
00169         ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
00170         if(!NT_SUCCESS(ntStatus))
00171         {
00172             FreeBT_DbgPrint(1, ("FBTUSB: FreeBT_DispatchPower: Lower drivers failed this Irp\n"));
00173 
00174         }
00175 
00176         FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchPower::"));
00177         FreeBT_IoDecrement(deviceExtension);
00178 
00179         break;
00180 
00181     }
00182 
00183     return ntStatus;
00184 
00185 }
00186 
00187 NTSTATUS HandleSystemQueryPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
00188 {
00189     NTSTATUS           ntStatus;
00190     PDEVICE_EXTENSION  deviceExtension;
00191     SYSTEM_POWER_STATE systemState;
00192     PIO_STACK_LOCATION irpStack;
00193 
00194     FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemQueryPower: Entered\n"));
00195 
00196     // initialize variables
00197     deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
00198     irpStack = IoGetCurrentIrpStackLocation(Irp);
00199     systemState = irpStack->Parameters.Power.State.SystemState;
00200 
00201     FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemQueryPower: Query for system power state S%X\n"
00202                         "FBTUSB: HandleSystemQueryPower: Current system power state S%X\n",
00203                          systemState - 1,
00204                          deviceExtension->SysPower - 1));
00205 
00206     // Fail a query for a power state incompatible with waking up the system
00207     if ((deviceExtension->WaitWakeEnable) && (systemState > deviceExtension->DeviceCapabilities.SystemWake))
00208     {
00209         FreeBT_DbgPrint(1, ("FBTUSB: HandleSystemQueryPower: Query for an incompatible system power state\n"));
00210 
00211         PoStartNextPowerIrp(Irp);
00212         Irp->IoStatus.Status = ntStatus = STATUS_INVALID_DEVICE_STATE;
00213         Irp->IoStatus.Information = 0;
00214         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00215 
00216         FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemQueryPower::"));
00217         FreeBT_IoDecrement(deviceExtension);
00218 
00219         return ntStatus;
00220 
00221     }
00222 
00223     // if querying for a lower S-state, issue a wait-wake
00224     if((systemState > deviceExtension->SysPower) && (deviceExtension->WaitWakeEnable))
00225     {
00226         IssueWaitWake(deviceExtension);
00227 
00228     }
00229 
00230     IoCopyCurrentIrpStackLocationToNext(Irp);
00231     IoSetCompletionRoutine(
00232             Irp,
00233             (PIO_COMPLETION_ROUTINE)SysPoCompletionRoutine,
00234             deviceExtension,
00235             TRUE,
00236             TRUE,
00237             TRUE);
00238 
00239     ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
00240     FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemQueryPower: Leaving\n"));
00241 
00242     return STATUS_PENDING;
00243 
00244 }
00245 
00246 NTSTATUS HandleSystemSetPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
00247 {
00248     NTSTATUS           ntStatus;
00249     PDEVICE_EXTENSION  deviceExtension;
00250     SYSTEM_POWER_STATE systemState;
00251     PIO_STACK_LOCATION irpStack;
00252 
00253     FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemSetPower: Entered\n"));
00254 
00255     deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
00256     irpStack = IoGetCurrentIrpStackLocation(Irp);
00257     systemState = irpStack->Parameters.Power.State.SystemState;
00258 
00259     FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemSetPower: Set request for system power state S%X\n"
00260                          "FBTUSB: HandleSystemSetPower: Current system power state S%X\n",
00261                          systemState - 1,
00262                          deviceExtension->SysPower - 1));
00263 
00264     IoCopyCurrentIrpStackLocationToNext(Irp);
00265     IoSetCompletionRoutine(
00266             Irp,
00267             (PIO_COMPLETION_ROUTINE)SysPoCompletionRoutine,
00268             deviceExtension,
00269             TRUE,
00270             TRUE,
00271             TRUE);
00272 
00273     ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
00274     FreeBT_DbgPrint(3, ("FBTUSB: HandleSystemSetPower: Leaving\n"));
00275 
00276     return STATUS_PENDING;
00277 
00278 }
00279 
00280 NTSTATUS HandleDeviceQueryPower(PDEVICE_OBJECT DeviceObject, PIRP Irp)
00281 {
00282     NTSTATUS           ntStatus;
00283     PDEVICE_EXTENSION  deviceExtension;
00284     PIO_STACK_LOCATION irpStack;
00285     DEVICE_POWER_STATE deviceState;
00286 
00287     FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceQueryPower: Entered\n"));
00288 
00289     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
00290     irpStack = IoGetCurrentIrpStackLocation(Irp);
00291     deviceState = irpStack->Parameters.Power.State.DeviceState;
00292 
00293     FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceQueryPower: Query for device power state D%X\n"
00294                          "FBTUSB: HandleDeviceQueryPower: Current device power state D%X\n",
00295                          deviceState - 1,
00296                          deviceExtension->DevPower - 1));
00297 
00298     if (deviceExtension->WaitWakeEnable && deviceState > deviceExtension->DeviceCapabilities.DeviceWake)
00299     {
00300         PoStartNextPowerIrp(Irp);
00301         Irp->IoStatus.Status = ntStatus = STATUS_INVALID_DEVICE_STATE;
00302         Irp->IoStatus.Information = 0;
00303         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00304 
00305         FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceQueryPower::"));
00306         FreeBT_IoDecrement(deviceExtension);
00307 
00308         return ntStatus;
00309 
00310     }
00311 
00312     if (deviceState < deviceExtension->DevPower)
00313     {
00314         ntStatus = STATUS_SUCCESS;
00315 
00316     }
00317 
00318     else
00319     {
00320         ntStatus = HoldIoRequests(DeviceObject, Irp);
00321         if(STATUS_PENDING == ntStatus)
00322         {
00323             return ntStatus;
00324 
00325         }
00326 
00327     }
00328 
00329     // on error complete the Irp.
00330     // on success pass it to the lower layers
00331     PoStartNextPowerIrp(Irp);
00332     Irp->IoStatus.Status = ntStatus;
00333     Irp->IoStatus.Information = 0;
00334     if(!NT_SUCCESS(ntStatus))
00335     {
00336         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00337 
00338     }
00339 
00340     else
00341     {
00342         IoSkipCurrentIrpStackLocation(Irp);
00343         ntStatus=PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
00344 
00345     }
00346 
00347     FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceQueryPower::"));
00348     FreeBT_IoDecrement(deviceExtension);
00349 
00350     FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceQueryPower: Leaving\n"));
00351 
00352     return ntStatus;
00353 
00354 }
00355 
00356 
00357 NTSTATUS SysPoCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
00358 {
00359     NTSTATUS           ntStatus;
00360     PIO_STACK_LOCATION irpStack;
00361 
00362     ntStatus = Irp->IoStatus.Status;
00363     irpStack = IoGetCurrentIrpStackLocation(Irp);
00364 
00365     FreeBT_DbgPrint(3, ("FBTUSB: SysPoCompletionRoutine: Entered\n"));
00366 
00367     // lower drivers failed this Irp
00368     if(!NT_SUCCESS(ntStatus))
00369     {
00370         PoStartNextPowerIrp(Irp);
00371         FreeBT_DbgPrint(3, ("FBTUSB: SysPoCompletionRoutine::"));
00372         FreeBT_IoDecrement(DeviceExtension);
00373 
00374         return STATUS_SUCCESS;
00375 
00376     }
00377 
00378     // ..otherwise update the cached system power state (IRP_MN_SET_POWER)
00379     if(irpStack->MinorFunction == IRP_MN_SET_POWER)
00380     {
00381         DeviceExtension->SysPower = irpStack->Parameters.Power.State.SystemState;
00382 
00383     }
00384 
00385     // queue device irp and return STATUS_MORE_PROCESSING_REQUIRED
00386     SendDeviceIrp(DeviceObject, Irp);
00387 
00388     FreeBT_DbgPrint(3, ("FBTUSB: SysPoCompletionRoutine: Leaving\n"));
00389 
00390     return STATUS_MORE_PROCESSING_REQUIRED;
00391 
00392 }
00393 
00394 VOID SendDeviceIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP SIrp )
00395 {
00396     NTSTATUS                  ntStatus;
00397     POWER_STATE               powState;
00398     PDEVICE_EXTENSION         deviceExtension;
00399     PIO_STACK_LOCATION        irpStack;
00400     SYSTEM_POWER_STATE        systemState;
00401     DEVICE_POWER_STATE        devState;
00402     PPOWER_COMPLETION_CONTEXT powerContext;
00403 
00404     irpStack = IoGetCurrentIrpStackLocation(SIrp);
00405     systemState = irpStack->Parameters.Power.State.SystemState;
00406     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
00407 
00408     FreeBT_DbgPrint(3, ("FBTUSB: SendDeviceIrp: Entered\n"));
00409 
00410     // Read out the D-IRP out of the S->D mapping array captured in QueryCap's.
00411     // we can choose deeper sleep states than our mapping but never choose
00412     // lighter ones.
00413     devState = deviceExtension->DeviceCapabilities.DeviceState[systemState];
00414     powState.DeviceState = devState;
00415 
00416     powerContext = (PPOWER_COMPLETION_CONTEXT) ExAllocatePool(NonPagedPool, sizeof(POWER_COMPLETION_CONTEXT));
00417     if (!powerContext)
00418     {
00419         FreeBT_DbgPrint(1, ("FBTUSB: SendDeviceIrp: Failed to alloc memory for powerContext\n"));
00420         ntStatus = STATUS_INSUFFICIENT_RESOURCES;
00421 
00422     }
00423 
00424     else
00425     {
00426         powerContext->DeviceObject = DeviceObject;
00427         powerContext->SIrp = SIrp;
00428 
00429         // in win2k PoRequestPowerIrp can take fdo or pdo.
00430         ntStatus = PoRequestPowerIrp(
00431                             deviceExtension->PhysicalDeviceObject,
00432                             irpStack->MinorFunction,
00433                             powState,
00434                             (PREQUEST_POWER_COMPLETE)DevPoCompletionRoutine,
00435                             powerContext,
00436                             NULL);
00437 
00438     }
00439 
00440     if (!NT_SUCCESS(ntStatus))
00441     {
00442         if (powerContext)
00443         {
00444             ExFreePool(powerContext);
00445 
00446         }
00447 
00448         PoStartNextPowerIrp(SIrp);
00449         SIrp->IoStatus.Status = ntStatus;
00450         SIrp->IoStatus.Information = 0;
00451         IoCompleteRequest(SIrp, IO_NO_INCREMENT);
00452 
00453         FreeBT_DbgPrint(3, ("FBTUSB: SendDeviceIrp::"));
00454         FreeBT_IoDecrement(deviceExtension);
00455 
00456     }
00457 
00458     FreeBT_DbgPrint(3, ("FBTUSB: SendDeviceIrp: Leaving\n"));
00459 
00460 }
00461 
00462 
00463 VOID DevPoCompletionRoutine(
00464     IN PDEVICE_OBJECT DeviceObject,
00465     IN UCHAR MinorFunction,
00466     IN POWER_STATE PowerState,
00467     IN PVOID Context,
00468     IN PIO_STATUS_BLOCK IoStatus
00469     )
00470 {
00471     PIRP                      sIrp;
00472     PDEVICE_EXTENSION         deviceExtension;
00473     PPOWER_COMPLETION_CONTEXT powerContext;
00474 
00475     powerContext = (PPOWER_COMPLETION_CONTEXT) Context;
00476     sIrp = powerContext->SIrp;
00477     deviceExtension = (PDEVICE_EXTENSION) powerContext->DeviceObject->DeviceExtension;
00478 
00479     FreeBT_DbgPrint(3, ("FBTUSB: DevPoCompletionRoutine: Entered\n"));
00480 
00481     sIrp->IoStatus.Status = IoStatus->Status;
00482     PoStartNextPowerIrp(sIrp);
00483     sIrp->IoStatus.Information = 0;
00484     IoCompleteRequest(sIrp, IO_NO_INCREMENT);
00485 
00486     FreeBT_DbgPrint(3, ("FBTUSB: DevPoCompletionRoutine::"));
00487     FreeBT_IoDecrement(deviceExtension);
00488 
00489     ExFreePool(powerContext);
00490 
00491     FreeBT_DbgPrint(3, ("FBTUSB: DevPoCompletionRoutine: Leaving\n"));
00492 
00493 }
00494 
00495 NTSTATUS HandleDeviceSetPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
00496 {
00497     KIRQL              oldIrql;
00498     NTSTATUS           ntStatus;
00499     POWER_STATE        newState;
00500     PIO_STACK_LOCATION irpStack;
00501     PDEVICE_EXTENSION  deviceExtension;
00502     DEVICE_POWER_STATE newDevState,
00503                        oldDevState;
00504 
00505     FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Entered\n"));
00506 
00507     deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
00508     irpStack = IoGetCurrentIrpStackLocation(Irp);
00509     oldDevState = deviceExtension->DevPower;
00510     newState = irpStack->Parameters.Power.State;
00511     newDevState = newState.DeviceState;
00512 
00513     FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Set request for device power state D%X\n"
00514                          "FBTUSB: HandleDeviceSetPower: Current device power state D%X\n",
00515                          newDevState - 1,
00516                          deviceExtension->DevPower - 1));
00517 
00518     if (newDevState < oldDevState)
00519     {
00520 
00521         FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Adding power to the device\n"));
00522 
00523         IoCopyCurrentIrpStackLocationToNext(Irp);
00524         IoSetCompletionRoutine(
00525                 Irp,
00526                 (PIO_COMPLETION_ROUTINE)FinishDevPoUpIrp,
00527                 deviceExtension,
00528                 TRUE,
00529                 TRUE,
00530                 TRUE);
00531 
00532         ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
00533 
00534     }
00535 
00536     else
00537     {
00538         // newDevState >= oldDevState
00539 
00540         // hold I/O if transition from D0 -> DX (X = 1, 2, 3)
00541         // if transition from D1 or D2 to deeper sleep states,
00542         // I/O queue is already on hold.
00543         if(PowerDeviceD0 == oldDevState && newDevState > oldDevState)
00544         {
00545             // D0 -> DX transition
00546             FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Removing power from the device\n"));
00547 
00548             ntStatus = HoldIoRequests(DeviceObject, Irp);
00549             if (!NT_SUCCESS(ntStatus))
00550             {
00551                 PoStartNextPowerIrp(Irp);
00552                 Irp->IoStatus.Status = ntStatus;
00553                 Irp->IoStatus.Information = 0;
00554                 IoCompleteRequest(Irp, IO_NO_INCREMENT);
00555 
00556                 FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower::"));
00557                 FreeBT_IoDecrement(deviceExtension);
00558 
00559                 return ntStatus;
00560 
00561             }
00562 
00563             else
00564             {
00565                 goto HandleDeviceSetPower_Exit;
00566 
00567             }
00568 
00569         }
00570 
00571         else if (PowerDeviceD0 == oldDevState && PowerDeviceD0 == newDevState)
00572         {
00573             // D0 -> D0
00574             // unblock the queue which may have been blocked processing
00575             // query irp
00576             FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: A SetD0 request\n"));
00577 
00578             KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
00579             deviceExtension->QueueState = AllowRequests;
00580             KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
00581 
00582             ProcessQueuedRequests(deviceExtension);
00583 
00584         }
00585 
00586         IoCopyCurrentIrpStackLocationToNext(Irp);
00587         IoSetCompletionRoutine(
00588                 Irp,
00589                 (PIO_COMPLETION_ROUTINE) FinishDevPoDnIrp,
00590                 deviceExtension,
00591                 TRUE,
00592                 TRUE,
00593                 TRUE);
00594 
00595         ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
00596         if(!NT_SUCCESS(ntStatus))
00597         {
00598             FreeBT_DbgPrint(1, ("FBTUSB: HandleDeviceSetPower: Lower drivers failed a power Irp\n"));
00599 
00600         }
00601 
00602     }
00603 
00604 HandleDeviceSetPower_Exit:
00605 
00606     FreeBT_DbgPrint(3, ("FBTUSB: HandleDeviceSetPower: Leaving\n"));
00607 
00608     return STATUS_PENDING;
00609 
00610 }
00611 
00612 NTSTATUS FinishDevPoUpIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
00613 {
00614     NTSTATUS           ntStatus;
00615 
00616     FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoUpIrp: Entered\n"));
00617 
00618     ntStatus = Irp->IoStatus.Status;
00619     if(Irp->PendingReturned)
00620     {
00621         IoMarkIrpPending(Irp);
00622 
00623     }
00624 
00625     if(!NT_SUCCESS(ntStatus))
00626     {
00627         PoStartNextPowerIrp(Irp);
00628 
00629         FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoUpIrp::"));
00630         FreeBT_IoDecrement(DeviceExtension);
00631 
00632         return STATUS_SUCCESS;
00633 
00634     }
00635 
00636     SetDeviceFunctional(DeviceObject, Irp, DeviceExtension);
00637 
00638     FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoUpIrp: Leaving\n"));
00639 
00640     return STATUS_MORE_PROCESSING_REQUIRED;
00641 
00642 }
00643 
00644 NTSTATUS SetDeviceFunctional(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
00645 {
00646     KIRQL              oldIrql;
00647     NTSTATUS           ntStatus;
00648     POWER_STATE        newState;
00649     PIO_STACK_LOCATION irpStack;
00650     DEVICE_POWER_STATE newDevState, oldDevState;
00651 
00652     ntStatus = Irp->IoStatus.Status;
00653     irpStack = IoGetCurrentIrpStackLocation(Irp);
00654     newState = irpStack->Parameters.Power.State;
00655     newDevState = newState.DeviceState;
00656     oldDevState = DeviceExtension->DevPower;
00657 
00658     FreeBT_DbgPrint(3, ("FBTUSB: SetDeviceFunctional: Entered\n"));
00659 
00660     // update the cached state
00661     DeviceExtension->DevPower = newDevState;
00662 
00663     // restore appropriate amount of state to our h/w
00664     // this driver does not implement partial context
00665     // save/restore.
00666     PoSetPowerState(DeviceObject, DevicePowerState, newState);
00667     if(PowerDeviceD0 == newDevState)
00668     {
00669         KeAcquireSpinLock(&DeviceExtension->DevStateLock, &oldIrql);
00670         DeviceExtension->QueueState = AllowRequests;
00671         KeReleaseSpinLock(&DeviceExtension->DevStateLock, oldIrql);
00672 
00673         ProcessQueuedRequests(DeviceExtension);
00674 
00675     }
00676 
00677     PoStartNextPowerIrp(Irp);
00678     Irp->IoStatus.Status = STATUS_SUCCESS;
00679     Irp->IoStatus.Information = 0;
00680     IoCompleteRequest(Irp, IO_NO_INCREMENT);
00681 
00682     FreeBT_DbgPrint(3, ("FBTUSB: SetDeviceFunctional::"));
00683     FreeBT_IoDecrement(DeviceExtension);
00684 
00685     FreeBT_DbgPrint(3, ("FBTUSB: SetDeviceFunctional: Leaving\n"));
00686 
00687     return STATUS_SUCCESS;
00688 
00689 }
00690 
00691 NTSTATUS FinishDevPoDnIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
00692 {
00693     NTSTATUS           ntStatus;
00694     POWER_STATE        newState;
00695     PIO_STACK_LOCATION irpStack;
00696 
00697     FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoDnIrp: Entered\n"));
00698 
00699     ntStatus = Irp->IoStatus.Status;
00700     irpStack = IoGetCurrentIrpStackLocation(Irp);
00701     newState = irpStack->Parameters.Power.State;
00702 
00703     if (NT_SUCCESS(ntStatus) && irpStack->MinorFunction == IRP_MN_SET_POWER)
00704     {
00705         FreeBT_DbgPrint(3, ("FBTUSB: updating cache..\n"));
00706         DeviceExtension->DevPower = newState.DeviceState;
00707         PoSetPowerState(DeviceObject, DevicePowerState, newState);
00708 
00709     }
00710 
00711     PoStartNextPowerIrp(Irp);
00712 
00713     FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoDnIrp::"));
00714     FreeBT_IoDecrement(DeviceExtension);
00715 
00716     FreeBT_DbgPrint(3, ("FBTUSB: FinishDevPoDnIrp: Leaving\n"));
00717 
00718     return STATUS_SUCCESS;
00719 
00720 }
00721 
00722 NTSTATUS HoldIoRequests(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
00723 
00724 {
00725     NTSTATUS               ntStatus;
00726     PIO_WORKITEM           item;
00727     PDEVICE_EXTENSION      deviceExtension;
00728     PWORKER_THREAD_CONTEXT context;
00729 
00730     FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequests: Entered\n"));
00731 
00732     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
00733     deviceExtension->QueueState = HoldRequests;
00734 
00735     context = (PWORKER_THREAD_CONTEXT) ExAllocatePool(NonPagedPool, sizeof(WORKER_THREAD_CONTEXT));
00736     if(context)
00737     {
00738         item = IoAllocateWorkItem(DeviceObject);
00739 
00740         context->Irp = Irp;
00741         context->DeviceObject = DeviceObject;
00742         context->WorkItem = item;
00743 
00744         if (item)
00745         {
00746             IoMarkIrpPending(Irp);
00747             IoQueueWorkItem(item, HoldIoRequestsWorkerRoutine, DelayedWorkQueue, context);
00748             ntStatus = STATUS_PENDING;
00749 
00750         }
00751 
00752         else
00753         {
00754             FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequests: Failed to allocate memory for workitem\n"));
00755             ExFreePool(context);
00756             ntStatus = STATUS_INSUFFICIENT_RESOURCES;
00757 
00758         }
00759 
00760     }
00761 
00762     else
00763     {
00764         FreeBT_DbgPrint(1, ("FBTUSB: HoldIoRequests: Failed to alloc memory for worker thread context\n"));
00765         ntStatus = STATUS_INSUFFICIENT_RESOURCES;
00766 
00767     }
00768 
00769     FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequests: Leaving\n"));
00770 
00771     return ntStatus;
00772 
00773 }
00774 
00775 VOID HoldIoRequestsWorkerRoutine(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context)
00776 {
00777     PIRP                   irp;
00778     NTSTATUS               ntStatus;
00779     PDEVICE_EXTENSION      deviceExtension;
00780     PWORKER_THREAD_CONTEXT context;
00781 
00782     FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequestsWorkerRoutine: Entered\n"));
00783 
00784     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
00785     context = (PWORKER_THREAD_CONTEXT) Context;
00786     irp = (PIRP) context->Irp;
00787 
00788     // wait for I/O in progress to finish.
00789     // the stop event is signalled when the counter drops to 1.
00790     // invoke FreeBT_IoDecrement twice: once each for the S-Irp and D-Irp.
00791     FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequestsWorkerRoutine::"));
00792     FreeBT_IoDecrement(deviceExtension);
00793 
00794     FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequestsWorkerRoutine::"));
00795     FreeBT_IoDecrement(deviceExtension);
00796 
00797     KeWaitForSingleObject(&deviceExtension->StopEvent, Executive, KernelMode, FALSE, NULL);
00798 
00799     // Increment twice to restore the count
00800     FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequestsWorkerRoutine::"));
00801     FreeBT_IoIncrement(deviceExtension);
00802 
00803     FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequestsWorkerRoutine::"));
00804     FreeBT_IoIncrement(deviceExtension);
00805 
00806     // now send the Irp down
00807     IoCopyCurrentIrpStackLocationToNext(irp);
00808     IoSetCompletionRoutine(
00809         irp,
00810         (PIO_COMPLETION_ROUTINE) FinishDevPoDnIrp,
00811         deviceExtension,
00812         TRUE,
00813         TRUE,
00814         TRUE);
00815 
00816     ntStatus = PoCallDriver(deviceExtension->TopOfStackDeviceObject, irp);
00817     if(!NT_SUCCESS(ntStatus))
00818     {
00819         FreeBT_DbgPrint(1, ("FBTUSB: HoldIoRequestsWorkerRoutine: Lower driver fail a power Irp\n"));
00820 
00821     }
00822 
00823     IoFreeWorkItem(context->WorkItem);
00824     ExFreePool((PVOID)context);
00825 
00826     FreeBT_DbgPrint(3, ("FBTUSB: HoldIoRequestsWorkerRoutine: Leaving\n"));
00827 
00828 }
00829 
00830 NTSTATUS QueueRequest(IN OUT PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp)
00831 {
00832     KIRQL    oldIrql;
00833     NTSTATUS ntStatus;
00834 
00835     FreeBT_DbgPrint(3, ("FBTUSB: QueueRequests: Entered\n"));
00836 
00837     ntStatus = STATUS_PENDING;
00838 
00839     ASSERT(HoldRequests == DeviceExtension->QueueState);
00840 
00841     KeAcquireSpinLock(&DeviceExtension->QueueLock, &oldIrql);
00842 
00843     InsertTailList(&DeviceExtension->NewRequestsQueue, &Irp->Tail.Overlay.ListEntry);
00844     IoMarkIrpPending(Irp);
00845     IoSetCancelRoutine(Irp, CancelQueued);
00846 
00847     KeReleaseSpinLock(&DeviceExtension->QueueLock, oldIrql);
00848 
00849     FreeBT_DbgPrint(3, ("FBTUSB: QueueRequests: Leaving\n"));
00850 
00851     return ntStatus;
00852 
00853 }
00854 
00855 VOID CancelQueued(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
00856 {
00857     PDEVICE_EXTENSION deviceExtension;
00858     KIRQL             oldIrql;
00859 
00860     FreeBT_DbgPrint(3, ("FBTUSB: CancelQueued: Entered\n"));
00861 
00862     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
00863     oldIrql = Irp->CancelIrql;
00864 
00865     // Release the cancel spin lock
00866     IoReleaseCancelSpinLock(Irp->CancelIrql);
00867 
00868     // Acquire the queue lock
00869     KeAcquireSpinLockAtDpcLevel(&deviceExtension->QueueLock);
00870 
00871     // Remove the cancelled Irp from queue and release the lock
00872     RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
00873 
00874     KeReleaseSpinLock(&deviceExtension->QueueLock, oldIrql);
00875 
00876     // complete with STATUS_CANCELLED
00877     Irp->IoStatus.Status = STATUS_CANCELLED;
00878     Irp->IoStatus.Information = 0;
00879     IoCompleteRequest(Irp, IO_NO_INCREMENT);
00880 
00881     FreeBT_DbgPrint(3, ("FBTUSB: CancelQueued: Leaving\n"));
00882 
00883     return;
00884 
00885 }
00886 
00887 NTSTATUS IssueWaitWake(IN PDEVICE_EXTENSION DeviceExtension)
00888 {
00889     POWER_STATE poState;
00890     NTSTATUS    ntStatus;
00891 
00892     FreeBT_DbgPrint(3, ("FBTUSB: IssueWaitWake: Entered\n"));
00893 
00894     if(InterlockedExchange(&DeviceExtension->FlagWWOutstanding, 1))
00895     {
00896         return STATUS_DEVICE_BUSY;
00897 
00898     }
00899 
00900     InterlockedExchange(&DeviceExtension->FlagWWCancel, 0);
00901 
00902     // lowest state from which this Irp will wake the system
00903     poState.SystemState = DeviceExtension->DeviceCapabilities.SystemWake;
00904     ntStatus = PoRequestPowerIrp(DeviceExtension->PhysicalDeviceObject,
00905                                  IRP_MN_WAIT_WAKE,
00906                                  poState,
00907                                  (PREQUEST_POWER_COMPLETE) WaitWakeCallback,
00908                                  DeviceExtension,
00909                                  &DeviceExtension->WaitWakeIrp);
00910 
00911     if(!NT_SUCCESS(ntStatus))
00912     {
00913         InterlockedExchange(&DeviceExtension->FlagWWOutstanding, 0);
00914 
00915     }
00916 
00917     FreeBT_DbgPrint(3, ("FBTUSB: IssueWaitWake: Leaving\n"));
00918 
00919     return ntStatus;
00920 
00921 }
00922 
00923 VOID CancelWaitWake(IN PDEVICE_EXTENSION DeviceExtension)
00924 {
00925     PIRP Irp;
00926 
00927     FreeBT_DbgPrint(3, ("FBTUSB: CancelWaitWake: Entered\n"));
00928 
00929     Irp = (PIRP) InterlockedExchangePointer(&DeviceExtension->WaitWakeIrp, NULL);
00930     if(Irp)
00931     {
00932         IoCancelIrp(Irp);
00933         if(InterlockedExchange(&DeviceExtension->FlagWWCancel, 1))
00934         {
00935             PoStartNextPowerIrp(Irp);
00936             Irp->IoStatus.Status = STATUS_CANCELLED;
00937             Irp->IoStatus.Information = 0;
00938             IoCompleteRequest(Irp, IO_NO_INCREMENT);
00939 
00940         }
00941 
00942     }
00943 
00944     FreeBT_DbgPrint(3, ("FBTUSB: CancelWaitWake: Leaving\n"));
00945 
00946 }
00947 
00948 NTSTATUS WaitWakeCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PDEVICE_EXTENSION DeviceExtension)
00949 {
00950     FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCompletionRoutine: Entered\n"));
00951     if(Irp->PendingReturned)
00952     {
00953         IoMarkIrpPending(Irp);
00954 
00955     }
00956 
00957     // Nullify the WaitWakeIrp pointer-the Irp is released
00958     // as part of the completion process. If it's already NULL,
00959     // avoid race with the CancelWaitWake routine.
00960     if(InterlockedExchangePointer(&DeviceExtension->WaitWakeIrp, NULL))
00961     {
00962         PoStartNextPowerIrp(Irp);
00963 
00964         return STATUS_SUCCESS;
00965 
00966     }
00967 
00968     // CancelWaitWake has run.
00969     // If FlagWWCancel != 0, complete the Irp.
00970     // If FlagWWCancel == 0, CancelWaitWake completes it.
00971     if(InterlockedExchange(&DeviceExtension->FlagWWCancel, 1))
00972     {
00973         PoStartNextPowerIrp(Irp);
00974 
00975         return STATUS_CANCELLED;
00976 
00977     }
00978 
00979     FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCompletionRoutine: Leaving\n"));
00980 
00981     return STATUS_MORE_PROCESSING_REQUIRED;
00982 
00983 }
00984 
00985 VOID WaitWakeCallback(
00986     IN PDEVICE_OBJECT DeviceObject,
00987     IN UCHAR MinorFunction,
00988     IN POWER_STATE PowerState,
00989     IN PVOID Context,
00990     IN PIO_STATUS_BLOCK IoStatus)
00991 {
00992     NTSTATUS               ntStatus;
00993     POWER_STATE            powerState;
00994     PDEVICE_EXTENSION      deviceExtension;
00995 
00996     FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCallback: Entered\n"));
00997 
00998     deviceExtension = (PDEVICE_EXTENSION) Context;
00999 
01000     InterlockedExchange(&deviceExtension->FlagWWOutstanding, 0);
01001 
01002     if(!NT_SUCCESS(IoStatus->Status))
01003     {
01004         return;
01005 
01006     }
01007 
01008     // wake up the device
01009     if(deviceExtension->DevPower == PowerDeviceD0)
01010     {
01011         FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCallback: Device already powered up...\n"));
01012 
01013         return;
01014 
01015     }
01016 
01017     FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCallback::"));
01018     FreeBT_IoIncrement(deviceExtension);
01019 
01020     powerState.DeviceState = PowerDeviceD0;
01021     ntStatus = PoRequestPowerIrp(deviceExtension->PhysicalDeviceObject,
01022                                  IRP_MN_SET_POWER,
01023                                  powerState,
01024                                  (PREQUEST_POWER_COMPLETE) WWIrpCompletionFunc,
01025                                  deviceExtension,
01026                                  NULL);
01027 
01028     if(deviceExtension->WaitWakeEnable)
01029     {
01030         IssueWaitWake(deviceExtension);
01031 
01032     }
01033 
01034     FreeBT_DbgPrint(3, ("FBTUSB: WaitWakeCallback: Leaving\n"));
01035 
01036     return;
01037 
01038 }
01039 
01040 
01041 PCHAR PowerMinorFunctionString (IN UCHAR MinorFunction)
01042 {
01043     switch (MinorFunction)
01044     {
01045         case IRP_MN_SET_POWER:
01046             return "IRP_MN_SET_POWER\n";
01047 
01048         case IRP_MN_QUERY_POWER:
01049             return "IRP_MN_QUERY_POWER\n";
01050 
01051         case IRP_MN_POWER_SEQUENCE:
01052             return "IRP_MN_POWER_SEQUENCE\n";
01053 
01054         case IRP_MN_WAIT_WAKE:
01055             return "IRP_MN_WAIT_WAKE\n";
01056 
01057         default:
01058             return "IRP_MN_?????\n";
01059 
01060     }
01061 
01062 }

Generated on Sat May 26 2012 04:25:43 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.