ReactOS  0.4.15-dev-3165-gdf6fff7
powerstatemachine.cpp
Go to the documentation of this file.
1 /*++
2 Copyright (c) Microsoft. All rights reserved.
3 
4 Module Name:
5 
6  PowerStateMachine.cpp
7 
8 Abstract:
9 
10  This module implements the Power state machine for the driver framework.
11  This code was split out from FxPkgPnp.cpp.
12 
13 Author:
14 
15 
16 
17 
18 Environment:
19 
20  Both kernel and user mode
21 
22 Revision History:
23 
24 
25 
26 --*/
27 
28 #include "pnppriv.hpp"
29 
30 extern "C" {
31 #if defined(EVENT_TRACING)
32 #include "PowerStateMachine.tmh"
33 #endif
34 }
35 
36 #if FX_STATE_MACHINE_VERIFY
37  #define VALIDATE_POWER_STATE(_CurrentState, _NewState) \
38  ValidatePowerStateEntryFunctionReturnValue((_CurrentState), (_NewState))
39 #else
40  #define VALIDATE_POWER_STATE(_CurrentState, _NewState) (0)
41 #endif //FX_STATE_MACHINE_VERIFY
42 
43 
44 // @@SMVERIFY_SPLIT_BEGIN
45 
46 //
47 // The Power State Machine
48 //
49 // This state machine responds to power IRPs that relate
50 // to devices. It is a subordinate, responding either to IRPs
51 // that are sent by other drivers, or by IRPs that are
52 // sent by the Power Policy State Machine.
53 //
54 // It responds to:
55 //
56 // IRP_MN_SET_POWER -- device power IRPs only
57 // IRP_MN_WAIT_WAKE
58 // IRP_MN_WAIT_WAKE Complete
59 // PowerImplicitD0
60 // PowerImplicitD3
61 // ParentMovesToD0
62 // PowerPolicyStop
63 // PowerMarkPageable
64 // PowerMarkNonpageable
65 //
66 
67 
68 
69 
70 
71 
73 {
77 };
78 
80 {
84 };
85 
87 {
92 };
93 
95 {
100 };
101 
103 {
110 };
111 
113 {
120 };
121 
123 {
126 };
127 
129 {
132 };
133 
135 {
141 };
142 
144 {
150 };
151 
153 {
157 };
158 
160 {
164 };
165 
167 {
170 };
171 
173 {
176 };
177 
179 {
180  // WdfDevStatePowerObjectCreated
181  { NULL,
183  NULL,
184  { TRUE,
185  PowerMarkPageable | // parent sends usage notifications before the PDO is
186  PowerMarkNonpageable | // started
187  PowerParentToD0 | // parent powered up upon enumeration of child
188  PowerDx | // If we are on top of a power policy owner who sends a Dx
189  // during start (or after AddDevice, etc)
190  PowerD0 // If we are on top of a power policy owner who sends a D0
191  // to the stack in start device, we can get this event early
192  },
193  },
194 
195  // WdfDevStatePowerCheckDeviceType
198  NULL,
199  { FALSE,
200  0 },
201  },
202 
203  // WdfDevStatePowerCheckDeviceTypeNP
206  NULL,
207  { FALSE,
208  0 },
209  },
210 
211  // WdfDevStatePowerCheckParentState
214  NULL,
215  { FALSE,
216  0 },
217  },
218 
219  // WdfDevStatePowerCheckParentStateNP
222  NULL,
223  { FALSE,
224  0 },
225  },
226 
227  // WdfDevStatePowerEnablingWakeAtBus
230  NULL,
231  { FALSE,
232  0 },
233  },
234 
235  // WdfDevStatePowerEnablingWakeAtBusNP
238  NULL,
239  { FALSE,
240  0 },
241  },
242 
243  // WdfDevStatePowerD0
247  { TRUE,
249  PowerD0 // A non WDF power policy owner might send a D0 irp
250  // while we are in D0
251  },
252  },
253 
254  // WdfDevStatePowerD0NP
258  { TRUE,
259  PowerD0 // A non WDF power policy owner might send a D0 irp
260  // while we are in D0
261  },
262  },
263 
264  // WdfDevStatePowerD0BusWakeOwner
268  { TRUE,
269  PowerWakeSucceeded | // During surprise remove, the pnp state machine
270  // could complete the ww request and result in
271  // this event before the pwr pol machine is stopped
272  PowerWakeCanceled | // while powering up, the wait wake owner canceled
273  // the ww irp
274  PowerWakeFailed | // while powering up, the wait wake owner failed
275  // the ww irp
277  PowerD0 // A non WDF power policy owner might send a D0 irp
278  // while we are in D0
279  },
280  },
281 
282  // WdfDevStatePowerD0BusWakeOwnerNP
286  { TRUE,
287  PowerWakeSucceeded | // During surprise remove, the pnp state machine
288  // could complete the ww request and result in
289  // this event before the pwr pol machine is stopped
290  PowerWakeCanceled | // while powering up, the wait wake owner canceled
291  // the ww irp
293  PowerD0 // A non WDF power policy owner might send a D0 irp
294  // while we are in D0
295  },
296  },
297 
298  // WdfDevStatePowerD0ArmedForWake
302  { TRUE,
304  PowerWakeArrival | // PowerIsWakeRequestPresent() returned true in
305  // WdfDevStatePowerD0BusWakeOwner and raced with
306  // this event being processed
308  PowerD0 // A non WDF power policy owner might send a D0 irp
309  // while we are in D0
310  },
311  },
312 
313  // WdfDevStatePowerD0ArmedForWakeNP
317  { TRUE,
319  PowerWakeArrival | // PowerIsWakeRequestPresent() returned true in
320  // WdfDevStatePowerD0BusWakeOwnerNP and raced with
321  // this event being processed
323  PowerD0 // A non WDF power policy owner might send a D0 irp
324  // while we are in D0
325  },
326  },
327 
328  // WdfDevStatePowerD0DisarmingWakeAtBus
331  NULL,
332  { FALSE,
333  0 },
334  },
335 
336  // WdfDevStatePowerD0DisarmingWakeAtBusNP
339  NULL,
340  { FALSE,
341  0 },
342  },
343 
344  // WdfDevStatePowerD0Starting
347  NULL,
348  { FALSE,
349  0 },
350  },
351 
352  // WdfDevStatePowerD0StartingConnectInterrupt
355  NULL,
356  { FALSE,
357  0 },
358  },
359 
360  // WdfDevStatePowerD0StartingDmaEnable
363  NULL,
364  { FALSE,
365  0 },
366  },
367 
368  // WdfDevStatePowerD0StartingStartSelfManagedIo
371  NULL,
372  { FALSE,
373  0 },
374  },
375 
376  // WdfDevStatePowerDecideD0State
379  NULL,
380  { FALSE,
381  0 },
382  },
383 
384  // WdfDevStatePowerGotoD3Stopped
387  NULL,
388  { FALSE,
389  0 },
390  },
391 
392  // WdfDevStatePowerStopped
393  { NULL,
396  { TRUE,
397  PowerD0 | // as a filter above the PPO and the PPO powers on the stack
398  // before seeing a surprise remove or remove irp
399  PowerWakeFailed | // power policy owner canceled the wake request while
400  // we were transitioning to stop (or after the
401  // transition succeeded)
402  PowerParentToD0 },
403  },
404 
405  // WdfDevStatePowerStartingCheckDeviceType
408  NULL,
409  { FALSE,
410  0 },
411  },
412 
413  // WdfDevStatePowerStartingChild
416  NULL,
417  { TRUE,
418  0 },
419  },
420 
421  // WdfDevStatePowerDxDisablingWakeAtBus
424  NULL,
425  { FALSE,
426  0 },
427  },
428 
429  // WdfDevStatePowerDxDisablingWakeAtBusNP
432  NULL,
433  { FALSE,
434  0 },
435  },
436 
437  // WdfDevStatePowerGotoDx
440  NULL,
441  { FALSE,
442  PowerWakeArrival | // on a PDO which is the PPO, it will send a wake
443  // request in this state.
444 
445 
446  PowerParentToD0 // Parent is powering up while this device is powering
447  // down
448  },
449  },
450 
451  // WdfDevStatePowerGotoDxNP
454  NULL,
455  { FALSE,
456  PowerWakeArrival | // on a PDO which is the PPO, it will send a wake
457  // request in this state.
458 
459 
460  PowerParentToD0 // Parent is powering up while this device is powering
461  // down
462  },
463  },
464 
465  // WdfDevStatePowerGotoDxIoStopped
468  NULL,
469  { FALSE,
470  0 },
471  },
472 
473  // WdfDevStatePowerGotoDxIoStoppedNP
476  NULL,
477  { FALSE,
478  0 },
479  },
480 
481  // WdfDevStatePowerGotoDxNPFailed
484  NULL,
485  { FALSE,
486  0 },
487  },
488 
489  // NOTE: can't use PowerDx as a func name since it's an enum value
490  // WdfDevStatePowerDx
491  { NULL,
494  { TRUE,
495  PowerWakeArrival | // on a PDO which is the PPO, it will send a wake
496  // request in this state.
497 
498 
499 
500  PowerWakeCanceled | // on a PDO which is the PPO, it will cancel the
501  // the wake request in this state. Since we didn't
502  // handle PowerWakeArrival in WdfDevStatePowerGotoDx
503  // for this scenario, we must also handle the canel
504  // here. Even if we handle wake arrived in that
505  // state, the PPO (non KMDF) could send a wake
506  // request while in Dx and then cancel it in Dx,
507  // so we must still ignore this event here.
508 
509  PowerWakeSucceeded | // on a PDO which is the PPO, a completion of the
510  // wait wake can arrive in this state. This event
511  // can be ignored and the pending wait wake will
512  // be completed.
513 
515  PowerParentToD0 | // parent went to D0 first while the PDO was still
516  // in Dx
517 
518  PowerDx // power policy sent a Dx to Dx transition
519  },
520  },
521 
522  // WdfDevStatePowerDxNP
523  { NULL,
526  { TRUE,
527  PowerWakeArrival | // on a PDO which is the PPO, it will send a wake
528  // request in this state.
529 
530 
531 
532  PowerWakeCanceled | // on a PDO which is the PPO, it will cancel the
533  // the wake request in this state. Since we didn't
534  // handle PowerWakeArrival in WdfDevStatePowerGotoDx
535  // for this scenario, we must also handle the canel
536  // here. Even if we handle wake arrived in that
537  // state, the PPO (non KMDF) could send a wake
538  // request while in Dx and then cancel it in Dx,
539  // so we must still ignore this event here.
540 
541  PowerWakeSucceeded | // on a PDO which is the PPO, a completion of the
542  // wait wake can arrive in this state. This event
543  // can be ignored and the pending wait wake will
544  // be completed.
545 
546  PowerParentToD0 | // parent went to D0 first while the PDO was still
547  // in Dx
548 
549  PowerDx // power policy sent a Dx to Dx transition
550  },
551  },
552 
553  // WdfDevStatePowerGotoDxArmedForWake
556  NULL,
557  { FALSE,
558  0 },
559  },
560 
561  // WdfDevStatePowerGotoDxArmedForWakeNP
564  NULL,
565  { FALSE,
566  0 },
567  },
568 
569  // WdfDevStatePowerGotoDxIoStoppedArmedForWake
572  NULL,
573  { FALSE,
574  0 },
575  },
576 
577  // WdfDevStatePowerGotoDxIoStoppedArmedForWakeNP
580  NULL,
581  { FALSE,
582  0 },
583  },
584 
585  // WdfDevStatePowerDxArmedForWake
586  { NULL,
589  { TRUE,
590  PowerParentToD0 // can occur on a PDO when a Dx transition completes
591  // on the parent and it wakes up before the child
592  },
593  },
594 
595  // WdfDevStatePowerDxArmedForWakeNP
596  { NULL,
599  { TRUE,
600  PowerParentToD0 // can occur on a PDO when a Dx transition completes
601  // on the parent and it wakes up before the child
602  },
603  },
604 
605  // WdfDevStatePowerCheckParentStateArmedForWake
608  NULL,
609  { FALSE,
610  0 },
611  },
612 
613  // WdfDevStatePowerCheckParentStateArmedForWakeNP
616  NULL,
617  { FALSE,
618  0 },
619  },
620 
621  // WdfDevStatePowerWaitForParentArmedForWake
622  { NULL,
624  NULL,
625  { FALSE,
626  0 },
627  },
628 
629  // WdfDevStatePowerWaitForParentArmedForWakeNP
630  { NULL,
632  NULL,
633  { FALSE,
634  0 },
635  },
636 
637  // WdfDevStatePowerStartSelfManagedIo
640  NULL,
641  { FALSE,
642  0 },
643  },
644 
645  // WdfDevStatePowerStartSelfManagedIoNP
648  NULL,
649  { FALSE,
650  0 },
651  },
652 
653  // WdfDevStatePowerStartSelfManagedIoFailed
656  NULL,
657  { FALSE,
658  0 },
659  },
660 
661  // WdfDevStatePowerStartSelfManagedIoFailedNP
664  NULL,
665  { FALSE,
666  0 },
667  },
668 
669  // WdfDevStatePowerWaitForParent
670  { NULL,
672  NULL,
673  { FALSE,
674  0 },
675  },
676 
677  // WdfDevStatePowerWaitForParentNP
678  { NULL,
680  NULL,
681  { FALSE,
682  0 },
683  },
684 
685  // WdfDevStatePowerWakePending
689  { TRUE,
690  PowerParentToD0 // parent moved to D0 while the child was moving to
691  // D0 from Dx armed for wake
692  },
693  },
694 
695  // WdfDevStatePowerWakePendingNP
699  { TRUE,
700  PowerParentToD0 // parent moved to D0 while the child was moving to
701  // D0 from Dx armed for wake
702  },
703  },
704 
705  // WdfDevStatePowerWaking
708  NULL,
709  { FALSE,
710  0 },
711  },
712 
713  // WdfDevStatePowerWakingNP
716  NULL,
717  { FALSE,
718  0 },
719  },
720 
721  // WdfDevStatePowerWakingConnectInterrupt
724  NULL,
725  { FALSE,
726  0 },
727  },
728 
729  // WdfDevStatePowerWakingConnectInterruptNP
732  NULL,
733  { FALSE,
734  0 },
735  },
736 
737  // WdfDevStatePowerWakingConnectInterruptFailed
740  NULL,
741  { FALSE,
742  0 },
743  },
744 
745  // WdfDevStatePowerWakingConnectInterruptFailedNP
748  NULL,
749  { FALSE,
750  0 },
751  },
752 
753  // WdfDevStatePowerWakingDmaEnable
756  NULL,
757  { FALSE,
758  PowerParentToD0 // parent moved to D0 while the child was moving to
759  // D0 from Dx armed for wake
760  },
761  },
762 
763  // WdfDevStatePowerWakingDmaEnableNP
766  NULL,
767  { FALSE,
768  PowerParentToD0 // parent moved to D0 while the child was moving to
769  // D0 from Dx armed for wake
770  },
771  },
772 
773  // WdfDevStatePowerWakingDmaEnableFailed
776  NULL,
777  { FALSE,
778  0 },
779  },
780 
781  // WdfDevStatePowerWakingDmaEnableFailedNP
784  NULL,
785  { FALSE,
786  0 },
787  },
788 
789  // WdfDevStatePowerReportPowerUpFailedDerefParent
792  NULL,
793  { FALSE,
794  0
795  },
796  },
797 
798  // WdfDevStatePowerReportPowerUpFailed
801  NULL,
802  { TRUE,
803  0
804  },
805  },
806 
807  // WdfDevStatePowerPowerFailedPowerDown
810  NULL,
811  { FALSE,
812  0 },
813  },
814 
815  // WdfDevStatePowerReportPowerDownFailed
818  NULL,
819  { TRUE,
820  0 },
821  },
822 
823  // WdfDevStatePowerInitialConnectInterruptFailed
826  NULL,
827  { FALSE,
828  0 },
829  },
830 
831  // WdfDevStatePowerInitialDmaEnableFailed
834  NULL,
835  { FALSE,
836  0 },
837  },
838 
839  // WdfDevStatePowerInitialSelfManagedIoFailed
842  NULL,
843  { FALSE,
844  0 },
845  },
846 
847  // WdfDevStatePowerInitialPowerUpFailedDerefParent
850  NULL,
851  { FALSE,
852  0 },
853  },
854 
855  // WdfDevStatePowerInitialPowerUpFailed
858  NULL,
859  { FALSE,
860  0 },
861  },
862 
863  // WdfDevStatePowerDxStoppedDisarmWake
866  NULL,
867  { FALSE,
868  0 },
869  },
870 
871  // WdfDevStatePowerDxStoppedDisarmWakeNP
874  NULL,
875  { FALSE,
876  0 },
877  },
878 
879  // WdfDevStatePowerGotoDxStoppedDisableInterruptNP
882  NULL,
883  { FALSE,
884  0 },
885  },
886 
887  // WdfDevStatePowerGotoDxStopped
890  NULL,
891  { FALSE,
892  0 },
893  },
894 
895  // WdfDevStatePowerDxStopped
896  { NULL,
899  { TRUE,
900  0 },
901  },
902 
903  // WdfDevStatePowerGotoStopped
906  NULL,
907  { FALSE,
908  0 },
909  },
910 
911  // WdfDevStatePowerStoppedCompleteDx
914  NULL,
915  { FALSE,
916  0 },
917  },
918 
919  // WdfDevStatePowerDxStoppedDecideDxState
922  NULL,
923  { FALSE,
924  0 },
925  },
926 
927  // WdfDevStatePowerDxStoppedArmForWake
930  NULL,
931  { FALSE,
932  0 },
933  },
934 
935  // WdfDevStatePowerDxStoppedArmForWakeNP
938  NULL,
939  { FALSE,
940  0 },
941  },
942 
943  // WdfDevStatePowerFinalPowerDownFailed
946  NULL,
947  { FALSE,
948  0 },
949  },
950 
951  // WdfDevStatePowerFinal
952  { NULL,
954  NULL,
955  { FALSE,
956  0 },
957  },
958 
959  // WdfDevStatePowerGotoImplicitD3DisarmWakeAtBus
962  NULL,
963  { FALSE,
964  0 },
965  },
966 
967  // WdfDevStatePowerUpFailed
970  NULL,
971  { FALSE,
972  0 },
973  },
974 
975  // WdfDevStatePowerUpFailedDerefParent
978  NULL,
979  { FALSE,
980  0 },
981  },
982 
983  // WdfDevStatePowerGotoDxFailed
986  NULL,
987  { FALSE,
988  0 },
989  },
990 
991  // WdfDevStatePowerGotoDxStoppedDisableInterrupt
994  NULL,
995  { FALSE,
996  0 },
997  },
998 
999  // WdfDevStatePowerUpFailedNP
1002  NULL,
1003  { FALSE,
1004  0 },
1005  },
1006 
1007  // WdfDevStatePowerUpFailedDerefParentNP
1010  NULL,
1011  { FALSE,
1012  0 },
1013  },
1014 
1015  // WdfDevStatePowerNotifyingD0ExitToWakeInterrupts
1018  NULL,
1019  { FALSE,
1020  0 },
1021  },
1022 
1023  // WdfDevStatePowerNotifyingD0EntryToWakeInterrupts
1026  NULL,
1027  { FALSE,
1028  0 },
1029  },
1030  // WdfDevStatePowerNotifyingD0ExitToWakeInterruptsNP
1033  NULL,
1034  { FALSE,
1035  0 },
1036  },
1037 
1038  // WdfDevStatePowerNotifyingD0EntryToWakeInterrupts
1041  NULL,
1042  { FALSE,
1043  0 },
1044  },
1045 
1046  // WdfDevStatePowerNull
1047  // *** no entry for this state ***
1048 };
1049 
1050 // @@SMVERIFY_SPLIT_END
1051 
1053 NTSTATUS
1055  __inout FxPkgPnp* Pnp,
1057  )
1058 {
1059  NTSTATUS status;
1060 
1062  if (!NT_SUCCESS(status)) {
1063  return status;
1064  }
1065 
1066  return STATUS_SUCCESS;
1067 }
1068 
1069 VOID
1071  VOID
1072  )
1073 /*++
1074 
1075 Routine Description:
1076  This routine is never actually called by running code, it just has
1077  WDFCASSERTs who upon failure, would not allow this file to be compiled.
1078 
1079  DO NOT REMOVE THIS FUNCTION just because it is not called by any running
1080  code.
1081 
1082 Arguments:
1083  None
1084 
1085 Return Value:
1086  None
1087 
1088  --*/
1089 {
1090  WDFCASSERT(sizeof(FxPowerStateInfo) == sizeof(ULONG));
1091 
1092  WDFCASSERT((sizeof(m_WdfPowerStates)/sizeof(m_WdfPowerStates[0]))
1093  ==
1095 
1096  // we assume these are the same length when we update the history index
1098  sizeof(m_PowerMachine.m_Queue.Events[0]))
1099  ==
1100  (sizeof(m_PowerMachine.m_States.History)/
1101  sizeof(m_PowerMachine.m_States.History[0])));
1102 }
1103 
1104 
1105 /*++
1106 
1107 The locking model for the Power state machine requires that events be enqueued
1108 possibly at DISPATCH_LEVEL. It also requires that the state machine be
1109 runnable at PASSIVE_LEVEL. Consequently, we have two locks, one DISPATCH_LEVEL
1110 lock that guards the event queue and one PASSIVE_LEVEL lock that guards the
1111 state machine itself.
1112 
1113 The Power state machine has a few constraints that the PnP state machine
1114 doesn't. Sometimes it has to call some driver functions at PASSIVE_LEVEL, but
1115 with the disks turned off. This means that these functions absolutely must not
1116 page fault. You might think that this means that we should call the driver at
1117 DISPATCH_LEVEL, and you'd be right if your only concern were for perfectly
1118 safe code. The problem with that approach, though is that it will force much
1119 of the rest of the driver to DISPATCH_LEVEL, which will only push the driver
1120 writer into using lots of asynchronous work items, which will complicate their
1121 code and make it unsafe in a new variety of ways. So we're going to go with
1122 PASSIVE_LEVEL here and setting a timeout of 20 seconds. If the driver faults,
1123 the timer will fire and log the failure. This also means that the driver must
1124 complete these callbacks within 20 seconds. Even beyond that, it means that
1125 the work items must be queued onto a special thread, one that once the machine
1126 has started to go to sleep, never handles any work items that may fault.
1127 
1128 Algorithm:
1129 
1130 1) Acquire the Power queue lock.
1131 2) Enqueue the request. Requests are put at the end of the queue.
1132 3) Drop the Power queue lock.
1133 4) If the thread is running at PASSIVE_LEVEL, skip to step 6.
1134 5) Queue a work item onto the special power thread.
1135 6) Attempt to acquire the state machine lock, with a near-zero-length timeout.
1136 7) If successful, skip to step 9.
1137 8) Queue a work item onto the special power thread.
1138 9) Acquire the state machine lock.
1139 10) Acquire the Power queue lock.
1140 11) Attempt to dequeue an event.
1141 12) Drop the Power queue lock.
1142 13) If there was no event to dequeue, drop the state machine lock and exit.
1143 14) Execute the state handler. This may involve taking one of the other state
1144  machine queue locks, briefly, to deliver an event.
1145 15) Go to Step 10.
1146 
1147 Implementing this algorithm requires three functions.
1148 
1149 PowerProcessEvent -- Implements steps 1-8.
1150 _PowerProcessEventInner -- Implements step 9.
1151 PowerProcessEventInner -- Implements steps 10-15.
1152 
1153 --*/
1154 
1155 VOID
1158  __in BOOLEAN ProcessOnDifferentThread
1159  )
1160 /*++
1161 
1162 Routine Description:
1163  This function implements steps 1-8 of the algorithm described above.
1164 
1165 Arguments:
1166  Event - Current Power event
1167 
1168  ProcessOnDifferentThread - Process the event on a different thread
1169  regardless of IRQL. By default this is FALSE as per the declaration.
1170 
1171 Return Value:
1172 
1173  NTSTATUS
1174 
1175 --*/
1176 {
1177  NTSTATUS status;
1178  KIRQL irql;
1179 
1180  //
1181  // Take the lock, raising to DISPATCH_LEVEL.
1182  //
1183  m_PowerMachine.Lock(&irql);
1184 
1185  //
1186  // If the input Event is any of the events described by PowerSingularEventMask,
1187  // then check whether it is already queued up. If so, then dont enqueue this
1188  // Event.
1189  //
1190  if (Event & PowerSingularEventMask) {
1191  if ((m_PowerMachine.m_SingularEventsPresent & Event) == 0x00) {
1193  }
1194  else {
1197  "WDFDEVICE 0x%p !devobj 0x%p current pwr pol state "
1198  "%!WDF_DEVICE_POWER_STATE! dropping event %!FxPowerEvent! because "
1199  "the Event is already enqueued.", m_Device->GetHandle(),
1202  Event);
1203 
1204  m_PowerMachine.Unlock(irql);
1205  return;
1206  }
1207  }
1208 
1209  if (m_PowerMachine.IsFull()) {
1210  //
1211  // The queue is full. Bail.
1212  //
1213  m_PowerMachine.Unlock(irql);
1214 
1215  ASSERT(!"The Power queue is full. This shouldn't be able to happen.");
1216  return;
1217  }
1218 
1222  "WDFDEVICE 0x%p !devobj 0x%p current pwr pol state "
1223  "%!WDF_DEVICE_POWER_STATE! dropping event %!FxPowerEvent! because "
1224  "of a closed queue", m_Device->GetHandle(),
1227  Event);
1228 
1229  //
1230  // The queue is closed. Bail
1231  //
1232  m_PowerMachine.Unlock(irql);
1233 
1234  return;
1235  }
1236 
1237  //
1238  // Enqueue the event. Whether the event goes on the front
1239  // or the end of the queue depends on which event it is.
1240  //
1242  //
1243  // Stick it on the front of the queue, making it the next
1244  // event that will be processed.
1245  //
1247  }
1248  else {
1249  //
1250  // Stick it on the end of the queue.
1251  //
1253  }
1254 
1255  //
1256  // Drop the lock.
1257  //
1258  m_PowerMachine.Unlock(irql);
1259 
1260  //
1261  // Now, if we are running at PASSIVE_LEVEL, attempt to run the state
1262  // machine on this thread. If we can't do that, then queue a work item.
1263  //
1264 
1265  if (irql == PASSIVE_LEVEL &&
1266  FALSE == ProcessOnDifferentThread) {
1267  LONGLONG timeout = 0;
1268 
1271 
1272  if (FxWaitLockInternal::IsLockAcquired(status)) {
1274 
1275  //
1276  // We now hold the state machine lock. So call the function that
1277  // dispatches the next state.
1278  //
1280 
1281  //
1282  // The pnp state machine should be the only one deleting the object
1283  //
1284  ASSERT(info.m_DeleteObject == FALSE);
1285 
1287 
1288  info.Evaluate(this);
1289 
1290  return;
1291  }
1292  }
1293 
1294  //
1295  // The tag added above will be released when the work item runs
1296  //
1297 
1298  // For one reason or another, we couldn't run the state machine on this
1299  // thread. So queue a work item to do it. If m_PnPWorkItemEnqueuing
1300  // is non-zero, that means that the work item is already being enqueued
1301  // on another thread. This is significant, since it means that we can't do
1302  // anything with the work item on this thread, but it's okay, since the
1303  // work item will pick up our work and do it.
1304  //
1306 }
1307 
1308 VOID
1310  __in FxPkgPnp* This,
1312  __in PVOID WorkerContext
1313  )
1314 {
1315 
1316  UNREFERENCED_PARAMETER(WorkerContext);
1317 
1318  //
1319  // Take the state machine lock.
1320  //
1321  This->m_PowerMachine.m_StateMachineLock.AcquireLock(
1322  This->GetDriverGlobals()
1323  );
1324 
1325  //
1326  // Call the function that will actually run the state machine.
1327  //
1328  This->PowerProcessEventInner(Info);
1329 
1330  //
1331  // We are being called from the work item and m_WorkItemRunning is > 0, so
1332  // we cannot be deleted yet.
1333  //
1334  ASSERT(Info->SomethingToDo() == FALSE);
1335 
1336  //
1337  // Now release the lock
1338  //
1339  This->m_PowerMachine.m_StateMachineLock.ReleaseLock(
1340  This->GetDriverGlobals()
1341  );
1342 }
1343 
1344 VOID
1347  )
1348 /*++
1349 
1350 Routine Description:
1351  This routine runs the state machine. It implements steps 10-15 of the
1352  algorithm described above.
1353 
1354 --*/
1355 {
1356  WDF_DEVICE_POWER_STATE currentPowerState, newState;
1359  KIRQL oldIrql;
1360 
1361  //
1362  // Process as many events as we can.
1363  //
1364  for (;;) {
1365 
1366  newState = WdfDevStatePowerNull;
1367  currentPowerState = m_Device->GetDevicePowerState();
1368  entry = GetPowerTableEntry(currentPowerState);
1369 
1370  //
1371  // Get an event from the queue.
1372  //
1373  m_PowerMachine.Lock(&oldIrql);
1374 
1375  if (m_PowerMachine.IsEmpty()) {
1377 
1378  //
1379  // The queue is empty.
1380  //
1381  m_PowerMachine.Unlock(oldIrql);
1382  return;
1383  }
1384 
1386 
1387  //
1388  // At this point, we need to determine whether we can process this
1389  // event.
1390  //
1392  //
1393  // These are always possible to handle.
1394  //
1395  DO_NOTHING();
1396  }
1397  else {
1398  //
1399  // Check to see if this state can handle new events.
1400  //
1401  if (entry->StateInfo.Bits.QueueOpen == FALSE) {
1402  //
1403  // This state can't handle new events.
1404  //
1405  m_PowerMachine.Unlock(oldIrql);
1406  return;
1407  }
1408  }
1409 
1410  //
1411  // If the event obtained from the queue was a singular event, then
1412  // clear the flag to allow other similar events to be put into this
1413  // queue for processing.
1414  //
1417  }
1418 
1420  m_PowerMachine.Unlock(oldIrql);
1421 
1422  //
1423  // Find the entry in the power state table that corresponds to this event
1424  //
1425  if (entry->FirstTargetState.PowerEvent == event) {
1426  newState = entry->FirstTargetState.TargetState;
1427 
1428  DO_EVENT_TRAP(&entry->FirstTargetState);
1429  }
1430  else if (entry->OtherTargetStates != NULL) {
1431  ULONG i = 0;
1432 
1433  for (i = 0;
1434  entry->OtherTargetStates[i].PowerEvent != PowerEventMaximum;
1435  i++) {
1436  if (entry->OtherTargetStates[i].PowerEvent == event) {
1437  newState = entry->OtherTargetStates[i].TargetState;
1438  DO_EVENT_TRAP(&entry->OtherTargetStates[i]);
1439  break;
1440  }
1441  }
1442  }
1443 
1444  if (newState == WdfDevStatePowerNull) {
1447  "WDFDEVICE 0x%p !devobj 0x%p current power state "
1448  "%!WDF_DEVICE_POWER_STATE! dropping event %!FxPowerEvent!",
1449  m_Device->GetHandle(),
1452 
1453  //
1454  // This state doesn't respond to the Event. Potentially throw
1455  // the event away.
1456  //
1457  if ((entry->StateInfo.Bits.KnownDroppedEvents & event) == 0) {
1458  COVERAGE_TRAP();
1459 
1462  "WDFDEVICE %p !devobj 0x%p current state "
1463  "%!WDF_DEVICE_POWER_STATE! event %!FxPowerEvent! is not a "
1464  "known dropped event, known dropped events are "
1465  "%!FxPowerEvent!", m_Device->GetHandle(),
1468  event, entry->StateInfo.Bits.KnownDroppedEvents);
1469 
1470 
1471  }
1472 
1473  switch (event) {
1474  case PowerWakeSucceeded:
1475  case PowerWakeFailed:
1476  case PowerWakeCanceled:
1477  //
1478  // There are states where we don't care if the wake completed.
1479  // Since the completion/cancellation of the wake request posts
1480  // an event which it assumes will complete the request, we must
1481  // catch these events here and complete the request.
1482  //
1484  break;
1485 
1486  case PowerD0:
1487  case PowerDx:
1488  //
1489  // There are some (non WDF) power policy owner implementations
1490  // which send Dx to Dx or D0 to D0 transitions to the stack.
1491  //
1492  // We don't explicitly handle them in the state machine.
1493  //
1494  // Instead, we complete the pended irp if are about to drop it
1495  // on the floor.
1496  //
1498  break;
1499  }
1500  }
1501  else {
1502  //
1503  // Now enter the new state.
1504  //
1505  PowerEnterNewState(newState);
1506  }
1507  }
1508 }
1509 
1510 VOID
1513  )
1514 /*++
1515 
1516 Routine Description:
1517  This function looks up the handler for a state and
1518  then calls it.
1519 
1520 Arguments:
1521  Event - Current PnP event
1522 
1523 Return Value:
1524 
1525  NTSTATUS
1526 
1527 --*/
1528 {
1530  WDF_DEVICE_POWER_STATE currentState, newState;
1532  FxWatchdog watchdog(this);
1533 
1534  currentState = m_Device->GetDevicePowerState();
1535  newState = State;
1536 
1537  while (newState != WdfDevStatePowerNull) {
1540  "WDFDEVICE 0x%p !devobj 0x%p entering Power State "
1541  "%!WDF_DEVICE_POWER_STATE! from %!WDF_DEVICE_POWER_STATE!",
1542  m_Device->GetHandle(),
1544  newState, currentState);
1545 
1546  if (m_PowerStateCallbacks != NULL) {
1547  //
1548  // Callback for leaving the old state
1549  //
1550  RtlZeroMemory(&data, sizeof(data));
1551 
1553  data.Data.LeaveState.CurrentState = currentState;
1554  data.Data.LeaveState.NewState = newState;
1555 
1556  m_PowerStateCallbacks->Invoke(currentState,
1558  m_Device->GetHandle(),
1559  &data);
1560  }
1561 
1563  (USHORT) newState;
1564 
1565  if (m_PowerStateCallbacks != NULL) {
1566  //
1567  // Callback for entering the new state
1568  //
1569  RtlZeroMemory(&data, sizeof(data));
1570 
1572  data.Data.EnterState.CurrentState = currentState;
1573  data.Data.EnterState.NewState = newState;
1574 
1575  m_PowerStateCallbacks->Invoke(newState,
1577  m_Device->GetHandle(),
1578  &data);
1579  }
1580 
1581  m_Device->SetDevicePowerState(newState);
1582  currentState = newState;
1583 
1584  entry = GetPowerTableEntry(currentState);
1585 
1586  //
1587  // And call the state handler, if there is one.
1588  //
1589  if (entry->StateFunc != NULL) {
1590  watchdog.StartTimer(currentState);
1591  newState = entry->StateFunc(this);
1592  watchdog.CancelTimer(currentState);
1593 
1594  //
1595  // Validate the return value if FX_STATE_MACHINE_VERIFY is enabled
1596  //
1597  VALIDATE_POWER_STATE(currentState, newState);
1598 
1599  }
1600  else {
1601  newState = WdfDevStatePowerNull;
1602  }
1603 
1604  if (m_PowerStateCallbacks != NULL) {
1605  //
1606  // Callback for post processing the new state
1607  //
1608  RtlZeroMemory(&data, sizeof(data));
1609 
1611  data.Data.PostProcessState.CurrentState = currentState;
1612 
1613  m_PowerStateCallbacks->Invoke(currentState,
1615  m_Device->GetHandle(),
1616  &data);
1617  }
1618  }
1619 }
1620 
1624  )
1625 /*++
1626 
1627 Routine Description:
1628  This function implements the Check Parent state. Its only task
1629  is to dispatch to the FDO and PDO logic and handle error.
1630 
1631 Arguments:
1632  none
1633 
1634 Return Value:
1635 
1636  new power state
1637 
1638 --*/
1639 {
1640  NTSTATUS status;
1641  BOOLEAN parentOn;
1642 
1643  status = This->PowerCheckParentOverload(&parentOn);
1644 
1645  if (!NT_SUCCESS(status)) {
1646  return WdfDevStatePowerUpFailed;
1647  }
1648  else if (parentOn) {
1649  return WdfDevStatePowerWaking;
1650  }
1651  else {
1653  }
1654 }
1655 
1659  )
1660 /*++
1661 
1662 Routine Description:
1663  This function implements the Check Parent (NP) state. Its only task
1664  is to dispatch to the FDO and PDO logic.
1665 
1666 Arguments:
1667  none
1668 
1669 Return Value:
1670 
1671  new power state
1672 
1673 --*/
1674 {
1675  NTSTATUS status;
1676  BOOLEAN parentOn;
1677 
1678  status = This->PowerCheckParentOverload(&parentOn);
1679 
1680  if (!NT_SUCCESS(status)) {
1682  }
1683  else if (parentOn) {
1684  return WdfDevStatePowerWakingNP;
1685  }
1686  else {
1688  }
1689 }
1690 
1694  )
1695 /*++
1696 
1697 Routine Description:
1698  This function implements the Check Type state. Its only task
1699  is to dispatch to the FDO and PDO logic.
1700 
1701 Arguments:
1702  none
1703 
1704 Return Value:
1705 
1706  new power state
1707 
1708 --*/
1709 {
1710  return This->PowerCheckDeviceTypeOverload();
1711 }
1712 
1716  )
1717 /*++
1718 
1719 Routine Description:
1720  This function implements the Check Type (NP) state. Its only task
1721  is to dispatch to the FDO and PDO logic.
1722 
1723 Arguments:
1724  none
1725 
1726 Return Value:
1727 
1728  new power state
1729 
1730 --*/
1731 {
1732  return This->PowerCheckDeviceTypeNPOverload();
1733 }
1734 
1738  )
1739 /*++
1740 
1741 Routine Description:
1742  This function requests the driver to arm the device in a bus generic fashion.
1743 
1744 Arguments:
1745  The package which contains this instance of the state machine
1746 
1747 Return Value:
1748  new power state
1749 
1750  --*/
1751 {
1752  NTSTATUS status;
1753 
1754  //
1755  // We should only get into this state when this devobj is not a PDO and a
1756  // power policy owner.
1757  //
1758  ASSERT((This->m_Device->IsPdo() && This->IsPowerPolicyOwner()) == FALSE);
1759 
1760  status = This->PowerEnableWakeAtBusOverload();
1761 
1763 
1764  if (NT_SUCCESS(status)) {
1765  //
1766  // No matter of the irp status (canceled, pending, completed), we always
1767  // transition to the D0ArmedForWake state because that is where we
1768  // we handle the change in the irp's status.
1769  //
1771  }
1772  else {
1773  This->PowerCompleteWakeRequestFromWithinMachine(status);
1774 
1776  }
1777 }
1778 
1782  )
1783 /*++
1784 
1785 Routine Description:
1786  This function requests the driver to arm the device in a bus generic fashion.
1787 
1788 Arguments:
1789  The package which contains this instance of the state machine
1790 
1791 Return Value:
1792  new power state
1793 
1794  --*/
1795 {
1796  NTSTATUS status;
1797 
1798  //
1799  // We should only get into this state when this devobj is not a PDO and a
1800  // power policy owner.
1801  //
1802  ASSERT((This->m_Device->IsPdo() &&
1803  This->IsPowerPolicyOwner()) == FALSE);
1804 
1805  status = This->PowerEnableWakeAtBusOverload();
1806 
1808 
1809  if (NT_SUCCESS(status)) {
1810  //
1811  // No matter of the irp status (canceled, pending, completed), we always
1812  // transition to the D0ArmedForWake state because that is where we
1813  // we handle the change in the irp's status.
1814  //
1816  }
1817  else {
1818  //
1819  // Complete the irp with the error that callback indicated
1820  //
1821  COVERAGE_TRAP();
1822 
1823  This->PowerCompleteWakeRequestFromWithinMachine(status);
1824 
1826  }
1827 }
1828 
1832  )
1833 /*++
1834 
1835 Routine Description:
1836  D0 state where we cannot wake the machine
1837 
1838 Arguments:
1839  This - Instance of this state machine
1840 
1841 Return Value:
1842  new power state machine state
1843 
1844  --*/
1845 {
1846  if ((This->m_Device->GetDeviceObjectFlags() & DO_POWER_PAGABLE) == 0) {
1847  //
1848  // We are non pageable, go to that state now
1849  //
1850  COVERAGE_TRAP();
1851 
1853  }
1854 
1855  return WdfDevStatePowerNull;
1856 }
1857 
1861  )
1862 /*++
1863 
1864 Routine Description:
1865  D0 state where we can't cause paging IO and we cannot wake the machine
1866 
1867 Arguments:
1868  This - Instance of this state machine
1869 
1870 Return Value:
1871  new power state machine state
1872 
1873  --*/
1874 {
1875  if (This->m_Device->GetDeviceObjectFlags() & DO_POWER_PAGABLE) {
1876  //
1877  // We are pageable, go to that state now
1878  //
1879  COVERAGE_TRAP();
1881  }
1882 
1883  return WdfDevStatePowerNull;
1884 }
1885 
1886 
1890  )
1891 /*++
1892 
1893 Routine Description:
1894  This function implements the D0 state. It's job is to figure out whether
1895  we need to swtich to the D0NP state, and to wait around for an event
1896  of some kind or another.
1897 
1898 Arguments:
1899  none
1900 
1901 Return Value:
1902 
1903  new power state
1904 
1905 --*/
1906 {
1907  if ((This->m_Device->GetDeviceObjectFlags() & DO_POWER_PAGABLE) == 0) {
1908  //
1909  // We are non pageable, go to that state now
1910  //
1911  COVERAGE_TRAP();
1912 
1914  }
1915  else if (This->PowerIsWakeRequestPresent()) {
1917  }
1918  else {
1919  return WdfDevStatePowerNull;
1920  }
1921 }
1922 
1926  )
1927 /*++
1928 
1929 Routine Description:
1930  This function implements the D0NP state. It's job is to figure out whether
1931  we need to swtich to the D0 state, and to wait around for an event
1932  of some kind or another.
1933 
1934 Arguments:
1935  none
1936 
1937 Return Value:
1938 
1939  new power state
1940 
1941 --*/
1942 {
1943  if (This->m_Device->GetDeviceObjectFlags() & DO_POWER_PAGABLE) {
1944  //
1945  // Pageable.
1946  //
1947  COVERAGE_TRAP();
1948 
1950  }
1951  else if (This->PowerIsWakeRequestPresent()) {
1953  }
1954  else {
1955  return WdfDevStatePowerNull;
1956  }
1957 }
1958 
1962  )
1963 /*++
1964 
1965 Routine Description:
1966  Device is in D0 and armed for wake. Complete any pended D0 irp if the power
1967  policy owner make a D0 to D0 transition. Transition the NP version of
1968  this state if we are no longer pageable.
1969 
1970 Arguments:
1971  This - instance of the state machine
1972 
1973 Return Value:
1974  new state machine state
1975 
1976  --*/
1977 {
1978  if ((This->m_Device->GetDeviceObjectFlags() & DO_POWER_PAGABLE) == 0) {
1979  //
1980  // We are non pageable, go to that state now
1981  //
1982  COVERAGE_TRAP();
1983 
1985  }
1986 
1987  return WdfDevStatePowerNull;
1988 }
1989 
1993  )
1994 /*++
1995 
1996 Routine Description:
1997  Device is in D0 and armed for wake. Complete any pended D0 irp if the power
1998  policy owner make a D0 to D0 transition. Transition the pageable version of
1999  this state if we are no longer NP.
2000 
2001 Arguments:
2002  This - instance of the state machine
2003 
2004 Return Value:
2005  new state machine state
2006 
2007  --*/
2008 {
2009  if (This->m_Device->GetDeviceObjectFlags() & DO_POWER_PAGABLE) {
2010  //
2011  // We are pageable, go to that state now
2012  //
2013  COVERAGE_TRAP();
2014 
2016  }
2017 
2018  return WdfDevStatePowerNull;
2019 }
2020 
2024  )
2025 /*++
2026 
2027 Routine Description:
2028  Disarms the bus after we have armed it. The device is going to implicit D3
2029  and it has not yet been powered down.
2030 
2031 Arguments:
2032  This - instance of the state machine
2033 
2034 Return Value:
2035  new state machine state
2036 
2037  --*/
2038 {
2039  //
2040  // We should only get into this state when this devobj is a PDO and not a
2041  // power policy owner.
2042  //
2043  ASSERT((This->m_Device->IsPdo() &&
2044  This->IsPowerPolicyOwner()) == FALSE);
2045 
2046  //
2047  // Disarm
2048  // No need to complete the pended ww irp. State machine will complete it
2049  // in PnpFailed handler, or upper driver will cancel it.
2050  //
2051  This->PowerDisableWakeAtBusOverload();
2052 
2054 }
2055 
2059  )
2060 /*++
2061 
2062 Routine Description:
2063  Disarms the bus after we have armed it. The device is still in D0 so it has
2064  not yet powered down.
2065 
2066 Arguments:
2067  This - This instance of the state machine
2068 
2069 Return Value:
2070  None.
2071 
2072  --*/
2073 {
2074  //
2075  // We should only get into this state when this devobj is not a PDO and a
2076  // power policy owner.
2077  //
2078  ASSERT((This->m_Device->IsPdo() &&
2079  This->IsPowerPolicyOwner()) == FALSE);
2080 
2081  //
2082  // Disarm
2083  //
2084  This->PowerDisableWakeAtBusOverload();
2085  This->PowerCompletePendedWakeIrp();
2086 
2087  //
2088  // Go back to normal unarmed D0 with bus wake ownership
2089  //
2091 }
2092 
2096  )
2097 /*++
2098 
2099 Routine Description:
2100  Disarms the bus after we have armed it. The device is still in D0 so it has
2101  not yet powered down.
2102 
2103 Arguments:
2104  This - This instance of the state machine
2105 
2106 Return Value:
2107  None.
2108 
2109  --*/
2110 {
2111  //
2112  // We should only get into this state when this devobj is not a PDO and a
2113  // power policy owner.
2114  //
2115  ASSERT((This->m_Device->IsPdo() && This->IsPowerPolicyOwner()) == FALSE);
2116 
2117  //
2118  // Disarm
2119  //
2120  This->PowerDisableWakeAtBusOverload();
2121  This->PowerCompletePendedWakeIrp();
2122 
2123  //
2124  // Go back to normal unarmed D0 with bus wake ownership
2125  //
2127 }
2128 
2132  )
2133 /*++
2134 
2135 Routine Description:
2136  This function calls D0Entry and the moves to the next state based on the
2137  result.
2138 
2139 Arguments:
2140  This - instance of the state machine
2141 
2142 Return Value:
2143  new power state
2144 
2145 --*/
2146 {
2147  NTSTATUS status;
2148 
2149  //
2150  // Call the driver to tell it to put the hardware into the working
2151  // state.
2152  //
2153  // m_DevicePowerState is the "old" state because we update it after the
2154  // D0Entry callback.
2155  //
2156  status = This->m_DeviceD0Entry.Invoke(
2157  This->m_Device->GetHandle(),
2158  (WDF_POWER_DEVICE_STATE) This->m_DevicePowerState);
2159 
2160  if (!NT_SUCCESS(status)) {
2162  This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
2163  "EvtDeviceD0Entry WDFDEVICE 0x%p !devobj 0x%p, old state "
2164  "%!WDF_POWER_DEVICE_STATE! failed, %!STATUS!",
2165  This->m_Device->GetHandle(),
2166  This->m_Device->GetDeviceObject(),
2167  This->m_DevicePowerState, status);
2168 
2170  }
2171 
2173 }
2174 
2178  )
2179 /*++
2180 
2181 Routine Description:
2182  Continues bringing the device into D0 from the D3 final state. This routine
2183  connects and enables the interrupts. If successful it will open up the power
2184  managed i/o queues.
2185 
2186 Arguments:
2187  This - instance of the state machine
2188 
2189 Return Value:
2190  new state machine state
2191 
2192  --*/
2193 {
2194  NTSTATUS status;
2195 
2196  //
2197  // Connect the interrupt and enable it
2198  //
2199  status = This->NotifyResourceObjectsD0(NotifyResourcesNoFlags);
2200  if (!NT_SUCCESS(status)) {
2201  //
2202  // NotifyResourceObjectsD0 has already logged the error, no need to
2203  // repeat any error messsages here
2204  //
2206  }
2207 
2208  status = This->m_DeviceD0EntryPostInterruptsEnabled.Invoke(
2209  This->m_Device->GetHandle(),
2210  (WDF_POWER_DEVICE_STATE) This->m_DevicePowerState);
2211 
2212  if (!NT_SUCCESS(status)) {
2213 
2215  This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
2216  "EvtDeviceD0EntryPostInterruptsEnabed WDFDEVICE 0x%p !devobj 0x%p, "
2217  "old state %!WDF_POWER_DEVICE_STATE! failed, %!STATUS!",
2218  This->m_Device->GetHandle(),
2219  This->m_Device->GetDeviceObject(),
2220  This->m_DevicePowerState, status);
2222  }
2223 
2224  //
2225  // Last, figure out which state to drop into. This is the juncture
2226  // where we figure out if we're doing power in a pageable fashion.
2227  //
2229 }
2230 
2234  )
2235 /*++
2236 
2237 Routine Description:
2238  The device is movig to D0 for the first time. Enable any DMA enablers
2239  attached to the device.
2240 
2241 Arguments:
2242  This - instance of the state machine
2243 
2244 Return Value:
2245  new machine state
2246 
2247  --*/
2248 {
2249  if (This->PowerDmaEnableAndScan(TRUE) == FALSE) {
2251  }
2252 
2254 }
2255 
2259  )
2260 /*++
2261 
2262 Routine Description:
2263  The device is entering D0 from the final Dx state (either start or restart
2264  perhaps). Send a start event to self managed io and then release
2265 
2266 Arguments:
2267  This - instance of the state machine
2268 
2269 Return Value:
2270  new state machine state
2271 
2272  --*/
2273 {
2274 
2275 
2276 
2277 
2278  This->m_Device->m_PkgIo->ResumeProcessingForPower();
2279 
2280  if (This->m_SelfManagedIoMachine != NULL) {
2281  NTSTATUS status;
2282 
2283  status = This->m_SelfManagedIoMachine->Start();
2284 
2285  if (!NT_SUCCESS(status)) {
2286  // return WdfDevStatePowerInitialSelfManagedIoFailed; __REACTOS__ : allow to fail
2287  }
2288  }
2289 
2290  This->PowerSetDevicePowerState(WdfPowerDeviceD0);
2291 
2292  //
2293  // Send the PowerUp event to both the PnP and the Power Policy state machines.
2294  //
2295  This->PowerSendPowerUpEvents();
2296 
2298 }
2299 
2303  )
2304 /*++
2305 
2306 Routine Description:
2307  Decide which D0 state we should transition to given the wait wake ownership
2308  of this device and if DO_POWER_PAGABLE is set or not.
2309 
2310 Arguments:
2311  This - instance of the state machine
2312 
2313 Return Value:
2314  new power state
2315 
2316  --*/
2317 {
2318  if (This->m_Device->GetDeviceObjectFlags() & DO_POWER_PAGABLE) {
2319  //
2320  // Pageable.
2321  //
2322  if (This->m_SharedPower.m_WaitWakeOwner) {
2324  }
2325  else {
2326  return WdfDevStatePowerD0;
2327  }
2328  }
2329  else {
2330  //
2331  // Non-pageable.
2332  //
2333  if (This->m_SharedPower.m_WaitWakeOwner) {
2335  }
2336  else {
2337  return WdfDevStatePowerD0NP;
2338  }
2339  }
2340 }
2341 
2345  )
2346 /*++
2347 
2348 Routine Description:
2349  This function implements the D3 Stopped state.
2350 
2351 Arguments:
2352  none
2353 
2354 Return Value:
2355 
2356  new power state
2357 
2358 --*/
2359 {
2360  NTSTATUS status;
2361  BOOLEAN failed;
2362 
2363  failed = FALSE;
2364 
2365  //
2366  // We *must* call suspend here even though the pnp state machine called self
2367  // managed io stop. Consider the following:
2368  // 1 this device is a filter
2369  // 2 the power policy owner has idle enabled and the device stack is
2370  // currently idled out (in Dx)
2371  // 3 the query remove comes, this driver processes it and succeeds
2372  // self managed io stop
2373  // 4 before the PwrPolStop event is processed in this driver, the pwr policy
2374  // owner moves the stack into D0.
2375  // 5 now this driver processed the PwrPolStop and moves into this state. We
2376  // now need to make sure self managed i/o is in the stopped state before
2377  // doing anything else.
2378  //
2379 
2380  //
2381  // The self managed io state machine can handle a suspend event when it is
2382  // already in the stopped state.
2383  //
2384  // Tell the driver to stop its self-managed I/O.
2385  //
2386  if (This->m_SelfManagedIoMachine != NULL) {
2387  status = This->m_SelfManagedIoMachine->Suspend();
2388 
2389  if (!NT_SUCCESS(status)) {
2391  This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
2392  "EvtDeviceSelfManagedIoStop failed %!STATUS!", status);
2393  failed = TRUE;
2394  }
2395  }
2396 
2397 
2398 
2399 
2400 
2401  // Top-edge queue hold.
2402  This->m_Device->m_PkgIo->StopProcessingForPower(FxIoStopProcessingForPowerHold);
2403 
2404  if (This->PowerDmaPowerDown() == FALSE) {
2405  failed = TRUE;
2406  }
2407 
2408  status = This->m_DeviceD0ExitPreInterruptsDisabled.Invoke(
2409  This->m_Device->GetHandle(),
2411  );
2412 
2413  if (!NT_SUCCESS(status)) {
2414  failed = TRUE;
2415 
2417  This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
2418  "EvtDeviceD0ExitPreInterruptsDisabled WDFDEVICE 0x%p !devobj 0x%p, "
2419  "new state %!WDF_POWER_DEVICE_STATE! failed, %!STATUS!",
2420  This->m_Device->GetHandle(),
2421  This->m_Device->GetDeviceObject(),
2423  }
2424 
2425  //
2426  // Disconnect the interrupt.
2427  //
2428  status = This->NotifyResourceObjectsDx(NotifyResourcesForceDisconnect);
2429  if (!NT_SUCCESS(status)) {
2430  //
2431  // NotifyResourceObjectsDx already traced the error
2432  //
2433  failed = TRUE;
2434  }
2435 
2436  //
2437  // Call the driver to tell it to put the hardware into a sleeping
2438  // state.
2439  //
2440  status = This->m_DeviceD0Exit.Invoke(This->m_Device->GetHandle(),
2442  if (!NT_SUCCESS(status)) {
2443  failed = TRUE;
2444 
2446  This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
2447  "EvtDeviceD0Exit WDFDEVICE 0x%p !devobj 0x%p, new state "
2448  "%!WDF_POWER_DEVICE_STATE! failed, %!STATUS!",
2449  This->m_Device->GetHandle(),
2450  This->m_Device->GetDeviceObject(),
2452  }
2453 
2454  This->PowerSetDevicePowerState(WdfPowerDeviceD3Final);
2455 
2456  //
2457  // If this is a child, release the power reference on the parent
2458  //
2459  This->PowerParentPowerDereference();
2460 
2461  if (failed) {
2463  }
2464 
2465  This->PowerSendPowerDownEvents(FxPowerDownTypeImplicit);
2466 
2467  //
2468  // If we are not the PPO for the stack we could receive a power irp
2469  // during the middle of an implicit power down so we cannot assume
2470  // that there will be no pended power irp during an implicit power down.
2471  //
2472  ASSERT(This->IsPowerPolicyOwner() ? This->m_PendingDevicePowerIrp == NULL : TRUE);
2473 
2474  return WdfDevStatePowerStopped;
2475 }
2476 
2480  )
2481 /*++
2482 
2483 Routine Description:
2484  The device is implicitly powering up from the created or stopped state.
2485  Determine if this is a PDO or not to determine if we must bring the parent
2486  back into D0.
2487 
2488 Arguments:
2489  This - instance of the state machine
2490 
2491 Return Value:
2492  WdfDevStatePowerStartingChild or WdfDevStatePowerD0Starting
2493 
2494  --*/
2495 {
2496  if (This->m_Device->IsPdo()) {
2498  }
2499  else {
2501  }
2502 }
2503 
2507  )
2508 /*++
2509 
2510 Routine Description:
2511  Get the parent into a D0 state
2512 
2513 Arguments:
2514  This - instance of the state machine
2515 
2516 Return Value:
2517  WdfDevStatePowerNull or WdfDevStatePowerD0Starting
2518 
2519  --*/
2520 {
2521  NTSTATUS status;
2522  BOOLEAN parentOn;
2523 
2524  status = This->PowerCheckParentOverload(&parentOn);
2525 
2526  if (!NT_SUCCESS(status)) {
2528  This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
2529  "PowerReference on parent WDFDEVICE %p for child WDFDEVICE %p "
2530  "failed, %!STATUS!", This->m_Device->m_ParentDevice->m_Device->GetHandle(),
2531  This->m_Device->GetHandle(),
2532  status);
2533 
2535  }
2536  else if (parentOn) {
2537  //
2538  // Parent is powered on, start the power up sequence
2539  //
2541  }
2542  else {
2543  //
2544  // The call to PowerReference will bring the parent into D0 and
2545  // move us out of this state after we return.
2546  //
2547  return WdfDevStatePowerNull;
2548  }
2549 }
2550 
2554  )
2555 /*++
2556 
2557 Routine Description:
2558  This function implements the Disable Wake at Bus state.
2559 
2560 Arguments:
2561  This - instance of the state machine
2562 
2563 Return Value:
2564  WdfDevStatePowerWaking
2565 
2566 --*/
2567 {
2568  //
2569  // We should only get into this state when this devobj is not a PDO and a
2570  // power policy owner.
2571  //
2572  ASSERT((This->m_Device->IsPdo() && This->IsPowerPolicyOwner()) == FALSE);
2573 
2574  This->PowerDisableWakeAtBusOverload();
2575 
2576  return WdfDevStatePowerWaking;
2577 }
2578 
2582  )
2583 /*++
2584 
2585 Routine Description:
2586  This function implements the Disable Wake at Bus state.
2587 
2588 Arguments:
2589  This - instance of the state machine
2590 
2591 Return Value:
2592  WdfDevStatePowerWakingNP
2593 
2594 --*/
2595 {
2596  //
2597  // We should only get into this state when this devobj is not a PDO and a
2598  // power policy owner.
2599  //
2600  ASSERT((This->m_Device->IsPdo() && This->IsPowerPolicyOwner()) == FALSE);
2601 
2602  This->PowerDisableWakeAtBusOverload();
2603 
2604  return WdfDevStatePowerWakingNP;
2605 }
2606 
2610  )
2611 /*++
2612 
2613 Routine Description:
2614  State where we go into Dx in the pageable path.
2615 
2616 Arguments:
2617  The instance of this state machine
2618 
2619 Return Value:
2620  new power state
2621 
2622  --*/
2623 {
2624  This->PowerGotoDx();
2625 
2626  return WdfDevStatePowerNull;
2627 }
2628 
2632  )
2633 /*++
2634 
2635 Routine Description:
2636  State where we go into Dx in the NP path.
2637 
2638 Arguments:
2639  The instance of this state machine
2640 
2641 Return Value:
2642  new power state
2643 
2644  --*/
2645 {
2646  This->PowerGotoDx();
2647 
2648  return WdfDevStatePowerNull;
2649 }
2650 
2654  )
2655 {
2656  if (This->PowerGotoDxIoStopped() == FALSE) {
2658  }
2659 
2660  return WdfDevStatePowerDx;
2661 }
2662 
2666  )
2667 {
2668  if (This->PowerGotoDxIoStoppedNP() == FALSE) {
2670  }
2671 
2672  return WdfDevStatePowerDxNP;
2673 }
2674 
2678  )
2679 /*++
2680 
2681 Routine Description:
2682  Going to Dx in the NP path failed. Disconnect all the interrupts.
2683 
2684 Arguments:
2685  This - instance of the state machine
2686 
2687 Return Value:
2688  WdfDevStatePowerReportPowerDownFailed
2689 
2690  --*/
2691 {
2692  This->DisconnectInterruptNP();
2693 
2695 }
2696 
2697 VOID
2699  VOID
2700  )
2701 /*++
2702 
2703 Routine Description:
2704  Implements the going into Dx logic for the pageable path.
2705 
2706 Arguments:
2707  None
2708 
2709 Return Value:
2710  None
2711 
2712  --*/
2713 {
2714  if (m_SelfManagedIoMachine != NULL) {
2715  NTSTATUS status;
2716 
2717  //
2718  // Tell the driver to stop its self-managed I/O
2719  //
2721 
2722  if (!NT_SUCCESS(status)) {
2725  "EvtDeviceSelfManagedIoStop failed %!STATUS!", status);
2726 
2728  }
2729  }
2730 
2731 
2732 
2733 
2734 
2735  // Top-edge queue hold
2737 
2739 }
2740 
2741 BOOLEAN
2743  VOID
2744  )
2745 /*++
2746 
2747 Routine Description:
2748  Implements the going into Dx logic for the pageable path.
2749 
2750 
2751 
2752 Arguments:
2753  None
2754 
2755 Return Value:
2756  TRUE if the power down succeeded, FALSE otherwise
2757 
2758  --*/
2759 {
2761  NTSTATUS status;
2762  BOOLEAN failed;
2763  FxIrp irp;
2764  ULONG notifyFlags;
2765 
2766  failed = FALSE;
2767 
2768  //
2769  // First determine the state that will be indicated to the driver
2770  //
2772 
2773  switch (irp.GetParameterPowerShutdownType()) {
2774  case PowerActionShutdown:
2778  break;
2779 
2780  default:
2782  break;
2783  }
2784 
2785  //
2786  // Can we even be a power pageable device and be in hibernation path?
2787  //
2790  COVERAGE_TRAP();
2791 
2792  //
2793  // This device is in the hibernation path and the target system state is
2794  // S4. Tell the driver that it should do special handling.
2795  //
2797  }
2798 
2799  if (PowerDmaPowerDown() == FALSE) {
2800  failed = TRUE;
2801  }
2802 
2804  m_Device->GetHandle(),
2805  state
2806  );
2807 
2808  if (!NT_SUCCESS(status)) {
2809  failed = TRUE;
2810 
2813  "EvtDeviceD0ExitPreInterruptsDisabled WDFDEVICE 0x%p !devobj 0x%p, "
2814  "new state %!WDF_POWER_DEVICE_STATE! failed, %!STATUS!",
2815  m_Device->GetHandle(),
2817  }
2818 
2819  //
2820  // interrupt disable & disconnect
2821  //
2822 
2823  notifyFlags = NotifyResourcesExplicitPowerDown;
2824 
2825  //
2826  // In general, m_WaitWakeIrp is accessed through guarded InterlockedExchange
2827  // operations. However, following is a special case where we just want to know
2828  // the current value. It is possible that the value of m_WaitWakeIrp can
2829  // change right after we query it. Users of NotifyResourcesArmedForWake will
2830  // need to be aware of this fact.
2831  //
2832  // Note that relying on m_WaitWakeIrp to decide whether to disconnect the wake
2833  // interrupts or not is unreliable and may result in a race condition between
2834  // the device powering down and a wake interrupt firing:
2835  //
2836  // Thread A: Device is powering down and is going to disconnect wake interrupts
2837  // unless m_WaitWakeIrp is not NULL.
2838  // Thread B: Wake interrupt fires (holding the OS interrupt lock) which results
2839  // in completing the IRP_MN_WAIT_WAKE and setting m_WaitWakeIrp to NULL.
2840  // Thread then blocks waiting for the device to power up.
2841  // Thread A: m_WaitWakeIrp is NULL so we disconnect the wake interrupt, but are
2842  // blocked waiting to acquire the lock held by the ISR. The deadlock
2843  // results in bugcheck 0x9F since the Dx IRP is being blocked.
2844  //
2845  // The m_WakeInterruptsKeepConnected flag is set when we request a IRP_MN_WAIT_WAKE
2846  // in the device powering down path, and is cleared below once it is used.
2847  //
2849  notifyFlags |= NotifyResourcesArmedForWake;
2851  }
2852 
2853  status = NotifyResourceObjectsDx(notifyFlags);
2854  if (!NT_SUCCESS(status)) {
2855  //
2856  // NotifyResourceObjectsDx already traced the error
2857  //
2858  failed = TRUE;
2859  }
2860 
2861  //
2862  // Call the driver to tell it to put the hardware into a sleeping
2863  // state.
2864  //
2865 
2867 
2868  if (!NT_SUCCESS(status)) {
2871  "EvtDeviceD0Exit WDFEVICE 0x%p !devobj 0x%p, new state "
2872  "%!WDF_POWER_DEVICE_STATE! failed, %!STATUS!",
2873  m_Device->GetHandle(),
2875 
2876  failed = TRUE;
2877  }
2878 
2879  //
2880  // If this is a child, release the power reference on the parent
2881  //
2883 
2884  //
2885  // Set our state no matter if power down failed or not
2886  //
2888 
2889  //
2890  // Stopping self managed io previously failed, convert that failure into
2891  // a local failure here.
2892  //
2895  failed = TRUE;
2896  }
2897 
2898  if (failed) {
2899  //
2900  // Power policy will use this property when it is processing the
2901  // completion of the Dx irp.
2902  //
2904 
2905  //
2906  // This state will record that we encountered an internal error.
2907  //
2908  return FALSE;
2909  }
2910 
2912 
2914 
2915  return TRUE;
2916 }
2917 
2918 BOOLEAN
2920  VOID
2921  )
2922 /*++
2923 
2924 Routine Description:
2925  This function implements going into the Dx state in the NP path.
2926 
2927 Arguments:
2928  None
2929 
2930 Return Value:
2931  TRUE if the power down succeeded, FALSE otherwise
2932 
2933  --*/
2934 {
2936  NTSTATUS status;
2937  BOOLEAN failed;
2938  FxIrp irp;
2939 
2940  failed = FALSE;
2941 
2942  //
2943  // First determine the state that will be indicated to the driver
2944  //
2946 
2947  switch (irp.GetParameterPowerShutdownType()) {
2948  case PowerActionShutdown:
2952  break;
2953 
2954  default:
2956  break;
2957  }
2958 
2961  //
2962  // This device is in the hibernation path and the target system state is
2963  // S4. Tell the driver that it should do special handling.
2964  //
2966  }
2967 
2968  if (PowerDmaPowerDown() == FALSE) {
2969  failed = TRUE;
2970  }
2971 
2973  m_Device->GetHandle(),
2974  state
2975  );
2976 
2977  if (!NT_SUCCESS(status)) {
2978  failed = TRUE;
2979 
2982  "EvtDeviceD0ExitPreInterruptsDisabled WDFDEVICE 0x%p !devobj 0x%p, "
2983  "new state %!WDF_POWER_DEVICE_STATE! failed, %!STATUS!",
2984  m_Device->GetHandle(),
2986  }
2987 
2988  //
2989  // Interrupt disable (and NO disconnect)
2990  //
2992 
2993  if (!NT_SUCCESS(status)) {
2994  //
2995  // NotifyResourceObjectsDx already traced the error
2996  //
2997  failed = TRUE;
2998  }
2999 
3000  //
3001  // Call the driver to tell it to put the hardware into a sleeping
3002  // state.
3003  //
3004 
3006 
3007  if (!NT_SUCCESS(status)) {
3010  "EvtDeviceD0Exit WDFDEVICE 0x%p !devobj 0x%p, new state "
3011  "%!WDF_POWER_DEVICE_STATE! failed, %!STATUS!",
3012  m_Device->GetHandle(),
3014 
3015  failed = TRUE;
3016  }
3017 
3018  //
3019  // If this is a child, release the power reference on the parent
3020  //
3022 
3023  //
3024  // Set our state no matter if power down failed or not
3025  //
3027 
3028  //
3029  // Stopping self managed io previously failed, convert that failure into
3030  // a local failure here.
3031  //
3034  failed = TRUE;
3035  }
3036 
3037  if (failed) {
3038  //
3039  // Power policy will use this property when it is processing the
3040  // completion of the Dx irp.
3041  //
3043 
3044  //
3045  // This state will record that we encountered an internal error.
3046  //
3047  return FALSE;
3048  }
3049 
3051 
3053 
3054  return TRUE;
3055 }
3056 
3060  )
3061 /*++
3062 
3063 Routine Description:
3064  This function implements the Dx state when we are armed for wake.
3065 
3066 Arguments:
3067  This - The instance of the state machine
3068 
3069 Return Value:
3070 
3071  new power state
3072 
3073 --*/
3074 {
3075  This->PowerGotoDx();
3076 
3077  return WdfDevStatePowerNull;
3078 }
3079 
3083  )
3084 /*++
3085 
3086 Routine Description:
3087  This function implements the Dx state when we are armed for wake in the NP
3088  path.
3089 
3090 Arguments:
3091  This - The instance of the state machine
3092 
3093 Return Value:
3094 
3095  new power state
3096 
3097 --*/
3098 {
3099  This->PowerGotoDx();
3100 
3101  return WdfDevStatePowerNull;
3102 }
3103 
3107  )
3108 {
3109  if (This->PowerGotoDxIoStopped() == FALSE) {
3111  }
3112 
3114 }
3115 
3119  )
3120 {
3121  if (This->PowerGotoDxIoStoppedNP() == FALSE) {
3123  }
3124 
3126 }
3127 
3131  )
3132 /*++
3133 
3134 Routine Description:
3135  The PDO was armed for wake in Dx and needs to be disarmed at the bus level.
3136  The child can only be disarmed while the parent is in D0, so check the state
3137  of the parent. If in D0, move directly to the disarm state, otherwise move
3138  into a wait state and disarm once the parent is in D0.
3139 
3140 Arguments:
3141  This - instance of the state machine
3142 
3143 Return Value:
3144  new state
3145 
3146  --*/
3147 
3148 {
3149  NTSTATUS status;
3150  BOOLEAN parentOn;
3151 
3152  status = This->PowerCheckParentOverload(&parentOn);
3153 
3154  if (!NT_SUCCESS(status)) {
3155  return WdfDevStatePowerUpFailed;
3156  }
3157  else if (parentOn) {
3159  }
3160  else {
3162  }
3163 }
3164 
3168  )
3169 /*++
3170 
3171 Routine Description:
3172  Same as PowerCheckParentStateArmedForWake, but we are in the NP path
3173 
3174 Arguments:
3175  This - instance of the state machine
3176 
3177 Return Value:
3178  new state
3179 
3180  --*/
3181 {
3182  NTSTATUS status;
3183  BOOLEAN parentOn;
3184 
3185  status = This->PowerCheckParentOverload(&parentOn);
3186 
3187  if (!NT_SUCCESS(status)) {
3189  }
3190  else if (parentOn) {
3192  }
3193  else {
3195  }
3196 }
3197 
3201  )
3202 /*++
3203 
3204 Routine Description:
3205  This function implements the Start Self-Managed I/O state. It tells the
3206  driver that it can resume operations that were not interlocked with
3207  the PnP and Power state machines.
3208 
3209 Arguments:
3210  This - The instance of the state machine
3211 
3212 Return Value:
3213 
3214  new power state
3215 
3216 --*/
3217 {
3218 
3219 
3220 
3221 
3222 
3223  // Top-edge queue release
3224  This->m_Device->m_PkgIo->ResumeProcessingForPower();
3225 
3226  if (This->m_SelfManagedIoMachine != NULL) {
3227  NTSTATUS status;
3228 
3229  status = This->m_SelfManagedIoMachine->Start();
3230 
3231  if (!NT_SUCCESS(status)) {
3233  This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
3234  "EvtDeviceSelfManagedIoRestart failed - %!STATUS!", status);
3235 
3237  }
3238  }
3239 
3240  This->PowerSetDevicePowerState(WdfPowerDeviceD0);
3241 
3242  //
3243  // Send the PowerUp event to both the PnP and the Power Policy state
3244  // machines.
3245  //
3246  This->PowerSendPowerUpEvents();
3247 
3248  This->PowerReleasePendingDeviceIrp();
3249 
3250  if (This->m_SharedPower.m_WaitWakeOwner) {
3252  }
3253  else {
3254  return WdfDevStatePowerD0;
3255  }
3256 }
3257 
3261  )
3262 /*++
3263 
3264 Routine Description:
3265  This function implements the Start Self-Managed I/O state. It tells the
3266  driver that it can resume operations that were not interlocked with
3267  the PnP and Power state machines.
3268 
3269 Arguments:
3270  This - The instance of the state machine
3271 
3272 Return Value:
3273 
3274  new power state
3275 
3276 --*/
3277 {
3278 
3279 
3280 
3281 
3282 
3283  // Top-edge queue release
3284  This->m_Device->m_PkgIo->ResumeProcessingForPower();
3285 
3286  if (This->m_SelfManagedIoMachine != NULL) {
3287  NTSTATUS status;
3288 
3289  status = This->m_SelfManagedIoMachine->Start();
3290 
3291  if (!NT_SUCCESS(status)) {
3293  This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
3294  "EvtDeviceSelfManagedIoRestart failed - %!STATUS!", status);
3295 
3297  }
3298  }
3299 
3300  This->PowerSetDevicePowerState(WdfPowerDeviceD0);
3301 
3302  //
3303  // Send the PowerUp event to both the PnP and the Power Policy state machines.
3304  //
3305  This->PowerSendPowerUpEvents();
3306 
3307  This->PowerReleasePendingDeviceIrp();
3308 
3309  if (This->m_SharedPower.m_WaitWakeOwner) {
3311  }
3312  else {
3313  return WdfDevStatePowerD0NP;
3314  }
3315 }
3316 
3320  )
3321 /*++
3322 
3323 Routine Description:
3324  Starting self managed io back up from an explicit Dx to D0 transition failed.
3325  Hold the power managed queues and proceed down the power up failure path.
3326 
3327 Arguments:
3328  This - instance of the state machine
3329 
3330 Return Value:
3331  WdfDevStatePowerWakingDmaEnableFailed
3332 
3333  --*/
3334 {
3335 
3336 
3337 
3338 
3339  This->m_Device->m_PkgIo->StopProcessingForPower(FxIoStopProcessingForPowerHold);
3340 
3342 }
3343 
3347  )
3348 /*++
3349 
3350 Routine Description:
3351  Starting self managed io back up from an explicit Dx to D0 transition failed.
3352  Hold the power managed queues and proceed down the power up failure path.
3353 
3354 Arguments:
3355  This - instance of the state machine
3356 
3357 Return Value:
3358  WdfDevStatePowerWakingDmaEnableFailedNP
3359 
3360  --*/
3361 {
3362 
3363 
3364 
3365 
3366  This->m_Device->m_PkgIo->StopProcessingForPower(FxIoStopProcessingForPowerHold);
3367 
3369 }
3370 
3371 
3375  )
3376 /*++
3377 
3378 Routine Description:
3379  State that indicates a successful wake from Dx. Primarily exists so that
3380  the driver writer can register to know about the entrance into this state.
3381  It also completes the pended wait wake request (which posts the appopriate
3382  events to the power policy state machine if it's listening).
3383 
3384 Arguments:
3385  This - The instance of the state machine
3386 
3387 Return Value:
3388  return WdfDevStatePowerNull
3389 
3390  --*/
3391 {
3392  This->PowerCompletePendedWakeIrp();
3393  return WdfDevStatePowerNull;
3394 }
3395 
3399  )
3400 /*++
3401 
3402 Routine Description:
3403  State that indicates a successful wake from Dx. Primarily exists so that
3404  the driver writer can register to know about the entrance into this state.
3405  It also completes the pended wait wake request (which posts the appopriate
3406  events to the power policy state machine if it's listening).
3407 
3408 Arguments:
3409  This - The instance of the state machine
3410 
3411 Return Value:
3412  return WdfDevStatePowerNull
3413 
3414  --*/
3415 {
3416  This->PowerCompletePendedWakeIrp();
3417  return WdfDevStatePowerNull;
3418 }
3419 
3423  )
3424 /*++
3425 
3426 Routine Description:
3427  This function implements the Waking state. Its job is to call into the
3428  driver to tell it to restore its hardware, and then to connect interrupts
3429  and release the queues.
3430 
3431 Arguments:
3432  This - The instance of the state machine
3433 
3434 Return Value:
3435 
3436  new power state
3437 
3438 --*/
3439 {
3440  NTSTATUS status;
3441 
3442  //
3443  // m_DevicePowerState is the "old" state because we update it after the
3444  // D0Entry callback in SelfManagedIo or PowerPolicyStopped
3445  //
3446  status = This->m_DeviceD0Entry.Invoke(
3447  This->m_Device->GetHandle(),
3448  (WDF_POWER_DEVICE_STATE) This->m_DevicePowerState);
3449 
3450  if (!NT_SUCCESS(status)) {
3452  This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
3453  "EvtDeviceD0Entry WDFDEVICE 0x%p !devobj 0x%p, old state "
3454  "%!WDF_POWER_DEVICE_STATE! failed, %!STATUS!",
3455  This->m_Device->GetHandle(),
3456  This->m_Device->GetDeviceObject(),
3457  This->m_DevicePowerState, status);
3458 
3460  }
3461 
3463 }
3464 
3465 
3469  )
3470 /*++
3471 
3472 Routine Description:
3473  This function implements the WakingNP state. Its job is to call into the
3474  driver to tell it to restore its hardware and release the queues.
3475 
3476 Arguments:
3477  This - The instance of the state machine
3478 
3479 Return Value:
3480 
3481  new power state
3482 
3483 --*/
3484 {
3485  NTSTATUS status;
3486 
3487  //
3488  // m_DevicePowerState is the "old" state because we update it after the
3489  // D0Entry callback in SelfManagedIoNP or PowerPolicyStopped
3490  //
3491  status = This->m_DeviceD0Entry.Invoke(
3492  This->m_Device->GetHandle(),
3493  (WDF_POWER_DEVICE_STATE) This->m_DevicePowerState);
3494 
3495  if (!NT_SUCCESS(status)) {
3497  This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
3498  "EvtDeviceD0Entry WDFDEVICE 0x%p !devobj 0x%p, old state "
3499  "%!WDF_POWER_DEVICE_STATE! failed, %!STATUS!",
3500  This->m_Device->GetHandle(),
3501  This->m_Device->GetDeviceObject(),
3502  This->m_DevicePowerState, status);
3503 
3505  }
3506 
3508 }
3509 
3513  )
3514 /*++
3515 
3516 Routine Description:
3517  The device is returning to D0 in the power pageable path. Connect and
3518  enable the interrupts. If that succeeds, scan for children and then
3519  open the power managed I/O queues.
3520 
3521 Arguments:
3522  This - instance of the state machine
3523 
3524 Return Value:
3525  new state
3526 
3527  --*/
3528 {
3529  NTSTATUS status;
3530 
3531  //
3532  // interrupt connect and enable
3533  //
3534  status = This->NotifyResourceObjectsD0(NotifyResourcesExplicitPowerup);
3535 
3536  if (!NT_SUCCESS(status)) {
3538  }
3539 
3540  status = This->m_DeviceD0EntryPostInterruptsEnabled.Invoke(
3541  This->m_Device->GetHandle(),
3542  (WDF_POWER_DEVICE_STATE) This->m_DevicePowerState);
3543 
3544  if (!NT_SUCCESS(status)) {
3546  This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
3547  "EvtDeviceD0EntryPostInterruptsEnabed WDFDEVICE 0x%p !devobj 0x%p, "
3548  "old state %!WDF_POWER_DEVICE_STATE! failed, %!STATUS!",
3549  This->m_Device->GetHandle(),
3550  This->m_Device->GetDeviceObject(),
3551  This->m_DevicePowerState, status);
3553  }
3554 
3556 }
3557 
3561  )
3562 /*++
3563 
3564 Routine Description:
3565  The device is returning to D0 in the power pageable path.
3566  Enable the interrupts. If that succeeds, scan for children and then
3567  open the power managed I/O queues.
3568 
3569 Arguments:
3570  This - instance of the state machine
3571 
3572 Return Value:
3573  new state
3574 
3575  --*/
3576 {
3577  NTSTATUS status;
3578 
3579  //
3580  // interrupt enable (already connected b/c they were never disconnected
3581  // during the Dx transition).
3582  //
3583  status = This->NotifyResourceObjectsD0(NotifyResourcesNP);
3584 
3585  if (!NT_SUCCESS(status)) {
3587  }
3588 
3589  status = This->m_DeviceD0EntryPostInterruptsEnabled.Invoke(
3590  This->m_Device->GetHandle(),
3591  (WDF_POWER_DEVICE_STATE) This->m_DevicePowerState);
3592 
3593  if (!NT_SUCCESS(status)) {
3595  This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
3596  "EvtDeviceD0EntryPostInterruptsEnabed WDFDEVICE 0x%p !devobj 0x%p, "
3597  "old state %!WDF_POWER_DEVICE_STATE! failed, %!STATUS!",
3598  This->m_Device->GetHandle(),
3599  This->m_Device->GetDeviceObject(),
3600  This->m_DevicePowerState, status);
3602  }
3603 
3605 }
3606 
3610  )
3611 /*++
3612 
3613 Routine Description:
3614  Connecting or enabling the interrupts failed. Disable and disconnect any
3615  interrupts which have been connected and maybe enabled.
3616 
3617 Arguments:
3618  This - instance of the state machine
3619 
3620 Return Value:
3621  WdfDevStatePowerReportPowerUpFailed
3622 
3623  --*/
3624 {
3625  This->PowerConnectInterruptFailed();
3626 
3628 }
3629 
3633  )
3634 /*++
3635 
3636 Routine Description:
3637  Enabling the interrupts failed. Disable and disconnect any
3638  interrupts which have been connected and maybe enabled.
3639 
3640 Arguments:
3641  This - instance of the state machine
3642 
3643 Return Value:
3644  WdfDevStatePowerReportPowerUpFailed
3645 
3646  --*/
3647 {
3648  //
3649  // PowerConnectInterruptFailed will call IoDisconnectInterrupt. Since we
3650  // are in the NP path, this may cause a deadlock between this thread and
3651  // paging I/O. Log something to the IFR so that if the watchdog timer kicks
3652  // in, at least we have context as to why we died.
3653  //
3655  This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
3656  "Force disconnecting interupts on !devobj %p, WDFDEVICE %p",
3657  This->m_Device->GetDeviceObject(),
3658  This->m_Device->GetHandle());
3659 
3660  This->PowerConnectInterruptFailed();
3661 
3663 }
3664 
3665 BOOLEAN
3667  __in BOOLEAN ImplicitPowerUp
3668  )
3669 {
3671 
3672  if (PowerDmaPowerUp() == FALSE) {
3673  return FALSE;
3674  }
3675 
3676  if (m_EnumInfo != NULL) {
3677  //
3678  // Scan for children
3679  //
3681 
3682  ple = NULL;
3683  while ((ple = m_EnumInfo->m_ChildListList.GetNextEntry(ple)) != NULL) {
3684  ((FxChildList*) ple->GetTransactionedObject())->ScanForChildren();
3685  }
3686 
3688  }
3689 
3690  if (ImplicitPowerUp == FALSE) {
3692  }
3693 
3694  return TRUE;
3695 }
3696 
3700  )
3701 /*++
3702 
3703 Routine Description:
3704  The device is returning to D0 from Dx. Power up all DMA enablers and scan
3705  for children.
3706 
3707 Arguments:
3708  This - instance of the state machine
3709 
3710 Return Value:
3711  new machine state
3712 
3713  --*/
3714 {
3715  if (This->PowerDmaEnableAndScan(FALSE) == FALSE) {
3717  }
3718 
3719  //
3720  // Return the state that we should drop into next.
3721  //
3722  return WdfDevStatePowerNull;
3723 }
3724 
3728  )
3729 /*++
3730 
3731 Routine Description:
3732  The device is returning to D0 from Dx in the NP path. Power up all DMA
3733  enablers and scan for children.
3734 
3735 Arguments:
3736  This - instance of the state machine
3737 
3738 Return Value:
3739  new machine state
3740 
3741  --*/
3742 {
3743  if (This->PowerDmaEnableAndScan(FALSE) == FALSE) {
3745  }
3746 
3747  //
3748  // Return the state that we should drop into next.
3749  //
3750  return WdfDevStatePowerNull;
3751 }
3752 
3756  )
3757 /*++
3758 
3759 Routine Description:
3760  Powering up a DMA enabler failed. Power down all DMA enablers and progress
3761  down the failed power up path.
3762 
3763 Arguments:
3764  This - instance of the state machine
3765 
3766 Return Value:
3767  WdfDevStatePowerWakingConnectInterruptFailed
3768 
3769  --*/
3770 {
3771  NTSTATUS status;
3772 
3773  (void) This->PowerDmaPowerDown();
3774 
3775  status = This->m_DeviceD0ExitPreInterruptsDisabled.Invoke(
3776  This->m_Device->GetHandle(),
3778  );
3779 
3780  if (!NT_SUCCESS(status)) {
3781  //
3782  // Report the error, but continue forward
3783  //
3785  This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
3786  "EvtDeviceD0ExitPreInterruptsDisabled WDFDEVICE 0x%p !devobj 0x%p "
3787  "new state %!WDF_POWER_DEVICE_STATE! failed, %!STATUS!",
3788  This->m_Device->GetHandle(),
3789  This->m_Device->GetDeviceObject(),
3791  }
3792 
3794 }
3795 
3799  )
3800 /*++
3801 
3802 Routine Description:
3803  Powering up a DMA enabler failed in the NP path. Power down all DMA
3804  enablers and progress down the failed power up path.
3805 
3806 Arguments:
3807  This - instance of the state machine
3808 
3809 Return Value:
3810  WdfDevStatePowerWakingConnectInterruptFailedNP
3811 
3812  --*/
3813 {
3814  NTSTATUS status;
3815 
3816  COVERAGE_TRAP();
3817 
3818  (void) This->PowerDmaPowerDown();
3819 
3820  status = This->m_DeviceD0ExitPreInterruptsDisabled.Invoke(
3821  This->m_Device->GetHandle(),
3823  );
3824 
3825  if (!NT_SUCCESS(status)) {
3826  //
3827  // Report the error, but continue forward
3828  //
3830  This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
3831  "EvtDeviceD0ExitPreInterruptsDisabled WDFDEVICE 0x%p !devobj 0x%p "
3832  "new state %!WDF_POWER_DEVICE_STATE! failed, %!STATUS!",
3833  This->m_Device->GetHandle(),
3834  This->m_Device->GetDeviceObject(),
3836  }
3837 
3839 }
3840 
3844  )
3845 /*++
3846 
3847 Routine Description:
3848  Power up failed. Release the reference on the parent that was taken at the
3849  start of power up.
3850 
3851 Arguments:
3852  This - instance of the state machine.
3853 
3854 Return Value:
3855  WdfDevStatePowerInitialPowerUpFailed
3856 
3857  --*/
3858 {
3859  //
3860  // If this is a child, release the power reference on the parent
3861  //
3862  This->PowerParentPowerDereference();
3863 
3865 }
3866 
3870  )
3871 /*++
3872 
3873 Routine Description:
3874  Posts PowerUpFailed event to the PnP state machine and then waits for death.
3875  The pended Power IRP is also completed.
3876 
3877 Arguments:
3878  This - The instance of the state machine
3879 
3880 Return Value:
3881  new power state
3882 
3883  --*/
3884 {
3885  This->m_SystemPowerAction = PowerActionNone;
3886 
3887  This->PowerReleasePendingDeviceIrp();
3888  This->PowerSendPowerUpFailureEvent();
3889 
3890  return WdfDevStatePowerNull;
3891 }
3892 
3896  )
3897 /*++
3898 
3899 Routine Description:
3900  We failed to power up/down properly and now the power policy state machine wants
3901  to power down the device. Since power policy and pnp rely on power posting
3902  power down events to make forward progress, we must do that here
3903 
3904 Arguments:
3905  This - instance of the state machine
3906 
3907 Return Value:
3908  WdfDevStatePowerStopped
3909 
3910  --*/
3911 {
3912  //
3913  // Even though we failed power up and never really powered down, record our
3914  // state as powered down, so that if we are restarted (can easily happen for
3915  // a PDO), we have the correct previous state.
3916  //
3917  This->PowerSetDevicePowerState(WdfPowerDeviceD3Final);
3918 
3919  This->PowerSendPowerDownEvents(FxPowerDownTypeImplicit);
3920 
3921  return WdfDevStatePowerStopped;
3922 }
3923 
3927  )
3928 /*++
3929 
3930 Routine Description:
3931  Posts PowerDownFailed event to the PnP state machine and then waits for death.
3932  The pended Power IRP is also completed.
3933 
3934 Arguments:
3935  This - The instance of the state machine
3936 
3937 Return Value:
3938  WdfDevStatePowerNull
3939 
3940  --*/
3941 {
3942 
3943 
3944 
3945 
3946  This->PowerReleasePendingDeviceIrp();
3947  This->PowerSendPowerDownFailureEvent(FxPowerDownTypeExplicit);
3948 
3949  return WdfDevStatePowerNull;
3950 }
3951 
3955  )
3956 /*++
3957 
3958 Routine Description:
3959  When bringing the device out of the D3 final state, connecting or enabling
3960  the interrupts failed. Disconnect and disable any interrupts which are
3961  connected and possibly enabled.
3962 
3963 Arguments:
3964  This - instance of the state machine
3965 
3966 Return Value:
3967  WdfDevStatePowerInitialPowerUpFailedDerefParent
3968 
3969  --*/
3970 {
3971  This->PowerConnectInterruptFailed();
3972 
3974 }
3975 
3976 
3980  )
3981 /*++
3982 
3983 Routine Description:
3984  Initial power up of the device failed while enabling DMA. Disable any
3985  started DMA enablers and proceed down the initial power up failure path.
3986 
3987 Arguments:
3988  This - instance of the state machine
3989 
3990 Return Value:
3991  WdfDevStatePowerInitialConnectInterruptFailed
3992 
3993  --*/
3994 {
3995  NTSTATUS status;
3996 
3997  (void) This->PowerDmaPowerDown();
3998 
3999  status = This->m_DeviceD0ExitPreInterruptsDisabled.Invoke(
4000  This->m_Device->GetHandle(),
4002  );
4003 
4004  if (!NT_SUCCESS(status)) {
4005  //
4006  // Report the error, but continue forward
4007  //
4009  This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
4010  "EvtDeviceD0ExitPreInterruptsDisabled WDFDEVICE 0x%p !devobj 0x%p "
4011  "new state %!WDF_POWER_DEVICE_STATE! failed, %!STATUS!",
4012  This->m_Device->GetHandle(),
4013  This->m_Device->GetDeviceObject(),
4015  }
4016 
4018 }
4019 
4023  )
4024 /*++
4025 
4026 Routine Description:
4027  The self managed io start failed when bringing the device out of Dx with an
4028  implicit D0 transition. Hold the power queues that were previous open can
4029  continue to cleanup
4030 
4031 Arguments:
4032  This - instance of the state machine
4033 
4034 Return Value:
4035  WdfDevStatePowerInitialDmaEnableFailed
4036 
4037  --*/
4038 {
4039 
4040 
4041 
4042 
4043  This->m_Device->m_PkgIo->StopProcessingForPower(FxIoStopProcessingForPowerHold);
4044 
4046 }
4047 
4051  )
4052 /*++
4053 
4054 Routine Description:
4055  Dereferences the parent's power ref count we took during start up
4056 
4057 Arguments:
4058  This - The instance of the state machine
4059 
4060 Return Value:
4061  WdfDevStatePowerInitialPowerUpFailed
4062 
4063  --*/
4064 {
4065 
4066  //
4067  // If this is a child, release the power reference on the parent
4068  //
4069  This->PowerParentPowerDereference();
4070 
4072 }
4073 
4077  )
4078 /*++
4079 
4080 Routine Description:
4081  Posts PowerUpFailed event to the PnP state machine and then waits for death.
4082 
4083 Arguments:
4084  This - The instance of the state machine
4085 
4086 Return Value:
4087  WdfDevStatePowerStopped
4088 
4089  --*/
4090 {
4091  This->PowerSendPowerUpFailureEvent();
4092 
4093  return WdfDevStatePowerStopped;
4094 }
4095 
4099  )
4100 /*++
4101 
4102 Routine Description:
4103  Disarms the device from wake because the device is being stopped/removed
4104  while in Dx.
4105 
4106 Arguments:
4107  This - instance of the state machine
4108 
4109 Return Value:
4110  WdfDevStatePowerDxStopped
4111 
4112  --*/
4113 {
4114  //
4115  // We should only get into this state when this devobj is not a PDO and a
4116  // power policy owner.
4117  //
4118  ASSERT((This->m_Device->IsPdo() && This->IsPowerPolicyOwner()) == FALSE);
4119 
4120  This->PowerDisableWakeAtBusOverload();
4121 
4123 }
4124 
4128  )
4129 /*++
4130 
4131 Routine Description:
4132  Disarms the device from wake because the device is being stopped/removed
4133  while in Dx.
4134 
4135 Arguments:
4136  This - instance of the state machine
4137 
4138 Return Value:
4139  WdfDevStatePowerGotoDxStoppedDisableInterruptNP
4140 
4141  --*/
4142 {
4143  //
4144  // We should only get into this state when this devobj is not a PDO and a
4145  // power policy owner.
4146  //
4147  ASSERT((This->m_Device->IsPdo() && This->IsPowerPolicyOwner()) == FALSE);
4148 
4149  This->PowerDisableWakeAtBusOverload();
4150 
4152 }
4153 
4157  )
4158 /*++
4159 
4160 Routine Description:
4161  Device is in Dx and was implicitly powered down. Disable the interrupt since
4162  the interrupt was not disconnected in the NP power down path.
4163 
4164 Arguments:
4165  This - instance of the state machine
4166 
4167 Return Value:
4168  WdfDevStatePowerGotoDxStopped
4169 
4170  --*/
4171 {
4172  This->NotifyResourceObjectsDx(NotifyResourcesSurpriseRemoved);
4173 
4175 }
4176 
4180  )
4181 /*++
4182 
4183 Routine Description:
4184  Device is in Dx and being removed/stopped. Inform the other state machines
4185  that the device is powered down so that they may continue.
4186 
4187 Arguments:
4188  This - instance of the state machine
4189 
4190 Return Value:
4191  WdfDevStatePowerStopped
4192 
4193  --*/
4194 {
4195  This->PowerSendPowerDownEvents(FxPowerDownTypeImplicit);
4196 
4197  return WdfDevStatePowerStopped;
4198 }
4199 
4203  )
4204 /*++
4205 
4206 Routine Description:
4207  We are in the Dx state and the power policy owner sent an explicit D0 irp
4208  to the stack. Transition to the stopped state which will transition to the
4209  D0 state when receiving an implicit D0.
4210 
4211 Arguments:
4212  This - instance of the state machine
4213 
4214 Return Value:
4215  WdfDevStatePowerStopped
4216 
4217  --*/
4218 {
4219  //
4220  // We should only get into this state when this devobj is not the power
4221  // policy owner.
4222  //
4223  ASSERT(This->IsPowerPolicyOwner() == FALSE);
4224 
4225  This->PowerReleasePendingDeviceIrp();
4226  return WdfDevStatePowerStopped;
4227 }
4228 
4232  )
4233 /*++
4234 
4235 Routine Description:
4236  We were in the Stopped state and the power policy owner sent an explicit
4237  Dx request to the stack. We will move to the DxStopped state where we will
4238  transition to a Dx state when an implicit D0 is received.
4239 
4240 Arguments:
4241  This - instance of the state machine
4242 
4243 Return Value:
4244  WdfDevStatePowerDxStopped
4245 
4246  --*/
4247 {
4248  //
4249  // We should only get into this state when this devobj is not the power
4250  // policy owner.
4251  //
4252  ASSERT(This->IsPowerPolicyOwner() == FALSE);
4253 
4254  This->PowerReleasePendingDeviceIrp();
4256 }
4257 
4261  )
4262 /*++
4263 
4264 Routine Description:
4265  We are implicitly powering up the stack while in the Dx state. Decide
4266  which Dx "holding" state to transition to.
4267 
4268 Arguments:
4269  This - instance of the state machine
4270 
4271 Return Value:
4272  new power state
4273 
4274  --*/
4275 {
4276  //
4277  // We should only get into this state when this devobj is not the power
4278  // policy owner.
4279  //
4280  ASSERT(This->IsPowerPolicyOwner() == FALSE);
4281 
4282  //
4283  // Move power policy back into a working state
4284  //
4285  // While it seems odd to send a power up in a Dx state, the power up is
4286  // really an indication to the power policy state machine that the implicit
4287  // D0 has been successfully processed, basically, it is a status event more
4288  // then an indication of true power state.
4289  //
4290  This->PowerSendPowerUpEvents();
4291 
4292  if (This->m_Device->GetDeviceObjectFlags() & DO_POWER_PAGABLE) {
4293  if (This->PowerIsWakeRequestPresent()) {
4294  COVERAGE_TRAP();
4296  }
4297  else {
4298  return WdfDevStatePowerDx;
4299  }
4300  }
4301  else {
4302  if (This->PowerIsWakeRequestPresent()) {
4303  COVERAGE_TRAP();
4305  }
4306  else {
4307  COVERAGE_TRAP();
4308  return WdfDevStatePowerDxNP;
4309  }
4310  }
4311 }
4312 
4316  )
4317 /*++
4318 
4319 Routine Description:
4320  We are implicitly powering the stack back up while the device is in Dx
4321  and there is a wait wake request presnt on this device. Enable wake at
4322  the bus level and then move to the appropriate state based on the enabling
4323  status.
4324 
4325 Arguments:
4326  This - instance of the state machine
4327 
4328 Return Value:
4329  new power state
4330 
4331  --*/
4332 {
4333  NTSTATUS status;
4334 
4335  COVERAGE_TRAP();
4336 
4337  //
4338  // We should only get into this state when this devobj is not a PDO and a
4339  // power policy owner.
4340  //
4341  ASSERT((This->m_Device->IsPdo() && This->IsPowerPolicyOwner()) == FALSE);
4342 
4343  status = This->PowerEnableWakeAtBusOverload();
4344 
4345  if (NT_SUCCESS(status)) {
4346  //
4347  // No matter of the irp status (canceled, pending, completed), we always
4348  // transition to the D0ArmedForWake state because that is where we
4349  // we handle the change in the irp's status.
4350  //
4351  COVERAGE_TRAP();
4353  }
4354  else {
4355  COVERAGE_TRAP();
4356  This->PowerCompleteWakeRequestFromWithinMachine(status);
4357  return WdfDevStatePowerDx;
4358  }
4359 }
4360 
4364  )
4365 /*++
4366 
4367 Routine Description:
4368  We are implicitly powering the stack back up while the device is in Dx
4369  and there is a wait wake request presnt on this device. Enable wake at
4370  the bus level and then move to the appropriate state based on the enabling
4371  status.
4372 
4373 Arguments:
4374  This - instance of the state machine
4375 
4376 Return Value:
4377  new power state
4378 
4379  --*/
4380 {
4381  NTSTATUS status;
4382 
4383  COVERAGE_TRAP();
4384 
4385  //
4386  // We should only get into this state when this devobj is not a PDO and a
4387  // power policy owner.
4388  //
4389  ASSERT((This->m_Device->IsPdo() && This->IsPowerPolicyOwner()) == FALSE);
4390 
4391  status = This->PowerEnableWakeAtBusOverload();
4392 
4393  if (NT_SUCCESS(status)) {
4394  //
4395  // No matter of the irp status (canceled, pending, completed), we always
4396  // transition to the D0ArmedForWake state because that is where we
4397  // we handle the change in the irp's status.
4398  //
4399  COVERAGE_TRAP();
4401  }
4402  else {
4403  COVERAGE_TRAP();
4404  This->PowerCompleteWakeRequestFromWithinMachine(status);
4405  return WdfDevStatePowerDxNP;
4406  }
4407 }
4408 
4412  )
4413 /*++
4414 
4415 Routine Description:
4416  Posts PowerDownFailed event to the PnP state machine and then waits for death.
4417 
4418 Arguments:
4419  This - The instance of the state machine
4420 
4421 Return Value:
4422  WdfDevStatePowerStopped
4423 
4424  --*/
4425 {
4426  This->PowerSendPowerDownFailureEvent(FxPowerDownTypeImplicit);
4427 
4428  //
4429  // If we are not the PPO for the stack we could receive a power irp
4430  // during the middle of an implicit power down so we cannot assume
4431  // that there will be no pended power irp during an implicit power down.
4432  //
4433  ASSERT(This->IsPowerPolicyOwner() ? This->m_PendingDevicePowerIrp == NULL : TRUE);
4434 
4435  return WdfDevStatePowerStopped;
4436 }
4437 
4441  )
4442 /*++
4443 
4444 Routine Description:
4445  Disconnects interrupts
4446 
4447 Arguments:
4448  This - The instance of the state machine
4449 
4450 Return Value:
4451  WdfDevStatePowerReportPowerUpFailed
4452 
4453  --*/
4454 {
4455  //
4456  // Notify the interrupt state machines that the power up failed
4457  //
4458  This->SendEventToAllWakeInterrupts(WakeInterruptEventD0EntryFailed);
4459  //
4460  // NotifyResourceObjectsDx will log any errors
4461  //
4462  (void) This->NotifyResourceObjectsDx(NotifyResourcesForceDisconnect |
4464 
4466 }
4467 
4471  )
4472 /*++
4473 
4474 Routine Description:
4475  Disconnects interrupts
4476 
4477 Arguments:
4478  This - The instance of the state machine
4479 
4480 Return Value:
4481  WdfDevStatePowerReportPowerUpFailed
4482 
4483  --*/
4484 {
4485  COVERAGE_TRAP();
4486  //
4487  // Notify the interrupt state machines that the power up failed
4488  //
4489  This->SendEventToAllWakeInterrupts(WakeInterruptEventD0EntryFailed);
4490  //
4491  // NotifyResourceObjectsDx will log any errors
4492  //
4493  (void) This->NotifyResourceObjectsDx(NotifyResourcesForceDisconnect |
4495 
4497 }
4498 
4502  )
4503 /*++
4504 
4505 Routine Description:
4506  Disconnects interrupts
4507 
4508 Arguments:
4509  This - The instance of the state machine
4510 
4511 Return Value:
4512  WdfDevStatePowerReportPowerDownFailed
4513 
4514  --*/
4515 {
4516  //
4517  // NotifyResourceObjectsDx will log any errors
4518  //
4519  (void) This->NotifyResourceObjectsDx(NotifyResourcesForceDisconnect |
4521 
4523 }
4524 
4528  )
4529 /*++
4530 
4531 Routine Description:
4532  Disconnects interrupts
4533 
4534 Arguments:
4535  This - The instance of the state machine
4536 
4537 Return Value:
4538  WdfDevStatePowerGotoDxStopped
4539 
4540  --*/
4541 {
4542  //
4543  // NotifyResourceObjectsDx will log any errors
4544  //
4545  (void) This->NotifyResourceObjectsDx(NotifyResourcesForceDisconnect |
4547 
4549 }
4550 
4554  )
4555 /*++
4556 
4557 Routine Description:
4558  Disconnects interrupts
4559 
4560 Arguments:
4561  This - The instance of the state machine
4562 
4563 Return Value:
4564  WdfDevStatePowerReportPowerUpFailed
4565 
4566  --*/
4567 {
4568  //
4569  // Notify the interrupt state machines that the power up failed
4570  //
4571  This->SendEventToAllWakeInterrupts(WakeInterruptEventD0EntryFailed);
4572  This->DisconnectInterruptNP();
4573 
4575 }
4576 
4580  )
4581 /*++
4582 
4583 Routine Description:
4584  Disconnects interrupts
4585 
4586 Arguments:
4587  This - The instance of the state machine
4588 
4589 Return Value:
4590  WdfDevStatePowerReportPowerUpFailed
4591 
4592  --*/
4593 {
4594  //
4595  // Notify the interrupt state machines that the power up failed
4596  //
4597  This->SendEventToAllWakeInterrupts(WakeInterruptEventD0EntryFailed);
4598  This->DisconnectInterruptNP();
4599 
4601 }
4602 
4606  )
4607 /*++
4608 
4609 Routine Description:
4610  Notifies the wake interrupt state machines that the device has entered
4611  D0
4612 
4613 Arguments:
4614  This - The instance of the state machine
4615 
4616 Return Value:
4617  WdfDevStatePowerWakingConnectInterrupt if there are no wake interrupts
4618  or WdfDevStatePowerNull otherwise
4619 
4620  --*/
4621 {
4622  if (This->m_WakeInterruptCount == 0) {
4624  }
4625 
4626  This->SendEventToAllWakeInterrupts(WakeInterruptEventEnteringD0);
4627 
4628  return WdfDevStatePowerNull;;
4629 }
4630 
4634  )
4635 /*++
4636 
4637 Routine Description:
4638  Notifies the wake interrupt state machines that the device is about
4639  to exit D0
4640 
4641 Arguments:
4642  This - The instance of the state machine
4643 
4644 Return Value:
4645  WdfDevStatePowerDx if there are no wake interrupts or WdfDevStatePowerNull
4646  otherwise
4647 
4648  --*/
4649 {
4650  if (This->m_WakeInterruptCount == 0) {
4652  }
4653 
4654  //
4655  // Indiciate to the wake interrupt state machine that the device is
4656  // leaving D0 and also whether the device is armed for wake. The wake
4657  // interrupt machine treats these differently as described below.
4658  //
4659  if (This->m_WakeInterruptsKeepConnected == TRUE ||
4660  This->m_SharedPower.m_WaitWakeIrp != NULL) {
4661  This->SendEventToAllWakeInterrupts(WakeInterruptEventLeavingD0);
4662  }
4663  else {
4664  //
4665  // When a wake interrupt is not armed for wake it will be disconnected
4666  // by the power state machine once the wake interrupt state machine
4667  // acknowledges the transition. If the interrupt fires between
4668  // the time this event is posted and it is disconnected, it needs to be
4669  // delivered to the driver or a deadlock could occur between PO state machine
4670  // trying to disconnect the interrupt and the wake interrupt machine
4671  // holding on to the ISR waiting for the device to return to D0 before
4672  // delivering the interrupt.
4673  //
4674  This->SendEventToAllWakeInterrupts(WakeInterruptEventLeavingD0NotArmedForWake);
4675  }
4676 
4677  return WdfDevStatePowerNull;;
4678 }
4679 
4683  )
4684 /*++
4685 
4686 Routine Description:
4687  Notifies the wake interrupt state machines that the device has entered
4688  D0
4689 
4690 Arguments:
4691  This - The instance of the state machine
4692 
4693 Return Value:
4694  WdfDevStatePowerWakingConnectInterruptNP if there are no wake interrupts
4695  or WdfDevStatePowerNull otherwise
4696 
4697  --*/
4698 {
4699  if (This->m_WakeInterruptCount == 0) {
4701  }
4702 
4703  This->SendEventToAllWakeInterrupts(WakeInterruptEventEnteringD0);
4704 
4705  return WdfDevStatePowerNull;;
4706 }
4707 
4711  )
4712 /*++
4713 
4714 Routine Description:
4715  Notifies the wake interrupt state machines that the device is about
4716  to exit D0
4717 
4718 Arguments:
4719  This - The instance of the state machine
4720 
4721 Return Value:
4722  WdfDevStatePowerDxNP if there are no wake interrupts or WdfDevStatePowerNull
4723  otherwise
4724 
4725  --*/
4726 {
4727  if (This->m_WakeInterruptCount == 0) {
4729  }
4730 
4731  //
4732  // Indiciate to the wake interrupt state machine that the device is
4733  // leaving D0 and also whether the device is armed for wake. The wake
4734  // interrupt machine treats these differently as described below
4735  //
4736  if (This->m_WakeInterruptsKeepConnected == TRUE ||
4737  This->m_SharedPower.m_WaitWakeIrp != NULL) {
4738  This->SendEventToAllWakeInterrupts(WakeInterruptEventLeavingD0);
4739  }
4740  else {
4741  //
4742  // When a wake interrupt is not armed for wake it will be disconnected by
4743  // the power state machine once the wake interrupt state machine
4744  // acknowledges the transition. If the interrupt fires between
4745  // the time this event is posted and it is disconnected, it needs to be
4746  // delivered to the driver or a deadlock could occur between PO state machine
4747  // trying to disconnect the interrupt and the wake interrupt machine holding on
4748  // to the ISR waiting for the device to return to D0 before delivering the
4749  // interrupt.
4750  //
4751  This->SendEventToAllWakeInterrupts(WakeInterruptEventLeavingD0NotArmedForWake);
4752  }
4753 
4754  return WdfDevStatePowerNull;;
4755 }
4756 
4757 VOID
4759  VOID
4760  )
4761 {
4762  //
4763  // NotifyResourceObjectsDx will call IoDisconnectInterrupt. Since we
4764  // are in the NP path, this may cause a deadlock between this thread and
4765  // paging I/O. Log something to the IFR so that if the watchdog timer kicks
4766  // in, at least we have context as to why we died.
4767  //
4770  "Force disconnecting interrupts on !devobj 0x%p, WDFDEVICE %p",
4772  m_Device->GetHandle());
4773 
4774  //
4775  // NotifyResourceObjectsDx will log any errors
4776  //
4778 }
4779 
4780 BOOLEAN
4783  )
4784 /*++
4785 
4786 Routine Description:
4787  If there is a pended wait wake request, this routine will remove the cancel
4788  routine and post the appropriate event to the power state machine. The
4789  consumer of this event will do the actual completion of the wait wake
4790  request.
4791 
4792  The difference between this routine and
4793  PowerCompleteWakeRequestFromWithinMachine is that
4794  PowerCompleteWakeRequestFromWithinMachine is a private API to the state
4795  machine and will attempt to complete the request immediately instead of
4796  deferring the completion through the posting of a power state machine event.
4797 
4798  PowerCompletePendedWakeIrp is used within the state machine to complete the
4799  IRP deferred by this routine.
4800 
4801 Arguments:
4802  WaitWakeStatus - The final status of the wait wake request
4803 
4804 Return Value:
4805  TRUE if there there was a request to cancel
4806 
4807  --*/
4808 {
4810  //
4811  // The power machine will eventually call PowerCompletePendedWakeIrp
4812  // to complete the request.
4813  //
4816  }
4817  else if (NT_SUCCESS(WaitWakeStatus)) {
4819  }
4820  else {
4822  }
4823 
4824  return TRUE;
4825  }
4826  else {
4827  return FALSE;
4828  }
4829 }
4830 
4831 VOID
4833  VOID
4834  )
4835 /*++
4836 
4837 Routine Description:
4838  Completes the wait wake request that was pended by the power state machine.
4839  It is valid if there is no request to complete (the only time there will be
4840  a request to complete is when this power state machine is the wait wake owner
4841 
4842 Arguments:
4843  None
4844 
4845 Return Value:
4846  None
4847 
4848  --*/
4849 {
4850  PLIST_ENTRY ple;
4851  KIRQL irql;
4852 
4854  COVERAGE_TRAP();
4855  return;
4856  }
4857 
4858  //
4859  // Pop an irp off of the list
4860  //
4865 
4867 
4869 
4871 }
4872 
4873 VOID
4876  )
4877 /*++
4878 
4879 Routine Description:
4880  Completes a wait wake from within the power state machine. Contrary to
4881  PowerIndicateWaitWakeStatus which posts an event to the state machine to
4882  process the irp's status change, this routine attempts to complete the
4883  irp immediately.
4884 
4885 Arguments:
4886  Status - Final status of the wake irp
4887 
4888 Return Value:
4889  None
4890 
4891  --*/
4892 {
4895  }
4896 }
4897 
4898 BOOLEAN
4901  )
4902 /*++
4903 
4904 Routine Description:
4905  Attempts to clear the cancel routine from the pended wake request. If
4906  successful, it will put the wake request on a pending wake list to be
4907  completed later by PowerCompletePendedWakeIrp .
4908 
4909 Arguments:
4910  WaitWakeStatus - final status for the wake request
4911 
4912 Return Value:
4913  TRUE if there was a request and we cleared the cancel routine, FALSE
4914  otherwise
4915 
4916  --*/
4917 {
4918  KIRQL irql;
4919  BOOLEAN result;
4920 
4921  //
4922  // Currently we assume that if we are the bus wait wake owner and that only
4923  // PDOs can be bus wake owners, so we must have a parent device.
4924  //
4926  (m_Device->m_ParentDevice != NULL));
4927 
4928  result = FALSE;
4929 
4930  //
4931  // Attempt to retrieve the wait wake irp. We can safely dereference the
4932  // PIRP in while holding the lock as long as it is not NULL.
4933  //
4935 
4936  if (m_SharedPower.m_WaitWakeIrp != NULL) {
4937  MdCancelRoutine pOldCancelRoutine;
4938  FxIrp wwIrp;
4939 
4941 
4942  pOldCancelRoutine = wwIrp.SetCancelRoutine(NULL);
4943 
4944  if (pOldCancelRoutine != NULL) {
4945  FxPkgPnp* pParentPkg;
4946 
4947  pParentPkg = m_Device->m_ParentDevice->m_PkgPnp;
4948 
4949  //
4950  // Propagate the successful wake status from the parent to this
4951  // child's WW IRP if the parent is the PPO for its stack.
4952  //
4953  if (NT_SUCCESS(WaitWakeStatus) &&
4954  pParentPkg->IsPowerPolicyOwner() &&
4956  //
4957  // The only way that m_SystemWakeSource can be TRUE is if
4958  // FxLibraryGlobals.PoGetSystemWake != NULL and if it is not
4959  // NULL, then FxLibraryGlobals.PoSetSystemWake cannot be NULL
4960  // either.
4961 
4962 
4963 
4964 
4965 
4967 
4968  //
4969  // If this PDO is the PPO for its stack, then we must mark this
4970  // device as the system wake source if we have any
4971  // enumerated PDOs off of this PDO so that we can propagate the
4972  // system wake source attribute to our children stacks.
4973  // (For a FDO which is the PPO, we do this in the WW completion
4974  // routine.)
4975  //
4976  if (IsPowerPolicyOwner()) {
4979  "WDFDEVICE 0x%p !devobj 0x%p WW !irp 0x%p is a source "
4980  "of wake", m_Device->GetHandle(),
4983 
4985  }
4986  }
4987 
4988  //
4989  // Set the status for the irp when it is completed later
4990  //
4991  wwIrp.SetStatus(WaitWakeStatus);
4992 
4993  //
4994  // Queue the irp for completion later
4995  //
4997  wwIrp.ListEntry());
4998 
4999  wwIrp.SetIrp(NULL);
5001  result = TRUE;
5002  }
5003  else {
5004  //
5005  // The irp is being canceled as we run here. As soon as the spin
5006  // lock is dropped, the cancel routine will run (or continue if it
5007  // is blocked on this lock). Do nothing here and let the cancel
5008  // routine run its course.
5009  //
5010  ASSERT(wwIrp.IsCanceled());
5011  DO_NOTHING();
5012  }
5013  }
5015 
5016  return result;
5017 }
5018 
5019 VOID
5022  )
5023 {
5024  if (IsPowerPolicyOwner()) {
5026  }
5027 }
5028 
5029 VOID
5032  )
5033 /*++
5034 
5035 Routine Description:
5036  The device has powered down, inform the power policy state machine
5037 
5038 Arguments:
5039  Type - the type of power down being performed
5040 
5041 Return Value:
5042  None
5043 
5044  --*/
5045 {
5046  //
5047  // If this is an implicit power type, there is completion routine on the
5048  // power irp and we must send these events in the power state machine
5049  // regardless if we are the PPO or not.
5050  //
5051  if (Type == FxPowerDownTypeImplicit) {
5053 
5054  //
5055  // If we are the power policy owner, there is no need to distinguish
5056  // between an implicit power down or an explicit power down since the
5057  // PPO controls all power irps in the stack and a power policy stop
5058  // (e.g. an implicit power down) will not be racing with a real power
5059  // irp.
5060  //
5061  // The non PPO state machine needs to distinguish between the 2 types
5062  // of power downs because both of them may occur simultaneously and we
5063  // don't want to interpret the power down event for the real Dx irp with
5064  // the power down event for the (final) implicit power down.
5065  //
5068  return;
5069  }
5070 
5072 
5073  //
5074  // If we are the PPO, then we will send PwrPolPowerDown in the completion
5075  // routine passed to PoRequestPowerIrp. If we are not the PPO, we must send
5076  // the event now because we have no such completion routine.
5077  //
5078  if (IsPowerPolicyOwner()) {
5079  //
5080  // Transition the idle state machine to off immediately.
5081  //
5084  );
5085  }
5086  else {
5087  //
5088  // If we are not the PPO, there is no idle state machine to send an
5089  // event to and there is no Po request completion routine to send this
5090  // event, so we send it now.
5091  //
5093  }
5094 }
5095 
5096 VOID
5098  VOID
5099  )
5100 /*++
5101 
5102 Routine Description:
5103  Sends power up events to the pnp and power policy state machines
5104 
5105 Arguments:
5106  None
5107 
5108 Return Value:
5109  None
5110 
5111  --*/
5112 {
5114 
5115  //
5116  // This must be called *before* PowerPostParentToD0ToChildren so that we
5117  // clear the child power up guard variable in the power policy state machine
5118  // and then post an event which will unblock the child.
5119  //
5121 }
5122 
5123 VOID
5126  )
5127 /*++
5128 
5129 Routine Description:
5130  Sends a power down failure event to the pnp state machine marks an internal
5131  error.
5132 
5133 Arguments:
5134  None
5135 
5136 Return Value:
5137  None
5138 
5139  --*/
5140 {
5142 
5143  if (IsPowerPolicyOwner()) {
5144  //
5145  // If we are the PPO and this is an explicit power operation, then we
5146  // will send PwrPolPowerDownFailed in the completion routine passed to
5147  // PoRequestPowerIrp. Otherwise, if this is an implicit power operation
5148  // that failed, we need to send the event now because there is no
5149  // Po completion routine to send the event later.
5150  //
5151  if (Type == FxPowerDownTypeImplicit) {
5152  //
5153  // Since there is no power irp to complete, we must send the event
5154  // now.
5155  //
5156  // We only send PwrPolImplicitPowerDownFailed if we are not the
5157  // PPO, so we can't share code with the !PPO path.
5158  //
5160  }
5161  else {
5163 
5164  //
5165  // Process the state change immediately in the idle state machine.
5166  // We should do this only on an explicit power down since the PPO
5167  // will have disabled the idle state machine before attempting an
5168  // implicit power down.
5169  //
5172  );
5173  }
5174  }
5175  else {
5176  //
5177  // We are not the PPO, so we must send the event now because we have no
5178  // such completion routine. Decide which event to send to the
5179  // !PPO state machine.
5180  //
5184  );
5185 
5186  //
5187  // Send the pnp event last becuase if we are in the middle of a Dx
5188  // transition during S0, there is no S irp to guard a pnp state change
5189  // from occurring immediately after sending this event. If we sent it
5190  // before sending the power policy message, power policy might not
5191  // transition to the failed state by the time pnp does creating a
5192  // mismatch.
5193  //
5196  }
5197  }
5198 }
5199 
5200 VOID
5202  VOID
5203  )
5204 /*++
5205 
5206 Routine Description:
5207  Sends a power up failure event to the pnp state machine marks an internal
5208  error.
5209 
5210 Arguments:
5211  None
5212 
5213 Return Value:
5214  None
5215 
5216  --*/
5217 {
5220 
5222 
5225  }
5226 }
5227 
5228 VOID
5231  )
5232 /*++
5233 
5234 Routine Description:
5235  Stores the state in the object and notifies the system of the change.
5236 
5237 Arguments:
5238  State - new device state
5239 
5240 Return Value:
5241  VOID
5242 
5243  --*/
5244 {
5245  POWER_STATE powerState;
5246 
5247  //
5248  // Remember our previous state
5249  //
5251 
5252  //
5253  // Set our new state
5254  //
5255  ASSERT(State <= 0xFF);
5257 
5258  //
5259  // Notify the system of the new power state.
5260  //
5261  switch (State) {
5262  case WdfPowerDeviceD3Final:
5264  powerState.DeviceState = PowerDeviceD3;
5265  break;
5266 
5267  case WdfPowerDeviceD0:
5269  __fallthrough;
5270 
5271  default:
5272  powerState.DeviceState = (DEVICE_POWER_STATE) State;
5273  break;
5274  }
5275 
5279  powerState);
5280 }
5281 
5282 VOID
5284  VOID
5285  )
5286 /*++
5287 
5288 Routine Description:
5289  Worker routine for all the paths where we are trying to bring the device into
5290  D0 and failed while trying to connect or enable an interrupt. This routine
5291  disables and disconnects all interrupts, calls D0Exit, and sets the device
5292  state.
5293 
5294 Arguments:
5295  This - instance of the state machine
5296 
5297 Return Value:
5298  None
5299 
5300  --*/
5301 
5302 {
5303  NTSTATUS status;
5304 
5306 
5307  if (!NT_SUCCESS(status)) {
5308  //
5309  // Report the error, but continue forward
5310  //
5313  "Interrupt(s) disconnect on WDFDEVICE %p failed, %!STATUS!",
5314  m_Device->GetHandle(), status);
5315  }
5316 
5319 
5320  if (!NT_SUCCESS(status)) {
5321  //
5322  // Report the error, but continue forward
5323  //
5326  "EvtDeviceD0Exit WDFDEVICE 0x%p !devobj 0x%p failed, %!STATUS!",
5327  m_Device->GetHandle(),
5329  }
5330 
5332 }
5333 
5334 
5335 
5336 
5337 
5338 
5339 
5340 
5341 VOID
5344  __in MdIrp Irp
5345  )
5346 /*++
5347 
5348 Routine Description:
5349  Cancel routine for the pended wait wake irp. This will post an event to
5350  the power state machine to process the cancellation under the machine's
5351  lock and complete the irp later.
5352 
5353 Arguments:
5354  DeviceObject - Instance of this state machine
5355  Irp - The wait wake request being canceled
5356 
5357 Return Value:
5358  None
5359 
5360  --*/
5361 {
5362  CfxDevice* pDevice;
5363  FxPkgPdo* pThis;
5364  FxIrp irp(Irp);
5365  KIRQL irql;
5366 
5367  //
5368  // Release the IO cancel spinlock because we use our own
5369  //
5370  Mx::ReleaseCancelSpinLock(irp.GetCancelIrql());
5371 
5373  pThis = pDevice->GetPdoPkg();
5374 
5376 
5377  //
5378  // Clear out the IRQL and set our state to disarming
5379  //
5380  pThis->m_PowerMachine.m_WaitWakeLock.Acquire(&irql);
5381 
5382  ASSERT(pThis->m_SharedPower.m_WaitWakeIrp == Irp &&
5383  pThis->m_SharedPower.m_WaitWakeIrp != NULL);
5384 
5386  irp.ListEntry());
5387 
5388  //
5389  // Set the status for the irp when it is completed later
5390  //
5392 
5393  pThis->m_SharedPower.m_WaitWakeIrp = NULL;
5394 
5395  pThis->m_PowerMachine.m_WaitWakeLock.Release(irql);
5396 
5398 }
static WDF_DEVICE_POWER_STATE PowerWakingNP(__inout FxPkgPnp *This)
POWER_STATE SetPowerState(__in POWER_STATE_TYPE Type, __in POWER_STATE State)
PLIST_ENTRY ListEntry()
Definition: fxirpum.cpp:535
POWER_ACTION GetParameterPowerShutdownType()
Definition: fxirpum.cpp:719
#define TRAP_ON_EVENT
Definition: fxpkgpnp.hpp:60
CfxDevice * m_Device
Definition: fxobject.hpp:329
#define DO_POWER_PAGABLE
UCHAR GetHead(VOID)
static WDF_DEVICE_POWER_STATE PowerGotoDxArmedForWakeNP(__inout FxPkgPnp *This)
static WDF_DEVICE_POWER_STATE PowerD0DisarmingWakeAtBusNP(__inout FxPkgPnp *This)
static WDF_DEVICE_POWER_STATE PowerGotoDxStopped(__inout FxPkgPnp *This)
VOID PowerCompletePendedWakeIrp(VOID)
CfxDevice * m_ParentDevice
Definition: fxdevice.hpp:569
VOID PowerSendPowerUpFailureEvent(VOID)
FxPnpDeviceD0Exit m_DeviceD0Exit
Definition: fxpkgpnp.hpp:4554
static WDF_DEVICE_POWER_STATE PowerStartSelfManagedIoFailed(__inout FxPkgPnp *This)
VOID Invoke(__in WDF_DEVICE_POWER_STATE State, __in WDF_STATE_NOTIFICATION_TYPE Type, __in WDFDEVICE Device, __in PCWDF_DEVICE_POWER_NOTIFICATION_DATA NotificationData)
virtual VOID PowerReleasePendingDeviceIrp(BOOLEAN IrpMustBePresent=TRUE)=0
static MdIrp GetIrpFromListEntry(__in PLIST_ENTRY Ple)
Definition: fxirpum.cpp:1190
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
static WDF_DEVICE_POWER_STATE PowerStartingCheckDeviceType(__inout FxPkgPnp *This)
static WDF_DEVICE_POWER_STATE PowerNotifyingD0ExitToWakeInterruptsNP(__inout FxPkgPnp *This)
MdDeviceObject __inline GetDeviceObject(VOID)
Definition: fxdevice.hpp:174
static WDF_DEVICE_POWER_STATE PowerNotifyingD0ExitToWakeInterrupts(__inout FxPkgPnp *This)
static const POWER_EVENT_TARGET_STATE m_PowerDNotZeroOtherStates[]
Definition: fxpkgpnp.hpp:4414
static VOID _PowerProcessEventInner(__in FxPkgPnp *This, __in FxPostProcessInfo *Info, __in PVOID WorkerContext)
VOID SetStatus(__in NTSTATUS Status)
Definition: fxirpum.cpp:457
static WDF_DEVICE_POWER_STATE PowerGotoDxIoStoppedArmedForWake(__inout FxPkgPnp *This)
GLuint64EXT * result
Definition: glext.h:11304
static WDF_DEVICE_POWER_STATE PowerGotoDxFailed(__inout FxPkgPnp *This)
VOID PnpProcessEvent(__in FxPnpEvent Event, __in BOOLEAN ProcessEventOnDifferentThread=FALSE)
static WDF_DEVICE_POWER_STATE PowerWakingConnectInterruptNP(__inout FxPkgPnp *This)
static WDF_DEVICE_POWER_STATE PowerNotifyingD0EntryToWakeInterrupts(__inout FxPkgPnp *This)
#define TRUE
Definition: types.h:120
USHORT History[PowerEventQueueDepth]
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
WDFDEVICE __inline GetHandle(VOID)
Definition: fxdevice.hpp:237
static WDF_DEVICE_POWER_STATE PowerWakingDmaEnableNP(__inout FxPkgPnp *This)
static WDF_DEVICE_POWER_STATE PowerReportPowerUpFailedDerefParent(__inout FxPkgPnp *This)
static VOID _PowerSetSystemWakeSource(__in FxIrp *Irp)
WDFCASSERT(sizeof(WDF_DRIVER_CONFIG_V1_0)==sizeof(WDF_DRIVER_CONFIG_V1_1))
static WDF_DEVICE_POWER_STATE PowerGotoDNotZeroNP(__inout FxPkgPnp *This)
MdIrp m_PendingDevicePowerIrp
Definition: fxpkgpnp.hpp:4372
_Must_inspect_result_ _In_ PFLT_CALLBACK_DATA _In_ PFLT_DEFERRED_IO_WORKITEM_ROUTINE WorkerRoutine
Definition: fltkernel.h:1976
LONG NTSTATUS
Definition: precomp.h:26
static FxDevice * GetFxDevice(__in MdDeviceObject DeviceObject)
Definition: fxdeviceum.cpp:60
static const POWER_EVENT_TARGET_STATE m_PowerD0ArmedForWakeOtherStates[]
Definition: fxpkgpnp.hpp:4412
_Must_inspect_result_ NTSTATUS Invoke(__in WDFDEVICE Device, __in WDF_POWER_DEVICE_STATE TargetState)
_In_ ULONG _In_ ULONG State
Definition: potypes.h:516
static const POWER_EVENT_TARGET_STATE m_WakePendingOtherStates[]
Definition: fxpkgpnp.hpp:4418
Definition: fxirp.hpp:28
static WDF_DEVICE_POWER_STATE PowerInitialPowerUpFailedDerefParent(__inout FxPkgPnp *This)
static WDF_DEVICE_POWER_STATE PowerD0DisarmingWakeAtBus(__inout FxPkgPnp *This)
static WDF_DEVICE_POWER_STATE PowerCheckDeviceTypeNP(__inout FxPkgPnp *This)
VOID SetInternalFailure(VOID)
Definition: fxpkgpnp.cpp:4856
KIRQL irql
Definition: wave.h:1
static WDF_DEVICE_POWER_STATE PowerDecideD0State(__inout FxPkgPnp *This)
FxPowerPolicyMachine m_PowerPolicyMachine
Definition: fxpkgpnp.hpp:4153
Definition: dhcpd.h:245
static WDF_DEVICE_POWER_STATE PowerGotoImplicitD3DisarmWakeAtBus(__inout FxPkgPnp *This)
UCHAR m_SystemPowerAction
Definition: fxpkgpnp.hpp:4242
BOOLEAN PowerDmaPowerDown(VOID)
#define VALIDATE_POWER_STATE(_CurrentState, _NewState)
static WDF_DEVICE_POWER_STATE PowerInitialDmaEnableFailed(__inout FxPkgPnp *This)
static WDF_DEVICE_POWER_STATE PowerUpFailedNP(__inout FxPkgPnp *This)
#define InsertTailList(ListHead, Entry)
UCHAR IncrementHistoryIndex(VOID)
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
_Must_inspect_result_ NTSTATUS Init(__inout FxPkgPnp *Pnp, __in PFN_PNP_EVENT_WORKER WorkerRoutine, __in PVOID WorkerContext=NULL)
Definition: eventqueue.cpp:370
static WDF_DEVICE_POWER_STATE PowerDxStoppedDisarmWake(__inout FxPkgPnp *This)
static WDF_DEVICE_POWER_STATE PowerUpFailedDerefParentNP(__inout FxPkgPnp *This)
#define TRACINGPNPPOWERSTATES
Definition: dbgtrace.h:69
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
static WDF_DEVICE_POWER_STATE PowerWakePending(__inout FxPkgPnp *This)
VOID PowerSendPowerUpEvents(VOID)
VOID PowerSetDevicePowerState(__in WDF_POWER_DEVICE_STATE State)
static WDF_DEVICE_POWER_STATE PowerWakingConnectInterrupt(__inout FxPkgPnp *This)
PSINGLE_LIST_ENTRY ple
MdIrp m_WaitWakeIrp
Definition: fxpkgpnp.hpp:180
_Must_inspect_result_ NTSTATUS Invoke(__in WDFDEVICE Device, __in WDF_POWER_DEVICE_STATE TargetState)
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:683
static MdCancelRoutineType _PowerWaitWakeCancelRoutine
Definition: fxpkgpnp.hpp:2736
VOID UnlockFromEnum(__in PFX_DRIVER_GLOBALS FxDriverGlobals)
_Must_inspect_result_ BOOLEAN PowerDmaPowerUp(VOID)
UCHAR KIRQL
Definition: env_spec_w32.h:591
static WDF_DEVICE_POWER_STATE PowerD0StartingConnectInterrupt(__inout FxPkgPnp *This)
VOID PowerProcessEventInner(__inout FxPostProcessInfo *Info)
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
BOOLEAN IsFull(VOID)
__inline WDF_DEVICE_POWER_STATE GetDevicePowerState()
Definition: fxdevice.hpp:1157
VOID StartTimer(__in ULONG State)
Definition: fxwatchdog.hpp:38
BOOLEAN PowerMakeWakeRequestNonCancelable(__in NTSTATUS Status)
FxEnumerationInfo * m_EnumInfo
Definition: fxpkgpnp.hpp:4215
static WDF_DEVICE_POWER_STATE PowerDxStoppedDecideDxState(__inout FxPkgPnp *This)
VOID IncrementHead(VOID)
FxWaitLockTransactionedList m_ChildListList
Definition: fxpkgpnp.hpp:485
static WDF_DEVICE_POWER_STATE PowerInitialConnectInterruptFailed(__inout FxPkgPnp *This)
_Must_inspect_result_ _In_ WDFDEVICE _In_ NTSTATUS WaitWakeStatus
Definition: wdfdevice.h:3942
#define FALSE
Definition: types.h:117
static const POWER_STATE_TABLE m_WdfPowerStates[]
Definition: fxpkgpnp.hpp:4381
_In_ PIRP Irp
Definition: csq.h:116
#define TRACE_LEVEL_VERBOSE
Definition: storswtr.h:30
static WDF_DEVICE_POWER_STATE PowerGotoDNotZero(__inout FxPkgPnp *This)
static WDF_DEVICE_POWER_STATE PowerPowerFailedPowerDown(__inout FxPkgPnp *This)
VOID PowerProcessEvent(__in FxPowerEvent Event, __in BOOLEAN ProcessEventOnDifferentThread=FALSE)
static WDF_DEVICE_POWER_STATE PowerGotoDxIoStoppedArmedForWakeNP(__inout FxPkgPnp *This)
VOID(* PFN_PNP_EVENT_WORKER)(__in FxPkgPnp *PkgPnp, __in FxPostProcessInfo *Info, __in PVOID Context)
VOID CancelTimer(__in ULONG State)
Definition: fxwatchdog.hpp:91
_In_ PVOID _In_ ULONG Event
Definition: iotypes.h:467
#define DO_EVENT_TRAP(x)
Definition: fxpkgpnp.hpp:61
static WDF_DEVICE_POWER_STATE PowerStoppedCompleteDx(__inout FxPkgPnp *This)
static WDF_DEVICE_POWER_STATE PowerD0BusWakeOwner(__inout FxPkgPnp *This)
unsigned char BOOLEAN
static CPPOWER_STATE_TABLE GetPowerTableEntry(__in WDF_DEVICE_POWER_STATE State)
Definition: fxpkgpnp.hpp:2862
#define COVERAGE_TRAP()
Definition: fxmacros.hpp:246
NTSTATUS NotifyResourceObjectsDx(__in ULONG NotifyFlags)
Definition: fxpkgpnp.cpp:6104
static WDF_DEVICE_POWER_STATE PowerGotoDxStoppedDisableInterrupt(__inout FxPkgPnp *This)
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
static WDF_DEVICE_POWER_STATE PowerDxStoppedArmForWake(__inout FxPkgPnp *This)
IWudfIrp * MdIrp
Definition: mxum.h:103
static WDF_DEVICE_POWER_STATE PowerStartSelfManagedIoNP(__inout FxPkgPnp *This)
VOID ProcessPowerEvent(__in FxPowerIdleEvents Event)
WUDF_DRIVER_CANCEL * MdCancelRoutine
Definition: mxum.h:143
static WDF_DEVICE_POWER_STATE PowerDxDisablingWakeAtBus(__inout FxPkgPnp *This)
static WDF_DEVICE_POWER_STATE PowerFinalPowerDownFailed(__inout FxPkgPnp *This)
static WDF_DEVICE_POWER_STATE PowerWakingConnectIn