Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfbtpwr.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
1.7.6.1
|