Source code of Windows XP (NT5)
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.

1897 lines
51 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. sysdev.c
  5. Abstract:
  6. This module interfaces to the system power state IRPs for devices
  7. Author:
  8. Ken Reneris (kenr) 17-Jan-1997
  9. Revision History:
  10. --*/
  11. #include "pop.h"
  12. //
  13. // External used to determine if the device tree has changed between
  14. // passes of informing devices of a system power state
  15. //
  16. extern ULONG IoDeviceNodeTreeSequence;
  17. //
  18. // Internal prototypes
  19. //
  20. VOID
  21. PopSleepDeviceList (
  22. IN PPOP_DEVICE_SYS_STATE DevState,
  23. IN PPO_NOTIFY_ORDER_LEVEL Level
  24. );
  25. VOID
  26. PopWakeDeviceList (
  27. IN PPOP_DEVICE_SYS_STATE DevState,
  28. IN PPO_NOTIFY_ORDER_LEVEL Level
  29. );
  30. VOID
  31. PopNotifyDevice (
  32. IN PPOP_DEVICE_SYS_STATE DevState,
  33. IN PPO_DEVICE_NOTIFY Notify
  34. );
  35. VOID
  36. PopWaitForSystemPowerIrp (
  37. IN PPOP_DEVICE_SYS_STATE DevState,
  38. IN BOOLEAN WaitForAll
  39. );
  40. NTSTATUS
  41. PopCompleteSystemPowerIrp (
  42. IN PDEVICE_OBJECT DeviceObject,
  43. IN PIRP Irp,
  44. IN PVOID Context
  45. );
  46. BOOLEAN
  47. PopCheckSystemPowerIrpStatus (
  48. IN PPOP_DEVICE_SYS_STATE DevState,
  49. IN PIRP Irp,
  50. IN BOOLEAN AllowTestFailure
  51. );
  52. VOID
  53. PopDumpSystemIrp (
  54. IN PUCHAR Desc,
  55. IN PPOP_DEVICE_POWER_IRP PowerIrp
  56. );
  57. VOID
  58. PopResetChildCount(
  59. IN PLIST_ENTRY ListHead
  60. );
  61. VOID
  62. PopSetupListForWake(
  63. IN PPO_NOTIFY_ORDER_LEVEL Level,
  64. IN PLIST_ENTRY ListHead
  65. );
  66. VOID
  67. PopWakeSystemTimeout(
  68. IN struct _KDPC *Dpc,
  69. IN PVOID DeferredContext,
  70. IN PVOID SystemArgument1,
  71. IN PVOID SystemArgument2
  72. );
  73. #ifdef ALLOC_PRAGMA
  74. #pragma alloc_text(PAGELK, PopSetDevicesSystemState)
  75. #pragma alloc_text(PAGELK, PopWakeDeviceList)
  76. #pragma alloc_text(PAGELK, PopSleepDeviceList)
  77. #pragma alloc_text(PAGELK, PopResetChildCount)
  78. #pragma alloc_text(PAGELK, PopSetupListForWake)
  79. #pragma alloc_text(PAGELK, PopNotifyDevice)
  80. #pragma alloc_text(PAGELK, PopWaitForSystemPowerIrp)
  81. #pragma alloc_text(PAGELK, PopCompleteSystemPowerIrp)
  82. #pragma alloc_text(PAGELK, PopCheckSystemPowerIrpStatus)
  83. #pragma alloc_text(PAGELK, PopCleanupDevState)
  84. #pragma alloc_text(PAGELK, PopRestartSetSystemState)
  85. #pragma alloc_text(PAGELK, PopReportDevState)
  86. #pragma alloc_text(PAGELK, PopDumpSystemIrp)
  87. #pragma alloc_text(PAGELK, PopWakeSystemTimeout)
  88. #pragma alloc_text(PAGE, PopAllocateDevState)
  89. #endif
  90. ULONG PopCurrentLevel=0;
  91. LONG PopWakeTimer = 1;
  92. KTIMER PopWakeTimeoutTimer;
  93. KDPC PopWakeTimeoutDpc;
  94. NTSTATUS
  95. PopSetDevicesSystemState (
  96. IN BOOLEAN Wake
  97. )
  98. /*++
  99. Routine Description:
  100. Sends a system power irp of IrpMinor and SystemState from PopAction
  101. to all devices.
  102. N.B. Function is not re-entrant.
  103. N.B. Policy lock must be held. This function releases and reacquires
  104. the policy lock.
  105. Arguments:
  106. Wake - TRUE if a transition to S0 should be broadcast to all drivers.
  107. FALSE if the appropriate sleep transition can be found in
  108. PopAction.DevState
  109. Return Value:
  110. Status.
  111. SUCCESS - all devices contacted without any errors.
  112. CANCELLED - operation was aborted.
  113. Error - error code of first failure. All failed IRPs and related
  114. device objects are on the Failed list.
  115. --*/
  116. {
  117. LONG i;
  118. NTSTATUS Status;
  119. PLIST_ENTRY ListHead;
  120. BOOLEAN NotifyGdi;
  121. BOOLEAN DidIoMmShutdown = FALSE;
  122. PPO_DEVICE_NOTIFY NotifyDevice;
  123. PLIST_ENTRY Link;
  124. PPOP_DEVICE_POWER_IRP PowerIrp;
  125. POWER_ACTION powerOperation;
  126. PPOP_DEVICE_SYS_STATE DevState;
  127. ASSERT(PopAction.DevState );
  128. DevState = PopAction.DevState;
  129. //
  130. // Intialize DevState for this pass
  131. //
  132. DevState->IrpMinor = PopAction.IrpMinor;
  133. DevState->SystemState = PopAction.SystemState;
  134. DevState->Status = STATUS_SUCCESS;
  135. DevState->FailedDevice = NULL;
  136. DevState->Cancelled = FALSE;
  137. DevState->IgnoreErrors = FALSE;
  138. DevState->IgnoreNotImplemented = FALSE;
  139. DevState->Waking = Wake;
  140. NotifyGdi = FALSE;
  141. if (PERFINFO_IS_GROUP_ON(PERF_POWER)) {
  142. PERFINFO_SET_DEVICES_STATE LogEntry;
  143. LogEntry.SystemState = (ULONG) DevState->SystemState;
  144. LogEntry.IrpMinor = PopAction.IrpMinor;
  145. LogEntry.Waking = Wake;
  146. LogEntry.Shutdown = PopAction.Shutdown;
  147. PerfInfoLogBytes(PERFINFO_LOG_TYPE_SET_DEVICES_STATE,
  148. &LogEntry,
  149. sizeof(LogEntry));
  150. }
  151. //
  152. // If this is a set operation, and the Gdi state is on then we need to
  153. // notify gdi of the set power operation
  154. //
  155. if (PopAction.IrpMinor == IRP_MN_SET_POWER &&
  156. AnyBitsSet (PopFullWake, PO_FULL_WAKE_STATUS | PO_GDI_STATUS)) {
  157. NotifyGdi = TRUE;
  158. }
  159. //
  160. // If the request is for Query on a shutdown operarion, ignore any
  161. // drivers which don't implment it. If it's for a Set on a
  162. // shutdown operation, ignore any errors - the system is going to
  163. // shutdown
  164. //
  165. if (PopAction.Shutdown) {
  166. DevState->IgnoreNotImplemented = TRUE;
  167. if (PopAction.IrpMinor == IRP_MN_SET_POWER) {
  168. DevState->IgnoreErrors = TRUE;
  169. }
  170. }
  171. //
  172. // This function is not re-entrant, and the operation has been
  173. // serialized before here
  174. //
  175. ASSERT (DevState->Thread == KeGetCurrentThread());
  176. //
  177. // Notify all devices.
  178. //
  179. if (!Wake) {
  180. //
  181. // If it's time to update the device list, then do so
  182. //
  183. if (DevState->GetNewDeviceList) {
  184. DevState->GetNewDeviceList = FALSE;
  185. IoFreePoDeviceNotifyList (&DevState->Order);
  186. DevState->Status = IoBuildPoDeviceNotifyList (&DevState->Order);
  187. } else {
  188. //
  189. // Reset the active child count of each notification
  190. //
  191. for (i=0;i<=PO_ORDER_MAXIMUM;i++) {
  192. PopResetChildCount(&DevState->Order.OrderLevel[i].WaitSleep);
  193. PopResetChildCount(&DevState->Order.OrderLevel[i].ReadySleep);
  194. PopResetChildCount(&DevState->Order.OrderLevel[i].ReadyS0);
  195. PopResetChildCount(&DevState->Order.OrderLevel[i].WaitS0);
  196. PopResetChildCount(&DevState->Order.OrderLevel[i].Complete);
  197. }
  198. }
  199. if (NT_SUCCESS(DevState->Status)) {
  200. //
  201. // Notify all devices of operation in forward order. Wait between each level.
  202. //
  203. DidIoMmShutdown = FALSE;
  204. for (i=PO_ORDER_MAXIMUM; i >= 0; i--) {
  205. //
  206. // Notify this list
  207. //
  208. if (DevState->Order.OrderLevel[i].DeviceCount) {
  209. if ((NotifyGdi) &&
  210. (i <= PO_ORDER_GDI_NOTIFICATION)) {
  211. NotifyGdi = FALSE;
  212. InterlockedExchange (&PopFullWake, 0);
  213. if (PopEventCallout) {
  214. //
  215. // Turn off the special system irp dispatcher here
  216. // as when we call into GDI it is going to block on its
  217. // D irp and we are not going to get control back.
  218. //
  219. PopSystemIrpDispatchWorker(TRUE);
  220. PopEventCalloutDispatch (PsW32GdiOff, DevState->SystemState);
  221. }
  222. }
  223. //
  224. // If we're shutting down and if we're done
  225. // notifying paged devices, shut down filesystems
  226. // and MM to free up all resources on the paging
  227. // path (which we should no longer need).
  228. //
  229. if (PopAction.Shutdown &&
  230. !DidIoMmShutdown &&
  231. (i < PO_ORDER_PAGABLE)) {
  232. // ISSUE-2000/03/14-earhart: shutdown
  233. // filesystems here.
  234. //
  235. // Swap in the worker threads, to keep them
  236. // from paging
  237. //
  238. // ExShutdownSystem (1);
  239. //
  240. // Send shutdown IRPs to all drivers that asked for it. This is
  241. // primarily for the filesystems as we will soon be closing the pagefile
  242. // handle causing the filesystems to unload. Drivers must free (or lock
  243. // down) their pagable data before this call returns.
  244. //
  245. // IoShutdownSystem (1);
  246. //
  247. // Memory management will close the pagefile handle(s) here, causing the
  248. // filesystem stack to unload.
  249. //
  250. // NO MORE REFERENCES TO PAGABLE CODE OR DATA MAY BE MADE.
  251. //
  252. // MmShutdownSystem (1);
  253. DidIoMmShutdown = TRUE;
  254. }
  255. //
  256. // Remove the warm eject node if we might have gotten here
  257. // without a query.
  258. //
  259. if (PopAction.Flags & POWER_ACTION_CRITICAL) {
  260. *DevState->Order.WarmEjectPdoPointer = NULL;
  261. }
  262. //
  263. // Notify this list
  264. //
  265. PopCurrentLevel = i;
  266. PopSleepDeviceList (DevState, &DevState->Order.OrderLevel[i]);
  267. PopWaitForSystemPowerIrp (DevState, TRUE);
  268. }
  269. //
  270. // If there's been an error, stop and issue wakes to all devices
  271. //
  272. if (!NT_SUCCESS(DevState->Status)) {
  273. Wake = TRUE;
  274. if ((DevState->FailedDevice != NULL) &&
  275. (PopAction.NextSystemState == PowerSystemWorking)) {
  276. powerOperation = PopMapInternalActionToIrpAction(
  277. PopAction.Action,
  278. DevState->SystemState,
  279. FALSE
  280. );
  281. IoNotifyPowerOperationVetoed(
  282. powerOperation,
  283. (powerOperation == PowerActionWarmEject) ?
  284. *DevState->Order.WarmEjectPdoPointer : NULL,
  285. DevState->FailedDevice
  286. );
  287. }
  288. break;
  289. }
  290. }
  291. }
  292. //
  293. // This will cause us to wake up all the devices after putting
  294. // them to sleep. Useful for test automation.
  295. //
  296. if ((PopSimulate & POP_WAKE_DEVICE_AFTER_SLEEP) && (PopAction.IrpMinor == IRP_MN_SET_POWER)) {
  297. DbgPrint ("po: POP_WAKE_DEVICE_AFTER_SLEEP enabled.\n");
  298. Wake = TRUE;
  299. DevState->Status = STATUS_UNSUCCESSFUL;
  300. }
  301. }
  302. //
  303. // Just in case we somehow managed to not shutdown paging
  304. // before, we'll make sure we do it here.
  305. //
  306. if (PopAction.Shutdown && !DidIoMmShutdown) {
  307. // ExShutdownSystem(1);
  308. // IoShutdownSystem(1);
  309. // MmShutdownSystem(1);
  310. DidIoMmShutdown = TRUE;
  311. }
  312. //
  313. // Some debugging code here. If the debug flag is set, then loop on failed
  314. // devices and continue to retry them. This will allow someone to step
  315. // them through the driver stack to determine where the failure is.
  316. //
  317. while ((PopSimulate & POP_LOOP_ON_FAILED_DRIVERS) &&
  318. !IsListEmpty(&PopAction.DevState->Head.Failed)) {
  319. Link = PopAction.DevState->Head.Failed.Flink;
  320. RemoveEntryList(Link);
  321. PowerIrp = CONTAINING_RECORD (Link, POP_DEVICE_POWER_IRP, Failed);
  322. PopDumpSystemIrp ("Retry", PowerIrp);
  323. IoFreeIrp (PowerIrp->Irp);
  324. NotifyDevice = PowerIrp->Notify;
  325. PowerIrp->Irp = NULL;
  326. PowerIrp->Notify = NULL;
  327. PushEntryList (
  328. &PopAction.DevState->Head.Free,
  329. &PowerIrp->Free
  330. );
  331. DbgBreakPoint ();
  332. PopNotifyDevice (DevState, NotifyDevice);
  333. PopWaitForSystemPowerIrp (DevState, TRUE);
  334. }
  335. //
  336. // If waking, send set power to the working state to all devices which where
  337. // send something else
  338. //
  339. DevState->Waking = Wake;
  340. if (DevState->Waking) {
  341. DevState->IgnoreErrors = TRUE;
  342. DevState->IrpMinor = IRP_MN_SET_POWER;
  343. DevState->SystemState = PowerSystemWorking;
  344. //
  345. // Notify all devices of the wake operation in reverse (level) order.
  346. //
  347. KeInitializeTimer(&PopWakeTimeoutTimer);
  348. KeInitializeDpc(&PopWakeTimeoutDpc, PopWakeSystemTimeout, NULL);
  349. for (i=0; i <= PO_ORDER_MAXIMUM; i++) {
  350. PopCurrentLevel = i;
  351. PopWakeDeviceList (DevState, &DevState->Order.OrderLevel[i]);
  352. PopWaitForSystemPowerIrp (DevState, TRUE);
  353. if (PopSimulate & POP_WAKE_DEADMAN) {
  354. KeCancelTimer(&PopWakeTimeoutTimer);
  355. }
  356. }
  357. // restore
  358. DevState->IrpMinor = PopAction.IrpMinor;
  359. DevState->SystemState = PopAction.SystemState;
  360. }
  361. //
  362. // Done
  363. //
  364. if (PERFINFO_IS_GROUP_ON(PERF_POWER)) {
  365. PERFINFO_SET_DEVICES_STATE_RET LogEntry;
  366. LogEntry.Status = DevState->Status;
  367. PerfInfoLogBytes(PERFINFO_LOG_TYPE_SET_DEVICES_STATE_RET,
  368. &LogEntry,
  369. sizeof(LogEntry));
  370. }
  371. return DevState->Status;
  372. }
  373. VOID
  374. PopReportDevState (
  375. IN BOOLEAN LogErrors
  376. )
  377. /*++
  378. Routine Description:
  379. Verifies that the DevState structure is idle
  380. Arguments:
  381. None
  382. Return Value:
  383. None
  384. --*/
  385. {
  386. PIRP Irp;
  387. PLIST_ENTRY Link;
  388. PPOP_DEVICE_POWER_IRP PowerIrp;
  389. PUCHAR IrpType;
  390. PIO_ERROR_LOG_PACKET ErrLog;
  391. if (!PopAction.DevState) {
  392. return ;
  393. }
  394. //
  395. // Cleanup any irps on the failed list
  396. //
  397. while (!IsListEmpty(&PopAction.DevState->Head.Failed)) {
  398. Link = PopAction.DevState->Head.Failed.Flink;
  399. RemoveEntryList(Link);
  400. PowerIrp = CONTAINING_RECORD (Link, POP_DEVICE_POWER_IRP, Failed);
  401. Irp = PowerIrp->Irp;
  402. PopDumpSystemIrp (
  403. LogErrors ? "Abort" : "fyi",
  404. PowerIrp
  405. );
  406. if (LogErrors) {
  407. ErrLog = IoAllocateErrorLogEntry (
  408. PowerIrp->Notify->TargetDevice->DriverObject,
  409. ERROR_LOG_MAXIMUM_SIZE
  410. );
  411. if (ErrLog) {
  412. RtlZeroMemory (ErrLog, sizeof (*ErrLog));
  413. ErrLog->FinalStatus = Irp->IoStatus.Status;
  414. ErrLog->DeviceOffset.QuadPart = Irp->IoStatus.Information;
  415. ErrLog->MajorFunctionCode = IRP_MJ_POWER;
  416. ErrLog->UniqueErrorValue = (PopAction.DevState->IrpMinor << 16) | PopAction.DevState->SystemState;
  417. ErrLog->ErrorCode = IO_SYSTEM_SLEEP_FAILED;
  418. IoWriteErrorLogEntry (ErrLog);
  419. }
  420. }
  421. IoFreeIrp (Irp);
  422. PowerIrp->Irp = NULL;
  423. PowerIrp->Notify = NULL;
  424. PushEntryList (
  425. &PopAction.DevState->Head.Free,
  426. &PowerIrp->Free
  427. );
  428. }
  429. //
  430. // Errors have been purged, we can now allocate a new device notification list if needed
  431. //
  432. if (PopAction.DevState->Order.DevNodeSequence != IoDeviceNodeTreeSequence) {
  433. PopAction.DevState->GetNewDeviceList = TRUE;
  434. }
  435. }
  436. VOID
  437. PopAllocateDevState(
  438. VOID
  439. )
  440. /*++
  441. Routine Description:
  442. Allocates and initialies the DevState structure.
  443. Arguments:
  444. None
  445. Return Value:
  446. PopAction.DevState != NULL if successful.
  447. PopAction.DevState == NULL otherwise.
  448. --*/
  449. {
  450. PPOP_DEVICE_SYS_STATE DevState;
  451. ULONG i;
  452. PAGED_CODE();
  453. ASSERT(PopAction.DevState == NULL);
  454. //
  455. // Allocate a device state structure
  456. //
  457. DevState = (PPOP_DEVICE_SYS_STATE) ExAllocatePoolWithTag(NonPagedPool,
  458. sizeof (POP_DEVICE_SYS_STATE),
  459. POP_PDSS_TAG);
  460. if (!DevState) {
  461. PopAction.DevState = NULL;
  462. return;
  463. }
  464. RtlZeroMemory (DevState, sizeof(POP_DEVICE_SYS_STATE));
  465. DevState->Thread = KeGetCurrentThread();
  466. DevState->GetNewDeviceList = TRUE;
  467. KeInitializeSpinLock (&DevState->SpinLock);
  468. KeInitializeEvent (&DevState->Event, SynchronizationEvent, FALSE);
  469. DevState->Head.Free.Next = NULL;
  470. InitializeListHead (&DevState->Head.Pending);
  471. InitializeListHead (&DevState->Head.Complete);
  472. InitializeListHead (&DevState->Head.Abort);
  473. InitializeListHead (&DevState->Head.Failed);
  474. InitializeListHead (&DevState->PresentIrpQueue);
  475. for (i=0; i < MAX_SYSTEM_POWER_IRPS; i++) {
  476. DevState->PowerIrpState[i].Irp = NULL;
  477. PushEntryList (&DevState->Head.Free,
  478. &DevState->PowerIrpState[i].Free);
  479. }
  480. for (i=0; i <= PO_ORDER_MAXIMUM; i++) {
  481. KeInitializeEvent(&DevState->Order.OrderLevel[i].LevelReady,
  482. NotificationEvent,
  483. FALSE);
  484. InitializeListHead(&DevState->Order.OrderLevel[i].WaitSleep);
  485. InitializeListHead(&DevState->Order.OrderLevel[i].ReadySleep);
  486. InitializeListHead(&DevState->Order.OrderLevel[i].Pending);
  487. InitializeListHead(&DevState->Order.OrderLevel[i].Complete);
  488. InitializeListHead(&DevState->Order.OrderLevel[i].ReadyS0);
  489. InitializeListHead(&DevState->Order.OrderLevel[i].WaitS0);
  490. }
  491. PopAction.DevState = DevState;
  492. }
  493. VOID
  494. PopCleanupDevState (
  495. VOID
  496. )
  497. /*++
  498. Routine Description:
  499. Verifies that the DevState structure is idle
  500. Arguments:
  501. None
  502. Return Value:
  503. None
  504. --*/
  505. {
  506. //
  507. // Notify power irp code that the device system state irps
  508. // are done
  509. //
  510. PopSystemIrpDispatchWorker (TRUE);
  511. //
  512. // Verify all lists are empty
  513. //
  514. ASSERT(IsListEmpty(&PopAction.DevState->Head.Pending) &&
  515. IsListEmpty(&PopAction.DevState->Head.Complete) &&
  516. IsListEmpty(&PopAction.DevState->Head.Abort) &&
  517. IsListEmpty(&PopAction.DevState->Head.Failed) &&
  518. IsListEmpty(&PopAction.DevState->PresentIrpQueue));
  519. ExFreePool (PopAction.DevState);
  520. PopAction.DevState = NULL;
  521. }
  522. #define STATE_DONE_WAITING 0
  523. #define STATE_COMPLETE_IRPS 1
  524. #define STATE_PRESENT_PAGABLE_IRPS 2
  525. #define STATE_CHECK_CANCEL 3
  526. #define STATE_WAIT_NOW 4
  527. VOID
  528. PopWaitForSystemPowerIrp (
  529. IN PPOP_DEVICE_SYS_STATE DevState,
  530. IN BOOLEAN WaitForAll
  531. )
  532. /*++
  533. Routine Description:
  534. Called to wait for one or more system power irps to complete. Handles
  535. final processing of any completed irp.
  536. Arguments:
  537. DevState - Current DevState structure
  538. WaitForAll - If TRUE all outstanding IRPs are waited for, else any outstanding
  539. irp will do
  540. Return Value:
  541. None
  542. --*/
  543. {
  544. KIRQL OldIrql;
  545. ULONG State;
  546. BOOLEAN IrpCompleted;
  547. BOOLEAN NotImplemented;
  548. PIRP Irp;
  549. PLIST_ENTRY Link;
  550. PPOP_DEVICE_POWER_IRP PowerIrp;
  551. PPO_DEVICE_NOTIFY Notify;
  552. NTSTATUS Status;
  553. LARGE_INTEGER Timeout;
  554. IrpCompleted = FALSE;
  555. KeAcquireSpinLock (&DevState->SpinLock, &OldIrql);
  556. //
  557. // Signal completion function that we are waiting
  558. //
  559. State = STATE_COMPLETE_IRPS;
  560. while (State != STATE_DONE_WAITING) {
  561. switch (State) {
  562. case STATE_COMPLETE_IRPS:
  563. //
  564. // Assume we're going to advance to the next state
  565. //
  566. State += 1;
  567. //
  568. // If there arn't any irps on the complete list, move to the
  569. // next state
  570. //
  571. if (IsListEmpty(&DevState->Head.Complete)) {
  572. break;
  573. }
  574. //
  575. // Handle the completed irps
  576. //
  577. IrpCompleted = TRUE;
  578. while (!IsListEmpty(&DevState->Head.Complete)) {
  579. Link = DevState->Head.Complete.Flink;
  580. RemoveEntryList(Link);
  581. PowerIrp = CONTAINING_RECORD (Link, POP_DEVICE_POWER_IRP, Complete);
  582. Notify = PowerIrp->Notify;
  583. PowerIrp->Complete.Flink = NULL;
  584. Irp = PowerIrp->Irp;
  585. //
  586. // Verify the device driver called PoStartNextPowerIrp
  587. //
  588. if ((Notify->TargetDevice->DeviceObjectExtension->PowerFlags & POPF_SYSTEM_ACTIVE) ||
  589. (Notify->DeviceObject->DeviceObjectExtension->PowerFlags & POPF_SYSTEM_ACTIVE)) {
  590. PDEVICE_OBJECT DeviceObject = Notify->DeviceObject;
  591. KeReleaseSpinLock (&DevState->SpinLock, OldIrql);
  592. PopDumpSystemIrp ("SYS STATE", PowerIrp);
  593. PopInternalAddToDumpFile ( NULL, 0, DeviceObject, NULL, NULL, NULL );
  594. PopInternalAddToDumpFile ( NULL, 0, Notify->TargetDevice, NULL, NULL, NULL );
  595. KeBugCheckEx (
  596. DRIVER_POWER_STATE_FAILURE,
  597. 0x500,
  598. DEVICE_SYSTEM_STATE_HUNG,
  599. (ULONG_PTR) Notify->TargetDevice,
  600. (ULONG_PTR) DeviceObject );
  601. }
  602. //
  603. // If success, or cancelled, or not implemented that's OK, then
  604. // the irp is complete
  605. //
  606. if (PopCheckSystemPowerIrpStatus(DevState, Irp, TRUE)) {
  607. //
  608. // See if IRP is failure being allowed for testing
  609. //
  610. if (!PopCheckSystemPowerIrpStatus(DevState, Irp, FALSE)) {
  611. KeReleaseSpinLock (&DevState->SpinLock, OldIrql);
  612. PopDumpSystemIrp ("ignored", PowerIrp);
  613. KeAcquireSpinLock (&DevState->SpinLock, &OldIrql);
  614. }
  615. //
  616. // Request is complete, free it
  617. //
  618. IoFreeIrp (Irp);
  619. PowerIrp->Irp = NULL;
  620. PowerIrp->Notify = NULL;
  621. PushEntryList (
  622. &DevState->Head.Free,
  623. &PowerIrp->Free
  624. );
  625. } else {
  626. //
  627. // Some sort of error. Keep track of the failure
  628. //
  629. ASSERT (!DevState->Waking);
  630. InsertTailList(&DevState->Head.Failed, &PowerIrp->Failed);
  631. }
  632. }
  633. break;
  634. case STATE_PRESENT_PAGABLE_IRPS:
  635. //
  636. // Assume we're going to advance to the next state
  637. //
  638. State += 1;
  639. //
  640. // If the last device that a system irp was sent to was pagable,
  641. // we use a thread to present them to the driver so it can page.
  642. //
  643. if (!(PopCallSystemState & PO_CALL_NON_PAGED)) {
  644. KeReleaseSpinLock (&DevState->SpinLock, OldIrql);
  645. PopSystemIrpDispatchWorker (FALSE);
  646. KeAcquireSpinLock (&DevState->SpinLock, &OldIrql);
  647. }
  648. break;
  649. case STATE_CHECK_CANCEL:
  650. //
  651. // Assume we're going to advance to the next state
  652. //
  653. State += 1;
  654. //
  655. // If there's no error or we've already canceled move to the state
  656. //
  657. if (NT_SUCCESS(DevState->Status) ||
  658. DevState->Cancelled ||
  659. DevState->Waking) {
  660. break;
  661. }
  662. //
  663. // First time the error has been seen. Cancel anything outstanding.
  664. // Build list of all pending irps
  665. //
  666. DevState->Cancelled = TRUE;
  667. for (Link = DevState->Head.Pending.Flink;
  668. Link != &DevState->Head.Pending;
  669. Link = Link->Flink) {
  670. PowerIrp = CONTAINING_RECORD (Link, POP_DEVICE_POWER_IRP, Pending);
  671. InsertTailList (&DevState->Head.Abort, &PowerIrp->Abort);
  672. }
  673. //
  674. // Drop completion lock and cancel irps on abort list
  675. //
  676. KeReleaseSpinLock (&DevState->SpinLock, OldIrql);
  677. for (Link = DevState->Head.Abort.Flink;
  678. Link != &DevState->Head.Abort;
  679. Link = Link->Flink) {
  680. PowerIrp = CONTAINING_RECORD (Link, POP_DEVICE_POWER_IRP, Abort);
  681. IoCancelIrp (PowerIrp->Irp);
  682. }
  683. KeAcquireSpinLock (&DevState->SpinLock, &OldIrql);
  684. InitializeListHead (&DevState->Head.Abort);
  685. //
  686. // After canceling check for more completed irps
  687. //
  688. State = STATE_COMPLETE_IRPS;
  689. break;
  690. case STATE_WAIT_NOW:
  691. //
  692. // Check for wait condition
  693. //
  694. if ((!WaitForAll && IrpCompleted) || IsListEmpty(&DevState->Head.Pending)) {
  695. //
  696. // Done. After waiting, verify there's at least struct on the
  697. // free list. If not, recycle something off the failured list
  698. //
  699. if (!DevState->Head.Free.Next && !IsListEmpty(&DevState->Head.Failed)) {
  700. Link = DevState->Head.Failed.Blink;
  701. PowerIrp = CONTAINING_RECORD (Link, POP_DEVICE_POWER_IRP, Failed);
  702. RemoveEntryList(Link);
  703. PowerIrp->Failed.Flink = NULL;
  704. PowerIrp->Irp = NULL;
  705. PowerIrp->Notify = NULL;
  706. PushEntryList (
  707. &DevState->Head.Free,
  708. &PowerIrp->Free
  709. );
  710. }
  711. State = STATE_DONE_WAITING;
  712. break;
  713. }
  714. //
  715. // Signal completion function that we are waiting
  716. //
  717. DevState->WaitAll = TRUE;
  718. DevState->WaitAny = !WaitForAll;
  719. //
  720. // Drop locks and wait for event to be signalled
  721. //
  722. KeClearEvent (&DevState->Event);
  723. KeReleaseSpinLock (&DevState->SpinLock, OldIrql);
  724. Timeout.QuadPart = DevState->Cancelled ?
  725. POP_ACTION_CANCEL_TIMEOUT : POP_ACTION_TIMEOUT;
  726. Timeout.QuadPart = Timeout.QuadPart * US2SEC * US2TIME * -1;
  727. Status = KeWaitForSingleObject (
  728. &DevState->Event,
  729. Suspended,
  730. KernelMode,
  731. FALSE,
  732. &Timeout
  733. );
  734. KeAcquireSpinLock (&DevState->SpinLock, &OldIrql);
  735. //
  736. // No longer waiting
  737. //
  738. DevState->WaitAll = FALSE;
  739. DevState->WaitAny = FALSE;
  740. //
  741. // If this is a timeout, then dump all the pending irps
  742. //
  743. if (Status == STATUS_TIMEOUT) {
  744. for (Link = DevState->Head.Pending.Flink;
  745. Link != &DevState->Head.Pending;
  746. Link = Link->Flink) {
  747. PowerIrp = CONTAINING_RECORD (Link, POP_DEVICE_POWER_IRP, Pending);
  748. InsertTailList (&DevState->Head.Abort, &PowerIrp->Abort);
  749. }
  750. KeReleaseSpinLock (&DevState->SpinLock, OldIrql);
  751. for (Link = DevState->Head.Abort.Flink;
  752. Link != &DevState->Head.Abort;
  753. Link = Link->Flink) {
  754. PowerIrp = CONTAINING_RECORD (Link, POP_DEVICE_POWER_IRP, Abort);
  755. PopDumpSystemIrp ("Waiting on", PowerIrp);
  756. }
  757. KeAcquireSpinLock (&DevState->SpinLock, &OldIrql);
  758. InitializeListHead (&DevState->Head.Abort);
  759. }
  760. //
  761. // Check for completed irps
  762. //
  763. State = STATE_COMPLETE_IRPS;
  764. break;
  765. }
  766. }
  767. KeReleaseSpinLock (&DevState->SpinLock, OldIrql);
  768. }
  769. VOID
  770. PopSleepDeviceList (
  771. IN PPOP_DEVICE_SYS_STATE DevState,
  772. IN PPO_NOTIFY_ORDER_LEVEL Level
  773. )
  774. /*++
  775. Routine Description:
  776. Sends Sx power irps to all devices in the supplied level
  777. Arguments:
  778. DevState - Supplies the devstate
  779. Level - Supplies the level to send power irps to
  780. Return Value:
  781. None. DevState->Status is set on error.
  782. --*/
  783. {
  784. PPO_DEVICE_NOTIFY NotifyDevice;
  785. PLIST_ENTRY Link;
  786. KIRQL OldIrql;
  787. ASSERT(!DevState->Waking);
  788. ASSERT(IsListEmpty(&Level->Pending));
  789. ASSERT(IsListEmpty(&Level->ReadyS0));
  790. ASSERT(IsListEmpty(&Level->WaitS0));
  791. //
  792. // Move any devices from the completed list back to their correct spots.
  793. //
  794. Link = Level->ReadyS0.Flink;
  795. while (Link != &Level->ReadyS0) {
  796. NotifyDevice = CONTAINING_RECORD (Link, PO_DEVICE_NOTIFY, Link);
  797. Link = NotifyDevice->Link.Flink;
  798. if (NotifyDevice->ChildCount) {
  799. InsertHeadList(&Level->WaitSleep, Link);
  800. } else {
  801. ASSERT(NotifyDevice->ActiveChild == 0);
  802. InsertHeadList(&Level->ReadySleep, Link);
  803. }
  804. }
  805. while (!IsListEmpty(&Level->Complete)) {
  806. Link = RemoveHeadList(&Level->Complete);
  807. NotifyDevice = CONTAINING_RECORD (Link, PO_DEVICE_NOTIFY, Link);
  808. if (NotifyDevice->ChildCount) {
  809. InsertHeadList(&Level->WaitSleep, Link);
  810. } else {
  811. ASSERT(NotifyDevice->ActiveChild == 0);
  812. InsertHeadList(&Level->ReadySleep, Link);
  813. }
  814. }
  815. ASSERT(!IsListEmpty(&Level->ReadySleep));
  816. Level->ActiveCount = Level->DeviceCount;
  817. KeAcquireSpinLock(&DevState->SpinLock, &OldIrql);
  818. while ((Level->ActiveCount) &&
  819. (NT_SUCCESS(DevState->Status))) {
  820. if (!IsListEmpty(&Level->ReadySleep)) {
  821. Link = RemoveHeadList(&Level->ReadySleep);
  822. InsertTailList(&Level->Pending, Link);
  823. KeReleaseSpinLock(&DevState->SpinLock, OldIrql);
  824. NotifyDevice = CONTAINING_RECORD (Link, PO_DEVICE_NOTIFY, Link);
  825. ASSERT(NotifyDevice->ActiveChild == 0);
  826. PopNotifyDevice(DevState, NotifyDevice);
  827. } else {
  828. if ((Level->ActiveCount) &&
  829. (NT_SUCCESS(DevState->Status))) {
  830. //
  831. // No devices are ready to receive IRPs yet, so wait for
  832. // one of the pending IRPs to complete.
  833. //
  834. ASSERT(!IsListEmpty(&Level->Pending));
  835. KeReleaseSpinLock(&DevState->SpinLock, OldIrql);
  836. PopWaitForSystemPowerIrp(DevState, FALSE);
  837. }
  838. }
  839. KeAcquireSpinLock(&DevState->SpinLock, &OldIrql);
  840. }
  841. KeReleaseSpinLock(&DevState->SpinLock, OldIrql);
  842. }
  843. VOID
  844. PopResetChildCount(
  845. IN PLIST_ENTRY ListHead
  846. )
  847. /*++
  848. Routine Description:
  849. Enumerates the notify structures in the supplied list and
  850. sets their active child count to be equal to the total
  851. child count.
  852. Arguments:
  853. ListHead - supplies the list head.
  854. Return Value:
  855. None
  856. --*/
  857. {
  858. PPO_DEVICE_NOTIFY Notify;
  859. PLIST_ENTRY Link;
  860. Link = ListHead->Flink;
  861. while (Link != ListHead) {
  862. Notify = CONTAINING_RECORD (Link, PO_DEVICE_NOTIFY, Link);
  863. Link = Link->Flink;
  864. Notify->ActiveChild = Notify->ChildCount;
  865. }
  866. }
  867. VOID
  868. PopSetupListForWake(
  869. IN PPO_NOTIFY_ORDER_LEVEL Level,
  870. IN PLIST_ENTRY ListHead
  871. )
  872. /*++
  873. Routine Description:
  874. Moves all devices that have WakeNeeded=TRUE from the specified
  875. list to either the ReadyS0 or WaitS0 lists.
  876. Arguments:
  877. Level - Supplies the level
  878. ListHead - Supplies the list to be moved.
  879. Return Value:
  880. None
  881. --*/
  882. {
  883. PPO_DEVICE_NOTIFY NotifyDevice;
  884. PPO_DEVICE_NOTIFY ParentNotify;
  885. PLIST_ENTRY Link;
  886. Link = ListHead->Flink;
  887. while (Link != ListHead) {
  888. NotifyDevice = CONTAINING_RECORD (Link, PO_DEVICE_NOTIFY, Link);
  889. Link = NotifyDevice->Link.Flink;
  890. if (NotifyDevice->WakeNeeded) {
  891. --Level->ActiveCount;
  892. RemoveEntryList(&NotifyDevice->Link);
  893. ParentNotify = IoGetPoNotifyParent(NotifyDevice);
  894. if ((ParentNotify==NULL) ||
  895. (!ParentNotify->WakeNeeded)) {
  896. InsertTailList(&Level->ReadyS0, &NotifyDevice->Link);
  897. } else {
  898. InsertTailList(&Level->WaitS0, &NotifyDevice->Link);
  899. }
  900. }
  901. }
  902. }
  903. VOID
  904. PopWakeDeviceList(
  905. IN PPOP_DEVICE_SYS_STATE DevState,
  906. IN PPO_NOTIFY_ORDER_LEVEL Level
  907. )
  908. /*++
  909. Routine Description:
  910. Sends S0 power irps to all devices that need waking in the
  911. given order level.
  912. Arguments:
  913. DevState - Supplies the device state
  914. Level - supplies the level to send power irps to
  915. Return Value:
  916. None. DevState->Status is set on error.
  917. --*/
  918. {
  919. PPO_DEVICE_NOTIFY NotifyDevice;
  920. PPO_DEVICE_NOTIFY ParentNotify;
  921. PLIST_ENTRY Link;
  922. KIRQL OldIrql;
  923. ASSERT(DevState->Waking);
  924. ASSERT(IsListEmpty(&Level->Pending));
  925. ASSERT(IsListEmpty(&Level->WaitS0));
  926. Level->ActiveCount = Level->DeviceCount;
  927. //
  928. // Run through all the devices and put everything that has
  929. // WakeNeeded=TRUE onto the wake list.
  930. //
  931. PopSetupListForWake(Level, &Level->WaitSleep);
  932. PopSetupListForWake(Level, &Level->ReadySleep);
  933. PopSetupListForWake(Level, &Level->Complete);
  934. ASSERT((Level->DeviceCount == 0) ||
  935. (Level->ActiveCount == Level->DeviceCount) ||
  936. !IsListEmpty(&Level->ReadyS0));
  937. KeAcquireSpinLock(&DevState->SpinLock, &OldIrql);
  938. while (Level->ActiveCount < Level->DeviceCount) {
  939. if (!IsListEmpty(&Level->ReadyS0)) {
  940. Link = RemoveHeadList(&Level->ReadyS0);
  941. InsertTailList(&Level->Pending,Link);
  942. KeReleaseSpinLock(&DevState->SpinLock, OldIrql);
  943. NotifyDevice = CONTAINING_RECORD (Link, PO_DEVICE_NOTIFY, Link);
  944. //
  945. // Set the timer to go off if we are not done by the timeout period
  946. //
  947. if (PopSimulate & POP_WAKE_DEADMAN) {
  948. LARGE_INTEGER DueTime;
  949. DueTime.QuadPart = (LONGLONG)PopWakeTimer * -1 * 1000 * 1000 * 10;
  950. KeSetTimer(&PopWakeTimeoutTimer, DueTime, &PopWakeTimeoutDpc);
  951. }
  952. PopNotifyDevice(DevState, NotifyDevice);
  953. } else {
  954. //
  955. // No devices are ready to receive IRPs yet, so wait for
  956. // one of the pending IRPs to complete.
  957. //
  958. ASSERT(!IsListEmpty(&Level->Pending));
  959. KeReleaseSpinLock(&DevState->SpinLock, OldIrql);
  960. PopWaitForSystemPowerIrp(DevState, FALSE);
  961. }
  962. KeAcquireSpinLock(&DevState->SpinLock, &OldIrql);
  963. }
  964. KeReleaseSpinLock(&DevState->SpinLock, OldIrql);
  965. ASSERT(Level->ActiveCount == Level->DeviceCount);
  966. }
  967. VOID
  968. PopLogNotifyDevice (
  969. IN PDEVICE_OBJECT TargetDevice,
  970. IN OPTIONAL PPO_DEVICE_NOTIFY Notify,
  971. IN PIRP Irp
  972. )
  973. /*++
  974. Routine Description:
  975. This routine logs a Po device notification. It is a seperate
  976. function so that the local buffer does not eat stack space
  977. through the PoCallDriver call.
  978. Arguments:
  979. TargetDevice - Device IRP is being sent to.
  980. Notify - If present, supplies the power notify structure for the specified device
  981. This will only be present on Sx irps, not Dx irps.
  982. Irp - Pointer to the built Irp for PoCallDriver.
  983. Return Value:
  984. None.
  985. --*/
  986. {
  987. UCHAR StackBuffer[256];
  988. ULONG StackBufferSize;
  989. PPERFINFO_PO_NOTIFY_DEVICE LogEntry;
  990. ULONG MaxDeviceNameLength;
  991. ULONG DeviceNameLength;
  992. ULONG CopyLength;
  993. ULONG RemainingSize;
  994. ULONG LogEntrySize;
  995. PIO_STACK_LOCATION IrpSp;
  996. //
  997. // Initialize locals.
  998. //
  999. StackBufferSize = sizeof(StackBuffer);
  1000. LogEntry = (PVOID) StackBuffer;
  1001. IrpSp = IoGetNextIrpStackLocation(Irp);
  1002. //
  1003. // Stack buffer should be large enough to contain at least the fixed
  1004. // part of the LogEntry structure.
  1005. //
  1006. if (StackBufferSize < sizeof(PERFINFO_PO_NOTIFY_DEVICE)) {
  1007. ASSERT(FALSE);
  1008. return;
  1009. }
  1010. //
  1011. // Fill in the LogEntry fields.
  1012. //
  1013. LogEntry->Irp = Irp;
  1014. LogEntry->DriverStart = TargetDevice->DriverObject->DriverStart;
  1015. LogEntry->MajorFunction = IrpSp->MajorFunction;
  1016. LogEntry->MinorFunction = IrpSp->MinorFunction;
  1017. LogEntry->Type = IrpSp->Parameters.Power.Type;
  1018. LogEntry->State = IrpSp->Parameters.Power.State;
  1019. if (Notify) {
  1020. LogEntry->OrderLevel = Notify->OrderLevel;
  1021. if (Notify->DeviceName) {
  1022. //
  1023. // Determine what the maximum device name length (excluding NUL) we
  1024. // can fit into our stack buffer. Note that PERFINFO_NOTIFY_DEVICE
  1025. // has space for the terminating NUL character.
  1026. //
  1027. RemainingSize = StackBufferSize - sizeof(PERFINFO_PO_NOTIFY_DEVICE);
  1028. MaxDeviceNameLength = RemainingSize / sizeof(WCHAR);
  1029. //
  1030. // Determine the length of the device name and adjust the copy length.
  1031. //
  1032. DeviceNameLength = wcslen(Notify->DeviceName);
  1033. CopyLength = DeviceNameLength;
  1034. if (CopyLength > MaxDeviceNameLength) {
  1035. CopyLength = MaxDeviceNameLength;
  1036. }
  1037. //
  1038. // Copy CopyLength characters from the end of the DeviceName.
  1039. // This way if our buffer is not enough, we get a more distinct part
  1040. // of the name.
  1041. //
  1042. wcscpy(LogEntry->DeviceName,
  1043. Notify->DeviceName + DeviceNameLength - CopyLength);
  1044. } else {
  1045. //
  1046. // There is no device name.
  1047. //
  1048. CopyLength = 0;
  1049. LogEntry->DeviceName[CopyLength] = 0;
  1050. }
  1051. } else {
  1052. LogEntry->OrderLevel = 0;
  1053. CopyLength = 0;
  1054. LogEntry->DeviceName[CopyLength] = 0;
  1055. }
  1056. //
  1057. // Copied device name should be terminated: we had enough room for it.
  1058. //
  1059. ASSERT(LogEntry->DeviceName[CopyLength] == 0);
  1060. //
  1061. // Log the entry.
  1062. //
  1063. LogEntrySize = sizeof(PERFINFO_PO_NOTIFY_DEVICE);
  1064. LogEntrySize += CopyLength * sizeof(WCHAR);
  1065. PerfInfoLogBytes(PERFINFO_LOG_TYPE_PO_NOTIFY_DEVICE,
  1066. LogEntry,
  1067. LogEntrySize);
  1068. //
  1069. // We are done.
  1070. //
  1071. return;
  1072. }
  1073. VOID
  1074. PopNotifyDevice (
  1075. IN PPOP_DEVICE_SYS_STATE DevState,
  1076. IN PPO_DEVICE_NOTIFY Notify
  1077. )
  1078. /*++
  1079. Routine Description:
  1080. Arguments:
  1081. Return Value:
  1082. --*/
  1083. {
  1084. PPOP_DEVICE_POWER_IRP PowerIrp;
  1085. PSINGLE_LIST_ENTRY Entry;
  1086. PIO_STACK_LOCATION IrpSp;
  1087. PIRP Irp;
  1088. ULONG SysCall;
  1089. KIRQL OldIrql;
  1090. PDEVICE_OBJECT *WarmEjectDevice;
  1091. POWER_ACTION IrpAction;
  1092. //
  1093. // Set the SysCall state to match our notify current state
  1094. //
  1095. ASSERT(PopCurrentLevel == Notify->OrderLevel);
  1096. SysCall = PO_CALL_SYSDEV_QUEUE;
  1097. if (!(Notify->OrderLevel & PO_ORDER_PAGABLE)) {
  1098. SysCall |= PO_CALL_NON_PAGED;
  1099. }
  1100. if (PopCallSystemState != SysCall) {
  1101. PopLockWorkerQueue(&OldIrql);
  1102. PopCallSystemState = SysCall;
  1103. PopUnlockWorkerQueue(OldIrql);
  1104. }
  1105. //
  1106. // Allocate an PowerIrp & Irp structures
  1107. //
  1108. PowerIrp = NULL;
  1109. Irp = NULL;
  1110. for (; ;) {
  1111. Entry = PopEntryList(&DevState->Head.Free);
  1112. if (Entry) {
  1113. break;
  1114. }
  1115. PopWaitForSystemPowerIrp (DevState, FALSE);
  1116. }
  1117. PowerIrp = CONTAINING_RECORD(Entry, POP_DEVICE_POWER_IRP, Free);
  1118. for (; ;) {
  1119. Irp = IoAllocateIrp ((CHAR) Notify->TargetDevice->StackSize, FALSE);
  1120. if (Irp) {
  1121. break;
  1122. }
  1123. PopWaitForSystemPowerIrp (DevState, FALSE);
  1124. }
  1125. SPECIALIRP_WATERMARK_IRP(Irp, IRP_SYSTEM_RESTRICTED);
  1126. if (!DevState->Waking) {
  1127. //
  1128. // If the device node list changed, then restart. This could have
  1129. // happened when we dropped our list and then rebuilt it inbetween
  1130. // queries for sleep states.
  1131. //
  1132. if (DevState->Order.DevNodeSequence != IoDeviceNodeTreeSequence) {
  1133. PopRestartSetSystemState();
  1134. }
  1135. //
  1136. // If there's been some sort of error, then abort
  1137. //
  1138. if (!NT_SUCCESS(DevState->Status)) {
  1139. PushEntryList (&DevState->Head.Free, &PowerIrp->Free);
  1140. IoFreeIrp (Irp);
  1141. return ; // abort
  1142. }
  1143. //
  1144. // Mark notify as needing wake.
  1145. //
  1146. Notify->WakeNeeded = TRUE;
  1147. } else {
  1148. Notify->WakeNeeded = FALSE;
  1149. }
  1150. //
  1151. // Put irp onto pending queue
  1152. //
  1153. PowerIrp->Irp = Irp;
  1154. PowerIrp->Notify = Notify;
  1155. ExInterlockedInsertTailList (
  1156. &DevState->Head.Pending,
  1157. &PowerIrp->Pending,
  1158. &DevState->SpinLock
  1159. );
  1160. //
  1161. // Setup irp
  1162. //
  1163. Irp->IoStatus.Status = STATUS_NOT_SUPPORTED ;
  1164. Irp->IoStatus.Information = 0;
  1165. IrpSp = IoGetNextIrpStackLocation(Irp);
  1166. IrpSp->MajorFunction = IRP_MJ_POWER;
  1167. IrpSp->MinorFunction = DevState->IrpMinor;
  1168. IrpSp->Parameters.Power.SystemContext = 0;
  1169. IrpSp->Parameters.Power.Type = SystemPowerState;
  1170. IrpSp->Parameters.Power.State.SystemState = DevState->SystemState;
  1171. ASSERT(PopAction.Action != PowerActionHibernate);
  1172. WarmEjectDevice = DevState->Order.WarmEjectPdoPointer;
  1173. //
  1174. // We need to determine the appropriate power action to place in our IRP.
  1175. // For instance, we send PowerActionWarmEject to the devnode being warm
  1176. // ejected, and we convert our internal PowerActionSleep to
  1177. // PowerActionHibernate if the sleep state is S4.
  1178. //
  1179. IrpAction = PopMapInternalActionToIrpAction (
  1180. PopAction.Action,
  1181. DevState->SystemState,
  1182. (BOOLEAN) (DevState->Waking || (*WarmEjectDevice != Notify->DeviceObject))
  1183. );
  1184. //
  1185. // If we are sending a set power to the devnode to be warm ejected,
  1186. // zero out the warm eject device field to signify we have handled to
  1187. // requested operation.
  1188. //
  1189. if ((IrpAction == PowerActionWarmEject) &&
  1190. (*WarmEjectDevice == Notify->DeviceObject) &&
  1191. (DevState->IrpMinor == IRP_MN_SET_POWER)) {
  1192. *WarmEjectDevice = NULL;
  1193. }
  1194. IrpSp->Parameters.Power.ShutdownType = IrpAction;
  1195. IoSetCompletionRoutine (Irp, PopCompleteSystemPowerIrp, PowerIrp, TRUE, TRUE, TRUE);
  1196. //
  1197. // Log the call.
  1198. //
  1199. if (PERFINFO_IS_GROUP_ON(PERF_POWER)) {
  1200. PopLogNotifyDevice(Notify->TargetDevice, Notify, Irp);
  1201. }
  1202. //
  1203. // Give it to the driver, and continue
  1204. //
  1205. PoCallDriver (Notify->TargetDevice, Irp);
  1206. }
  1207. NTSTATUS
  1208. PopCompleteSystemPowerIrp (
  1209. IN PDEVICE_OBJECT DeviceObject,
  1210. IN PIRP Irp,
  1211. IN PVOID Context
  1212. )
  1213. /*++
  1214. Routine Description:
  1215. IRP completion routine for system power irps. Takes the irp from the
  1216. DevState pending queue and puts it on the DevState complete queue.
  1217. Arguments:
  1218. DeviceObect - The device object
  1219. Irp - The IRP
  1220. Context - Device power irp structure for this request
  1221. Return Value:
  1222. STATUS_MORE_PROCESSING_REQUIRED
  1223. --*/
  1224. {
  1225. PPOP_DEVICE_POWER_IRP PowerIrp;
  1226. PPOP_DEVICE_SYS_STATE DevState;
  1227. KIRQL OldIrql;
  1228. BOOLEAN SetEvent;
  1229. NTSTATUS Status;
  1230. PIO_STACK_LOCATION IrpSp, IrpSp2;
  1231. PPO_DEVICE_NOTIFY Notify;
  1232. PPO_DEVICE_NOTIFY ParentNotify;
  1233. PPO_NOTIFY_ORDER_LEVEL Order;
  1234. PowerIrp = (PPOP_DEVICE_POWER_IRP) Context;
  1235. DevState = PopAction.DevState;
  1236. SetEvent = FALSE;
  1237. //
  1238. // Log the completion.
  1239. //
  1240. if (PERFINFO_IS_GROUP_ON(PERF_POWER)) {
  1241. PERFINFO_PO_NOTIFY_DEVICE_COMPLETE LogEntry;
  1242. LogEntry.Irp = Irp;
  1243. LogEntry.Status = Irp->IoStatus.Status;
  1244. PerfInfoLogBytes(PERFINFO_LOG_TYPE_PO_NOTIFY_DEVICE_COMPLETE,
  1245. &LogEntry,
  1246. sizeof(LogEntry));
  1247. }
  1248. KeAcquireSpinLock (&DevState->SpinLock, &OldIrql);
  1249. //
  1250. // Move irp from pending queue to complete queue
  1251. //
  1252. RemoveEntryList (&PowerIrp->Pending);
  1253. PowerIrp->Pending.Flink = NULL;
  1254. InsertTailList (&DevState->Head.Complete, &PowerIrp->Complete);
  1255. //
  1256. // Move notify from pending queue to the appropriate queue
  1257. // depending on whether we are sleeping or waking.
  1258. //
  1259. Notify=PowerIrp->Notify;
  1260. ASSERT(Notify->OrderLevel == PopCurrentLevel);
  1261. Order = &DevState->Order.OrderLevel[Notify->OrderLevel];
  1262. RemoveEntryList(&Notify->Link);
  1263. InsertTailList(&Order->Complete, &Notify->Link);
  1264. if (DevState->Waking) {
  1265. ++Order->ActiveCount;
  1266. IoMovePoNotifyChildren(Notify, &DevState->Order);
  1267. } else {
  1268. //
  1269. // We will only decrement the parent's active count if the IRP was
  1270. // completed successfully. Otherwise it is possible for a parent to
  1271. // get put on the ReadySleep list even though its child has failed
  1272. // the query/set irp.
  1273. //
  1274. if (NT_SUCCESS(Irp->IoStatus.Status) || DevState->IgnoreErrors) {
  1275. --Order->ActiveCount;
  1276. ParentNotify = IoGetPoNotifyParent(Notify);
  1277. if (ParentNotify) {
  1278. ASSERT(ParentNotify->ActiveChild > 0);
  1279. if (--ParentNotify->ActiveChild == 0) {
  1280. RemoveEntryList(&ParentNotify->Link);
  1281. InsertTailList(&DevState->Order.OrderLevel[ParentNotify->OrderLevel].ReadySleep,
  1282. &ParentNotify->Link);
  1283. }
  1284. }
  1285. }
  1286. }
  1287. //
  1288. // If there is a wait any, then kick event
  1289. // If there is a wait all, then check for empty pending queue
  1290. //
  1291. if ((DevState->WaitAny) ||
  1292. (DevState->WaitAll && IsListEmpty(&DevState->Head.Pending))) {
  1293. SetEvent = TRUE;
  1294. }
  1295. //
  1296. // If the IRP is in error and it's the first such IRP start aborting
  1297. // the current operation
  1298. //
  1299. if (!PopCheckSystemPowerIrpStatus(DevState, Irp, TRUE) &&
  1300. NT_SUCCESS(DevState->Status)) {
  1301. //
  1302. // We need to set the failed device here. If we are warm ejecting
  1303. // however, the warm eject devnode will *legitimately* fail any queries
  1304. // for S states it doesn't support. As we will be trying several Sx
  1305. // states, the trick is to preserve any failed device that is *not*
  1306. // warm eject devnode, and update failed device to the warm eject
  1307. // devnode only if failed device is currently NULL.
  1308. //
  1309. if ((PopAction.Action != PowerActionWarmEject) ||
  1310. (DevState->FailedDevice == NULL) ||
  1311. (PowerIrp->Notify->DeviceObject != *DevState->Order.WarmEjectPdoPointer)) {
  1312. DevState->FailedDevice = PowerIrp->Notify->DeviceObject;
  1313. }
  1314. DevState->Status = Irp->IoStatus.Status;
  1315. SetEvent = TRUE; // wake to cancel pending irps
  1316. }
  1317. KeReleaseSpinLock (&DevState->SpinLock, OldIrql);
  1318. if (SetEvent) {
  1319. KeSetEvent (&DevState->Event, IO_NO_INCREMENT, FALSE);
  1320. }
  1321. return STATUS_MORE_PROCESSING_REQUIRED;
  1322. }
  1323. BOOLEAN
  1324. PopCheckSystemPowerIrpStatus (
  1325. IN PPOP_DEVICE_SYS_STATE DevState,
  1326. IN PIRP Irp,
  1327. IN BOOLEAN AllowTestFailure
  1328. )
  1329. // return FALSE if irp is some sort of unallowed error
  1330. {
  1331. NTSTATUS Status;
  1332. Status = Irp->IoStatus.Status;
  1333. //
  1334. // If Status is sucess, then no problem
  1335. //
  1336. if (NT_SUCCESS(Status)) {
  1337. return TRUE;
  1338. }
  1339. //
  1340. // If errors are allowed, or it's a cancelled request no problem
  1341. //
  1342. if (DevState->IgnoreErrors || Status == STATUS_CANCELLED) {
  1343. return TRUE;
  1344. }
  1345. //
  1346. // Check to see if the error is that the driver doesn't implement the
  1347. // request and if such a condition is allowed
  1348. //
  1349. if (Status == STATUS_NOT_SUPPORTED && DevState->IgnoreNotImplemented) {
  1350. return TRUE;
  1351. }
  1352. //
  1353. // For testing purposes, optionally let through unsupported device drivers
  1354. //
  1355. if (Status == STATUS_NOT_SUPPORTED &&
  1356. AllowTestFailure &&
  1357. (PopSimulate & POP_IGNORE_UNSUPPORTED_DRIVERS)) {
  1358. return TRUE;
  1359. }
  1360. //
  1361. // Some unexpected failure, treat it as an error
  1362. //
  1363. return FALSE;
  1364. }
  1365. VOID
  1366. PopRestartSetSystemState (
  1367. VOID
  1368. )
  1369. /*++
  1370. Routine Description:
  1371. Aborts current system power state operation.
  1372. Arguments:
  1373. None
  1374. Return Value:
  1375. None
  1376. --*/
  1377. {
  1378. KIRQL OldIrql;
  1379. KeAcquireSpinLock (&PopAction.DevState->SpinLock, &OldIrql);
  1380. if (!PopAction.Shutdown && NT_SUCCESS(PopAction.DevState->Status)) {
  1381. PopAction.DevState->Status = STATUS_CANCELLED;
  1382. }
  1383. KeReleaseSpinLock (&PopAction.DevState->SpinLock, OldIrql);
  1384. KeSetEvent (&PopAction.DevState->Event, IO_NO_INCREMENT, FALSE);
  1385. }
  1386. VOID
  1387. PopDumpSystemIrp (
  1388. IN PUCHAR Desc,
  1389. IN PPOP_DEVICE_POWER_IRP PowerIrp
  1390. )
  1391. {
  1392. PUCHAR Testing;
  1393. PUCHAR IrpType;
  1394. PPO_DEVICE_NOTIFY Notify;
  1395. Notify = PowerIrp->Notify;
  1396. //
  1397. // Dump errors to debugger
  1398. //
  1399. switch (PopAction.DevState->IrpMinor) {
  1400. case IRP_MN_QUERY_POWER: IrpType = "QueryPower"; break;
  1401. case IRP_MN_SET_POWER: IrpType = "SetPower"; break;
  1402. default: IrpType = "?"; break;
  1403. }
  1404. DbgPrint ("%s: ", Desc);
  1405. if (Notify->DriverName) {
  1406. DbgPrint ("%ws ", Notify->DriverName);
  1407. } else {
  1408. DbgPrint ("%x ", Notify->TargetDevice->DriverObject);
  1409. }
  1410. if (Notify->DeviceName) {
  1411. DbgPrint ("%ws ", Notify->DeviceName);
  1412. } else {
  1413. DbgPrint ("%x ", Notify->TargetDevice);
  1414. }
  1415. DbgPrint ("irp (%x) %s-%s status %x\n",
  1416. PowerIrp->Irp,
  1417. IrpType,
  1418. PopSystemStateString(PopAction.DevState->SystemState),
  1419. PowerIrp->Irp->IoStatus.Status
  1420. );
  1421. }
  1422. VOID
  1423. PopWakeSystemTimeout(
  1424. IN struct _KDPC *Dpc,
  1425. IN PVOID DeferredContext,
  1426. IN PVOID SystemArgument1,
  1427. IN PVOID SystemArgument2
  1428. )
  1429. /*++
  1430. Routine Description:
  1431. This routine is used to break into the kernel debugger if somebody is
  1432. taking too long processing their S irps.
  1433. Arguments:
  1434. Return Value:
  1435. None
  1436. --*/
  1437. {
  1438. try {
  1439. DbgBreakPoint();
  1440. } except (EXCEPTION_EXECUTE_HANDLER) {
  1441. ;
  1442. }
  1443. }