Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1647 lines
39 KiB

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