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.

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