1 /*++
2 
3 Copyright (c) Microsoft. All rights reserved.
4 
5 Module Name:
6 
7     PowerPolicyStateMachine.cpp
8 
9 Abstract:
10 
11     This module implements the Power Policy state machine for the driver
12     framework.  This code was split out from FxPkgPnp.cpp.
13 
14 Author:
15 
16 
17 
18 
19 Environment:
20 
21     Both kernel and user mode
22 
23 Revision History:
24 
25 
26 
27 --*/
28 
29 #include "pnppriv.hpp"
30 
31 #if FX_IS_KERNEL_MODE
32 #include <usbdrivr.h>
33 #endif
34 
35 #include "fxusbidleinfo.hpp"
36 
37 extern "C" {
38 #if defined(EVENT_TRACING)
39 #include "PowerPolicyStateMachine.tmh"
40 #endif
41 }
42 
43 //
44 // The Power Policy State Machine
45 //
46 // This state machine responds to the following events:
47 //
48 // PowerUp
49 // PowerDown
50 // PowerPolicyStart
51 // PowerPolicyStop
52 // IRP_MN_SET_POWER -- System State S0
53 // IRP_MN_SET_POWER -- System State Sx
54 // PowerTimeoutExpired
55 // IoPresent
56 // IRP_MN_WAIT_WAKE Complete
57 // IRP_MN_WAIT_WAKE Failed
58 //
59 
60 #if FX_SUPER_DBG
61   #define ASSERT_PWR_POL_STATE(_This, _State) \
62       ASSERT((_This)->m_Device->GetDevicePowerPolicyState() == (_State))
63 #else
64   #define ASSERT_PWR_POL_STATE(_This, _State) (0)
65 #endif
66 
67 #if FX_STATE_MACHINE_VERIFY
68     #define VALIDATE_PWR_POL_STATE(_CurrentState, _NewState)                      \
69         ValidatePwrPolStateEntryFunctionReturnValue((_CurrentState), (_NewState))
70 #else
71     #define VALIDATE_PWR_POL_STATE(_CurrentState, _NewState)   (0)
72 #endif  //FX_STATE_MACHINE_VERIFY
73 
74 // @@SMVERIFY_SPLIT_BEGIN
75 
76 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolObjectCreatedOtherStates[] =
77 {
78     { PwrPolRemove, WdfDevStatePwrPolRemoved DEBUGGED_EVENT },
79     { PwrPolNull, WdfDevStatePwrPolNull },
80 };
81 
82 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolStartingOtherStates[] =
83 {
84     { PwrPolPowerUpFailed, WdfDevStatePwrPolStartingFailed DEBUGGED_EVENT },
85     { PwrPolNull, WdfDevStatePwrPolNull },
86 };
87 
88 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolStartedIdleCapableOtherStates[] =
89 {
90     { PwrPolSx, WdfDevStatePwrPolStartedIdleCapableCancelTimerForSleep DEBUGGED_EVENT },
91     { PwrPolStop, WdfDevStatePwrPolStoppingCancelTimer DEBUGGED_EVENT },
92     { PwrPolSurpriseRemove,WdfDevStatePwrPolStoppingCancelTimer DEBUGGED_EVENT },
93     { PwrPolS0IdlePolicyChanged, WdfDevStatePwrPolStartedCancelTimer DEBUGGED_EVENT },
94     { PwrPolNull, WdfDevStatePwrPolNull },
95 };
96 
97 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolIdleCapableDeviceIdleOtherStates[] =
98 {
99     { PwrPolSx, WdfDevStatePwrPolDeviceIdleSleeping DEBUGGED_EVENT },
100     { PwrPolStop, WdfDevStatePwrPolDeviceIdleStopping DEBUGGED_EVENT },
101     { PwrPolSurpriseRemove,WdfDevStatePwrPolDeviceIdleStopping DEBUGGED_EVENT },
102     { PwrPolS0IdlePolicyChanged, WdfDevStatePwrPolDeviceIdleReturnToActive TRAP_ON_EVENT },
103     { PwrPolIoPresent, WdfDevStatePwrPolDeviceIdleReturnToActive DEBUGGED_EVENT },
104     { PwrPolNull, WdfDevStatePwrPolNull },
105 };
106 
107 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolTimerExpiredNoWakeOtherStates[] =
108 {
109     { PwrPolPowerDown, WdfDevStatePwrPolTimerExpiredNoWakePowerDownNotProcessed TRAP_ON_EVENT },
110     { PwrPolNull, WdfDevStatePwrPolNull },
111 };
112 
113 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolTimerExpiredNoWakeCompletePowerDownOtherStates[] =
114 {
115     { PwrPolPowerDownFailed, WdfDevStatePwrPolDevicePowerRequestFailed DEBUGGED_EVENT },
116     { PwrPolNull, WdfDevStatePwrPolNull },
117 };
118 
119 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolWaitingUnarmedOtherStates[] =
120 {
121     { PwrPolSx, WdfDevStatePwrPolSystemSleepFromDeviceWaitingUnarmed DEBUGGED_EVENT },
122     { PwrPolStop, WdfDevStatePwrPolStoppingResetDevice DEBUGGED_EVENT },
123     { PwrPolSurpriseRemove, WdfDevStatePwrPolStoppingCancelTimer DEBUGGED_EVENT },
124     { PwrPolS0IdlePolicyChanged, WdfDevStatePwrPolS0NoWakePowerUp DEBUGGED_EVENT },
125     { PwrPolDevicePowerRequired, WdfDevStatePwrPolS0NoWakePowerUp DEBUGGED_EVENT },
126     { PwrPolNull, WdfDevStatePwrPolNull },
127 };
128 
129 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolS0NoWakePowerUpOtherStates[] =
130 {
131     { PwrPolPowerUpFailed, WdfDevStatePwrPolDevicePowerRequestFailed DEBUGGED_EVENT },
132     { PwrPolPowerUpNotSeen, WdfDevStatePwrPolDeviceD0PowerRequestFailed TRAP_ON_EVENT },
133     { PwrPolNull, WdfDevStatePwrPolNull },
134 };
135 
136 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolS0NoWakeCompletePowerUpOtherStates[] =
137 {
138     { PwrPolPowerUpFailed, WdfDevStatePwrPolDevicePowerRequestFailed DEBUGGED_EVENT },
139     { PwrPolNull, WdfDevStatePwrPolNull },
140 };
141 
142 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolSystemSleepNeedWakeOtherStates[] =
143 {
144     { PwrPolPowerUpFailed, WdfDevStatePwrPolSystemSleepPowerRequestFailed DEBUGGED_EVENT },
145     { PwrPolPowerUpNotSeen, WdfDevStatePwrPolPowerUpForSystemSleepNotSeen TRAP_ON_EVENT },
146     { PwrPolNull, WdfDevStatePwrPolNull },
147 };
148 
149 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolSystemSleepNeedWakeCompletePowerUpOtherStates[] =
150 {
151     { PwrPolPowerUpFailed, WdfDevStatePwrPolSystemSleepPowerRequestFailed DEBUGGED_EVENT },
152     { PwrPolNull, WdfDevStatePwrPolNull },
153 };
154 
155 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolSystemAsleepWakeArmedOtherStates[] =
156 {
157     { PwrPolWakeSuccess, WdfDevStatePwrPolSystemWakeDeviceWakeTriggered DEBUGGED_EVENT },
158     { PwrPolWakeInterruptFired, WdfDevStatePwrPolSystemWakeDeviceWakeInterruptFired DEBUGGED_EVENT },
159     { PwrPolNull,        WdfDevStatePwrPolNull },
160 };
161 
162 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolSystemAsleepWakeArmedNPOtherStates[] =
163 {
164     { PwrPolWakeSuccess, WdfDevStatePwrPolSystemWakeDeviceWakeTriggeredNP DEBUGGED_EVENT },
165     { PwrPolWakeInterruptFired, WdfDevStatePwrPolSystemWakeDeviceWakeInterruptFiredNP TRAP_ON_EVENT },
166     { PwrPolNull,        WdfDevStatePwrPolNull },
167 };
168 
169 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolSystemWakeDeviceToD0OtherStates[] =
170 {
171     { PwrPolPowerUpFailed, WdfDevStatePwrPolDevicePowerRequestFailed DEBUGGED_EVENT },
172     { PwrPolPowerUpNotSeen, WdfDevStatePwrPolDeviceD0PowerRequestFailed TRAP_ON_EVENT },
173     { PwrPolNull,        WdfDevStatePwrPolNull },
174 };
175 
176 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolSystemWakeDeviceToD0CompletePowerUpOtherStates[] =
177 {
178     { PwrPolPowerUpFailed, WdfDevStatePwrPolDevicePowerRequestFailed DEBUGGED_EVENT },
179     { PwrPolNull, WdfDevStatePwrPolNull },
180 };
181 
182 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolStartedWakeCapableOtherStates[] =
183 {
184     { PwrPolSx, WdfDevStatePwrPolStartedWakeCapableCancelTimerForSleep DEBUGGED_EVENT },
185     { PwrPolStop, WdfDevStatePwrPolStoppingCancelTimer DEBUGGED_EVENT },
186     { PwrPolSurpriseRemove, WdfDevStatePwrPolStoppingCancelTimer DEBUGGED_EVENT },
187     { PwrPolS0IdlePolicyChanged, WdfDevStatePwrPolStartedCancelTimer DEBUGGED_EVENT },
188     { PwrPolNull, WdfDevStatePwrPolNull },
189 };
190 
191 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolWakeCapableDeviceIdleOtherStates[] =
192 {
193     { PwrPolSx, WdfDevStatePwrPolDeviceIdleSleeping DEBUGGED_EVENT },
194     { PwrPolStop, WdfDevStatePwrPolDeviceIdleStopping TRAP_ON_EVENT },
195     { PwrPolSurpriseRemove,WdfDevStatePwrPolDeviceIdleStopping DEBUGGED_EVENT },
196     { PwrPolS0IdlePolicyChanged, WdfDevStatePwrPolDeviceIdleReturnToActive TRAP_ON_EVENT },
197     { PwrPolIoPresent, WdfDevStatePwrPolDeviceIdleReturnToActive DEBUGGED_EVENT },
198     { PwrPolNull, WdfDevStatePwrPolNull },
199 };
200 
201 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolSleepingWakePowerDownOtherStates[] =
202 {
203     { PwrPolPowerDown, WdfDevStatePwrPolSleepingPowerDownNotProcessed TRAP_ON_EVENT },
204     { PwrPolNull, WdfDevStatePwrPolNull },
205 };
206 
207 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolTimerExpiredWakeCapablePowerDownOtherStates[] =
208 {
209     { PwrPolPowerDown, WdfDevStatePwrPolTimerExpiredWakeCapablePowerDownNotProcessed TRAP_ON_EVENT },
210     { PwrPolNull, WdfDevStatePwrPolNull },
211 };
212 
213 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolTimerExpiredWakeCapableSendWakeOtherStates[] =
214 {
215     { PwrPolWakeFailed, WdfDevStatePwrPolTimerExpiredWakeCompletedDisarm DEBUGGED_EVENT },
216     { PwrPolWakeSuccess, WdfDevStatePwrPolTimerExpiredWakeSucceeded DEBUGGED_EVENT },
217     { PwrPolNull, WdfDevStatePwrPolNull },
218 };
219 
220 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolTimerExpiredWakeCapableUsbSSOtherStates[] =
221 {
222     { PwrPolSx, WdfDevStatePwrPolStartedWakeCapableSleepingUsbSS DEBUGGED_EVENT },
223     { PwrPolStop, WdfDevStatePwrPolStoppingCancelUsbSS TRAP_ON_EVENT },
224     { PwrPolSurpriseRemove, WdfDevStatePwrPolStoppingCancelUsbSS DEBUGGED_EVENT },
225     { PwrPolUsbSelectiveSuspendCompleted, WdfDevStatePwrPolWakeCapableUsbSSCompleted DEBUGGED_EVENT },
226     { PwrPolS0IdlePolicyChanged, WdfDevStatePwrPolCancelUsbSS DEBUGGED_EVENT },
227     { PwrPolIoPresent, WdfDevStatePwrPolCancelUsbSS DEBUGGED_EVENT },
228     { PwrPolDevicePowerRequired, WdfDevStatePwrPolCancelUsbSS DEBUGGED_EVENT },
229     { PwrPolNull, WdfDevStatePwrPolNull },
230 };
231 
232 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolWaitingArmedOtherStates[] =
233 {
234     { PwrPolSx, WdfDevStatePwrPolCancelingUsbSSForSystemSleep DEBUGGED_EVENT },
235     { PwrPolWakeSuccess, WdfDevStatePwrPolWaitingArmedWakeSucceededCancelUsbSS DEBUGGED_EVENT },
236     { PwrPolWakeFailed, WdfDevStatePwrPolWaitingArmedWakeFailedCancelUsbSS DEBUGGED_EVENT },
237     { PwrPolStop, WdfDevStatePwrPolStoppingD0CancelUsbSS DEBUGGED_EVENT },
238     { PwrPolSurpriseRemove, WdfDevStatePwrPolWaitingArmedStoppingCancelUsbSS DEBUGGED_EVENT },
239     { PwrPolS0IdlePolicyChanged, WdfDevStatePwrPolWaitingArmedIoPresentCancelUsbSS  DEBUGGED_EVENT },
240     { PwrPolUsbSelectiveSuspendCompleted, WdfDevStatePwrPolIoPresentArmed TRAP_ON_EVENT },
241     { PwrPolDevicePowerRequired, WdfDevStatePwrPolWaitingArmedIoPresentCancelUsbSS DEBUGGED_EVENT },
242     { PwrPolWakeInterruptFired, WdfDevStatePwrPolWaitingArmedWakeInterruptFired DEBUGGED_EVENT },
243     { PwrPolNull, WdfDevStatePwrPolNull },
244 };
245 
246 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolDisarmingWakeForSystemSleepCompletePowerUpOtherStates[] =
247 {
248     { PwrPolPowerUpFailed, WdfDevStatePwrPolPowerUpForSystemSleepFailed DEBUGGED_EVENT },
249     { PwrPolNull, WdfDevStatePwrPolNull },
250 };
251 
252 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolCancelingWakeForSystemSleepWakeCanceledOtherStates[] =
253 {
254     { PwrPolPowerUpFailed, WdfDevStatePwrPolPowerUpForSystemSleepFailed DEBUGGED_EVENT },
255     { PwrPolPowerUpNotSeen, WdfDevStatePwrPolPowerUpForSystemSleepNotSeen TRAP_ON_EVENT },
256     { PwrPolNull, WdfDevStatePwrPolNull },
257 };
258 
259 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolWokeFromS0OtherStates[] =
260 {
261     { PwrPolPowerUpFailed, WdfDevStatePwrPolDevicePowerRequestFailed DEBUGGED_EVENT },
262     { PwrPolPowerUpNotSeen, WdfDevStatePwrPolDeviceD0PowerRequestFailed TRAP_ON_EVENT },
263     { PwrPolNull, WdfDevStatePwrPolNull },
264 };
265 
266 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolStoppingResetDeviceOtherStates[] =
267 {
268     { PwrPolPowerUpFailed, WdfDevStatePwrPolStoppingResetDeviceFailed DEBUGGED_EVENT },
269     { PwrPolPowerUpNotSeen, WdfDevStatePwrPolDeviceD0PowerRequestFailed TRAP_ON_EVENT },
270     { PwrPolNull, WdfDevStatePwrPolNull },
271 };
272 
273 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolStoppingResetDeviceCompletePowerUpOtherStates[] =
274 {
275     { PwrPolPowerUpFailed, WdfDevStatePwrPolStoppingResetDeviceFailed DEBUGGED_EVENT },
276     { PwrPolNull, WdfDevStatePwrPolNull },
277 };
278 
279 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolStoppingD0OtherStates[] =
280 {
281     { PwrPolPowerUpFailed, WdfDevStatePwrPolStoppingD0Failed DEBUGGED_EVENT },
282     { PwrPolPowerUpNotSeen, WdfDevStatePwrPolDeviceD0PowerRequestFailed TRAP_ON_EVENT },
283     { PwrPolNull, WdfDevStatePwrPolNull },
284 };
285 
286 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolStoppingDisarmWakeOtherStates[] =
287 {
288     { PwrPolPowerUpFailed, WdfDevStatePwrPolStoppingD0Failed DEBUGGED_EVENT },
289     { PwrPolNull, WdfDevStatePwrPolNull },
290 };
291 
292 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolStoppingDisarmWakeCancelWakeOtherStates[] =
293 {
294     { PwrPolWakeSuccess,     WdfDevStatePwrPolStoppingDisarmWakeWakeCanceled DEBUGGED_EVENT },
295     { PwrPolNull,            WdfDevStatePwrPolNull },
296 };
297 
298 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolStartedOtherStates[] =
299 {
300     { PwrPolStop, WdfDevStatePwrPolStopping DEBUGGED_EVENT },
301     { PwrPolSurpriseRemove, WdfDevStatePwrPolStopping DEBUGGED_EVENT },
302     { PwrPolS0IdlePolicyChanged, WdfDevStatePwrPolStartingDecideS0Wake DEBUGGED_EVENT },
303     { PwrPolNull, WdfDevStatePwrPolNull },
304 };
305 
306 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolStartedWaitForIdleTimeoutOtherStates[] =
307 {
308     { PwrPolStop, WdfDevStatePwrPolStoppingWaitForIdleTimeout TRAP_ON_EVENT },
309     { PwrPolSurpriseRemove, WdfDevStatePwrPolStoppingWaitForIdleTimeout TRAP_ON_EVENT },
310     { PwrPolNull, WdfDevStatePwrPolNull },
311 };
312 
313 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolIoPresentArmedOtherStates[] =
314 {
315     { PwrPolWakeSuccess, WdfDevStatePwrPolIoPresentArmedWakeCanceled DEBUGGED_EVENT },
316     { PwrPolNull, WdfDevStatePwrPolNull },
317 };
318 
319 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolIoPresentArmedWakeCanceledOtherStates[] =
320 {
321     { PwrPolPowerUpFailed, WdfDevStatePwrPolDevicePowerRequestFailed DEBUGGED_EVENT },
322     { PwrPolPowerUpNotSeen, WdfDevStatePwrPolDeviceD0PowerRequestFailed TRAP_ON_EVENT },
323     { PwrPolNull, WdfDevStatePwrPolNull },
324 };
325 
326 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolS0WakeCompletePowerUpOtherStates[] =
327 {
328     { PwrPolPowerUpFailed, WdfDevStatePwrPolDevicePowerRequestFailed DEBUGGED_EVENT },
329     { PwrPolNull, WdfDevStatePwrPolNull },
330 };
331 
332 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolTimerExpiredWakeCapableWakeSucceededOtherStates[] =
333 {
334     { PwrPolPowerDownFailed, WdfDevStatePwrPolTimerExpiredWakeCapablePowerDownFailedUsbSS DEBUGGED_EVENT },
335     { PwrPolNull, WdfDevStatePwrPolNull },
336 };
337 
338 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolTimerExpiredWakeCapableWakeFailedOtherStates[] =
339 {
340     { PwrPolPowerDownFailed, WdfDevStatePwrPolTimerExpiredWakeCapablePowerDownFailedUsbSS DEBUGGED_EVENT },
341     { PwrPolNull, WdfDevStatePwrPolNull },
342 };
343 
344 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolTimerExpiredWakeCapablePowerDownFailedCancelWakeOtherStates[] =
345 {
346     { PwrPolWakeFailed, WdfDevStatePwrPolTimerExpiredWakeCapablePowerDownFailedWakeCanceled DEBUGGED_EVENT },
347     { PwrPolNull, WdfDevStatePwrPolNull },
348 };
349 
350 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolCancelingWakeForSystemSleepOtherStates[] =
351 {
352     { PwrPolWakeSuccess,     WdfDevStatePwrPolCancelingWakeForSystemSleepWakeCanceled DEBUGGED_EVENT },
353     { PwrPolNull,            WdfDevStatePwrPolNull },
354 };
355 
356 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolTimerExpiredWakeCapableWakeArrivedOtherStates[] =
357 {
358     { PwrPolWakeSuccess,    WdfDevStatePwrPolTimerExpiredWakeCapableWakeSucceeded DEBUGGED_EVENT },
359     { PwrPolWakeFailed,     WdfDevStatePwrPolTimerExpiredWakeCapableWakeFailed DEBUGGED_EVENT },
360     { PwrPolPowerDownFailed, WdfDevStatePwrPolTimerExpiredWakeCapablePowerDownFailedCancelWake DEBUGGED_EVENT },
361     { PwrPolWakeInterruptFired, WdfDevStatePwrPolTimerExpiredWakeCapableWakeInterruptArrived },
362     { PwrPolNull,           WdfDevStatePwrPolNull },
363 };
364 
365 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolTimerExpiredWakeCapableCancelWakeOtherStates[] =
366 {
367     { PwrPolWakeFailed, WdfDevStatePwrPolTimerExpiredWakeCapableWakeCanceled DEBUGGED_EVENT },
368     { PwrPolNull, WdfDevStatePwrPolNull },
369 };
370 
371 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolTimerExpiredWakeCompletedPowerDownOtherStates[] =
372 {
373     { PwrPolPowerDownFailed, WdfDevStatePwrPolDevicePowerRequestFailed DEBUGGED_EVENT },
374     { PwrPolNull,           WdfDevStatePwrPolNull },
375 };
376 
377 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolTimerExpiredWakeCompletedPowerUpOtherStates[] =
378 {
379     { PwrPolPowerUpFailed, WdfDevStatePwrPolDevicePowerRequestFailed DEBUGGED_EVENT },
380     { PwrPolPowerUpNotSeen, WdfDevStatePwrPolDeviceD0PowerRequestFailed TRAP_ON_EVENT },
381     { PwrPolNull, WdfDevStatePwrPolNull },
382 };
383 
384 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolSleepingWakeWakeArrivedOtherStates[] =
385 {
386     { PwrPolPowerDownFailed, WdfDevStatePwrPolSleepingWakePowerDownFailed DEBUGGED_EVENT },
387     { PwrPolNull, WdfDevStatePwrPolNull },
388 };
389 
390 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolSystemWakeDeviceWakeTriggeredS0OtherStates[] =
391 {
392     { PwrPolPowerUpFailed, WdfDevStatePwrPolDevicePowerRequestFailed DEBUGGED_EVENT },
393     { PwrPolPowerUpNotSeen, WdfDevStatePwrPolDeviceD0PowerRequestFailed TRAP_ON_EVENT },
394     { PwrPolNull,           WdfDevStatePwrPolNull },
395 };
396 
397 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolSystemWakeDeviceWakeTriggeredS0NPOtherStates[] =
398 {
399     { PwrPolPowerUpFailed, WdfDevStatePwrPolDevicePowerRequestFailed DEBUGGED_EVENT },
400     { PwrPolPowerUpNotSeen, WdfDevStatePwrPolDeviceD0PowerRequestFailed TRAP_ON_EVENT },
401     { PwrPolNull, WdfDevStatePwrPolNull },
402 };
403 
404 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolSystemWakeDeviceWakeCompletePowerUpOtherStates[] =
405 {
406     { PwrPolPowerUpFailed, WdfDevStatePwrPolDevicePowerRequestFailed DEBUGGED_EVENT },
407     { PwrPolNull, WdfDevStatePwrPolNull },
408 };
409 
410 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolSleepingNoWakePowerDownOtherStates[] =
411 {
412     { PwrPolPowerDown, WdfDevStatePwrPolSleepingPowerDownNotProcessed TRAP_ON_EVENT },
413     { PwrPolNull, WdfDevStatePwrPolNull },
414 };
415 
416 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolSleepingNoWakeCompletePowerDownOtherStates[] =
417 {
418     { PwrPolPowerDownFailed, WdfDevStatePwrPolSystemSleepPowerRequestFailed DEBUGGED_EVENT },
419     { PwrPolNull, WdfDevStatePwrPolNull },
420 };
421 
422 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolSleepingSendWakeOtherStates[] =
423 {
424     { PwrPolWakeSuccess, WdfDevStatePwrPolSleepingNoWakeCompletePowerDown DEBUGGED_EVENT },
425     { PwrPolWakeFailed, WdfDevStatePwrPolSleepingNoWakeCompletePowerDown DEBUGGED_EVENT },
426     { PwrPolNull, WdfDevStatePwrPolNull },
427 };
428 
429 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolSleepingWakeWakeArrivedNPOtherStates[] =
430 {
431     { PwrPolPowerDownFailed, WdfDevStatePwrPolSleepingWakePowerDownFailed DEBUGGED_EVENT },
432     { PwrPolNull, WdfDevStatePwrPolNull },
433 };
434 
435 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolSleepingWakePowerDownFailedOtherStates[] =
436 {
437     { PwrPolWakeFailed, WdfDevStatePwrPolSleepingWakePowerDownFailedWakeCanceled DEBUGGED_EVENT },
438     { PwrPolNull, WdfDevStatePwrPolNull },
439 };
440 
441 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolSystemWakeDeviceWakeEnabledOtherStates[] =
442 {
443     { PwrPolWakeSuccess,    WdfDevStatePwrPolSystemWakeDeviceWakeEnabledWakeCanceled DEBUGGED_EVENT },
444     { PwrPolNull,           WdfDevStatePwrPolNull },
445 };
446 
447 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolSystemWakeDeviceWakeEnabledWakeCanceledOtherStates[] =
448 {
449     { PwrPolPowerUpFailed, WdfDevStatePwrPolDevicePowerRequestFailed DEBUGGED_EVENT },
450     { PwrPolPowerUpNotSeen, WdfDevStatePwrPolDeviceD0PowerRequestFailed TRAP_ON_EVENT },
451     { PwrPolNull,           WdfDevStatePwrPolNull },
452 };
453 
454 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolSystemWakeDeviceWakeEnabledNPOtherStates[] =
455 {
456     { PwrPolWakeSuccess,    WdfDevStatePwrPolSystemWakeDeviceWakeEnabledWakeCanceledNP DEBUGGED_EVENT },
457     { PwrPolNull,           WdfDevStatePwrPolNull },
458 };
459 
460 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolSystemWakeDeviceWakeEnabledWakeCanceledNPOtherStates[] =
461 {
462     { PwrPolPowerUpFailed, WdfDevStatePwrPolDevicePowerRequestFailed DEBUGGED_EVENT },
463     { PwrPolPowerUpNotSeen, WdfDevStatePwrPolDeviceD0PowerRequestFailed TRAP_ON_EVENT },
464     { PwrPolNull,          WdfDevStatePwrPolNull },
465 };
466 
467 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolDevicePowerRequestFailedOtherStates[] =
468 {
469     { PwrPolSurpriseRemove, WdfDevStatePwrPolStopping DEBUGGED_EVENT },
470     { PwrPolNull,           WdfDevStatePwrPolNull },
471 };
472 
473 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolStoppingOtherStates[] =
474 {
475     { PwrPolPowerDownFailed, WdfDevStatePwrPolStoppingFailed DEBUGGED_EVENT },
476     { PwrPolNull,WdfDevStatePwrPolNull },
477 };
478 
479 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolStoppedOtherStates[] =
480 {
481     { PwrPolRemove,         WdfDevStatePwrPolStoppedRemoving DEBUGGED_EVENT },
482     { PwrPolNull,           WdfDevStatePwrPolNull },
483 };
484 
485 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolRestartingOtherStates[] =
486 {
487     { PwrPolPowerUpFailed,  WdfDevStatePwrPolRestartingFailed DEBUGGED_EVENT },
488     { PwrPolNull,           WdfDevStatePwrPolNull },
489 };
490 
491 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolStoppingCancelWakeOtherStates[] =
492 {
493     { PwrPolWakeSuccess, WdfDevStatePwrPolStopping DEBUGGED_EVENT },
494     { PwrPolNull,        WdfDevStatePwrPolNull },
495 };
496 
497 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolCancelUsbSSOtherStates[] =
498 {
499     { PwrPolStop, WdfDevStatePwrPolStoppingWaitForUsbSSCompletion TRAP_ON_EVENT },
500     { PwrPolSurpriseRemove, WdfDevStatePwrPolStoppingWaitForUsbSSCompletion TRAP_ON_EVENT },
501     { PwrPolNull,        WdfDevStatePwrPolNull },
502 };
503 
504 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolSleepingWakeRevertArmWakeOtherStates[] =
505 {
506     { PwrPolWakeSuccess,    WdfDevStatePwrPolSleepingNoWakeCompletePowerDown DEBUGGED_EVENT },
507     { PwrPolNull,           WdfDevStatePwrPolNull },
508 };
509 
510 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolSleepingWakeRevertArmWakeNPOtherStates[] =
511 {
512     { PwrPolWakeSuccess,    WdfDevStatePwrPolSleepingNoWakeCompletePowerDown DEBUGGED_EVENT },
513     { PwrPolNull,           WdfDevStatePwrPolNull },
514 };
515 
516 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolRemovedOtherStates[] =
517 {
518     { PwrPolRemove, WdfDevStatePwrPolRemoved DEBUGGED_EVENT },
519     { PwrPolNull, WdfDevStatePwrPolNull },
520 };
521 
522 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolWaitingArmedWakeInterruptFiredOtherStates[] =
523 {
524     { PwrPolWakeSuccess, WdfDevStatePwrPolWaitingArmedWakeSucceededCancelUsbSS TRAP_ON_EVENT },
525     { PwrPolNull, WdfDevStatePwrPolNull },
526 };
527 
528 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolSystemWakeDeviceWakeInterruptFiredOtherStates[] =
529 {
530     { PwrPolWakeSuccess, WdfDevStatePwrPolSystemWakeDeviceWakeTriggered TRAP_ON_EVENT },
531     { PwrPolNull, WdfDevStatePwrPolNull },
532 };
533 
534 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolSystemWakeDeviceWakeInterruptFiredNPOtherStates[] =
535 {
536     { PwrPolWakeSuccess, WdfDevStatePwrPolSystemWakeDeviceWakeTriggeredNP TRAP_ON_EVENT },
537     { PwrPolNull, WdfDevStatePwrPolNull },
538 };
539 
540 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolTimerExpiredWakeCapableWakeInterruptArrivedOtherStates[] =
541 {
542     { PwrPolWakeSuccess, WdfDevStatePwrPolTimerExpiredWakeCapableWakeSucceeded TRAP_ON_EVENT },
543     { PwrPolPowerDownFailed, WdfDevStatePwrPolTimerExpiredWakeCapablePowerDownFailedWakeInterruptArrived TRAP_ON_EVENT },
544     { PwrPolPowerDown, WdfDevStatePwrPolWaitingArmedWakeInterruptFiredDuringPowerDown },
545     { PwrPolNull, WdfDevStatePwrPolNull },
546 };
547 
548 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolTimerExpiredWakeCapablePowerDownFailedWakeInterruptArrivedOtherStates[] =
549 {
550     { PwrPolWakeSuccess, WdfDevStatePwrPolTimerExpiredWakeCapablePowerDownFailedWakeCanceled TRAP_ON_EVENT },
551     { PwrPolNull, WdfDevStatePwrPolNull },
552 };
553 
554 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_PowerPolWaitingArmedWakeInterruptFiredDuringPowerDownOtherStates[] =
555 {
556     { PwrPolWakeSuccess, WdfDevStatePwrPolWaitingArmedWakeSucceededCancelUsbSS TRAP_ON_EVENT },
557     { PwrPolNull, WdfDevStatePwrPolNull },
558 };
559 
560 const POWER_POLICY_STATE_TABLE FxPkgPnp::m_WdfPowerPolicyStates[] =
561 {
562     // transition function,
563     // { first target state },
564     // other target states
565     // queue open,
566 
567     // WdfDevStatePwrPolObjectCreated
568     { NULL,
569       { PwrPolStart, WdfDevStatePwrPolStarting DEBUGGED_EVENT },
570       FxPkgPnp::m_PowerPolObjectCreatedOtherStates,
571       { TRUE,
572         PwrPolS0 |  // Sx -> S0 transition on a PDO which was enumerated and
573                     // in the disabled state
574 
575         PwrPolSx |  // Sx transition right after enumeration
576         PwrPolS0IdlePolicyChanged },
577     },
578 
579     // WdfDevStatePwrPolStarting
580     { FxPkgPnp::PowerPolStarting,
581       { PwrPolPowerUp, WdfDevStatePwrPolStartingPoweredUp DEBUGGED_EVENT },
582       FxPkgPnp::m_PowerPolStartingOtherStates,
583       { FALSE,
584         PwrPolPowerUpFailed   // If the power state machine fails D0 entry upon
585                               // initial start, we will get this event here.  The
586                               // pnp s.m. will not rely on the pwr pol s.m. to
587                               // power down the stack in this case.
588       },
589     },
590 
591     // WdfDevStatePwrPolStartingSucceeded
592     { FxPkgPnp::PowerPolStartingSucceeded,
593       { PwrPolNull, WdfDevStatePwrPolNull },
594       NULL,
595       { FALSE,
596         0 },
597     },
598 
599     // WdfDevStatePwrPolStartingFailed
600     { FxPkgPnp::PowerPolStartingFailed,
601       { PwrPolRemove, WdfDevStatePwrPolRemoved DEBUGGED_EVENT },
602       NULL,
603       { TRUE,
604         0 },
605     },
606 
607     // WdfDevStatePwrPolStartingDecideS0Wake
608     { FxPkgPnp::PowerPolStartingDecideS0Wake,
609       { PwrPolNull, WdfDevStatePwrPolNull },  // transition out based on wake from S0 enabled
610       NULL,
611       { FALSE,
612         0 },
613     },
614 
615     // WdfDevStatePwrPolStartedIdleCapable
616     { FxPkgPnp::PowerPolStartedIdleCapable,
617       { PwrPolPowerTimeoutExpired, WdfDevStatePwrPolIdleCapableDeviceIdle DEBUGGED_EVENT },
618       FxPkgPnp::m_PowerPolStartedIdleCapableOtherStates,
619       { TRUE,
620         PwrPolS0 | // If the machine send a query Sx and it fails, it will send
621                    // an S0 while in the running state (w/out ever sending a true set Sx irp)
622         PwrPolWakeArrived | // If the wake request is failed by the bus in between WakeArrived
623                             // being posted in TimerExpiredWakeCapapble and being
624                             // processed, this event will show up in this state if the idle
625                             // setting changed at this exact moment as well
626         PwrPolPowerUp |     // posted by power when we are powering up the first time
627         PwrPolIoPresent |   // posted by the idle state machine.  If we return
628                             // to idle this can happen
629         PwrPolDevicePowerNotRequired | // The device-power-not-required event arrived just after an
630                                        // I/O request or or an S0-idle policy change caused us to
631                                        // become active again. The event is ignored in this case.
632         PwrPolDevicePowerRequired // The device-power-required event arrived, but we had already
633                                   // powered-up the device proactively because we detected that
634                                   // power was needed. The event is ignored in this case.
635         },
636     },
637 
638     // WdfDevStatePwrPolTimerExpiredNoWake
639     { FxPkgPnp::PowerPolTimerExpiredNoWake,
640       { PwrPolPowerDownIoStopped, WdfDevStatePwrPolTimerExpiredNoWakeCompletePowerDown DEBUGGED_EVENT },
641       FxPkgPnp::m_PowerPolTimerExpiredNoWakeOtherStates,
642       { FALSE,
643         0 },
644     },
645 
646     // WdfDevStatePwrPolTimerExpiredNoWakeCompletePowerDown
647     { FxPkgPnp::PowerPolTimerExpiredNoWakeCompletePowerDown,
648       // NOTE: see the comments PowerPolWaitingArmedUsbSS() about why we query the
649       // idle state instead of going directly to WdfDevStatePwrPolWaitingUnarmed
650       { PwrPolPowerDown, WdfDevStatePwrPolTimerExpiredNoWakePoweredDownDisableIdleTimer DEBUGGED_EVENT },
651       FxPkgPnp::m_PowerPolTimerExpiredNoWakeCompletePowerDownOtherStates,
652       { FALSE,
653         0 },
654     },
655 
656     // WdfDevStatePwrPolWaitingUnarmed
657     { NULL,
658       { PwrPolIoPresent, WdfDevStatePwrPolWaitingUnarmedQueryIdle DEBUGGED_EVENT },
659       FxPkgPnp::m_PowerPolWaitingUnarmedOtherStates,
660       { TRUE,
661         PwrPolS0 | // If the machine send a query Sx and it fails, it will send
662                    // an S0 while in the running state (w/out ever sending a true set Sx irp)
663         PwrPolDevicePowerNotRequired   // When moving from Sx -> S0, we do not power up the
664                                        // device if:
665                                        // (UsingSystemManagedIdleTimeout == TRUE) and
666                                        // (IdleEnabled == TRUE) and
667                                        // (WakeFromS0Capable == FALSE) and
668                                        // (PowerUpIdleDeviceOnSystemWake == FALSE).
669                                        // In this situation, we declare to the active/idle
670                                        // state machine that we are idle, but ignore the
671                                        // device-power-not-required event, because we are
672                                        // already in Dx.
673       },
674     },
675 
676     // WdfDevStatePwrPolWaitingUnarmedQueryIdle
677     { FxPkgPnp::PowerPolWaitingUnarmedQueryIdle,
678       { PwrPolNull, WdfDevStatePwrPolNull },
679       NULL,
680       { FALSE,
681         0 },
682     },
683 
684     // WdfDevStatePwrPolS0NoWakePowerUp
685     { FxPkgPnp::PowerPolS0NoWakePowerUp,
686       { PwrPolPowerUpHwStarted, WdfDevStatePwrPolS0NoWakeCompletePowerUp DEBUGGED_EVENT },
687       FxPkgPnp::m_PowerPolS0NoWakePowerUpOtherStates,
688       { FALSE,
689         0 },
690     },
691 
692     // WdfDevStatePwrPolS0NoWakeCompletePowerUp
693     { FxPkgPnp::PowerPolS0NoWakeCompletePowerUp,
694       { PwrPolPowerUp, WdfDevStatePwrPolStartingDecideS0Wake DEBUGGED_EVENT },
695       FxPkgPnp::m_PowerPolS0NoWakeCompletePowerUpOtherStates,
696       { FALSE,
697         0 },
698     },
699 
700     // WdfDevStatePwrPolSystemSleepFromDeviceWaitingUnarmed
701     { FxPkgPnp::PowerPolSystemSleepFromDeviceWaitingUnarmed,
702       { PwrPolNull, WdfDevStatePwrPolNull }, // transition out based on wake from Sx enabled
703       NULL,
704       { FALSE,
705         0 },
706     },
707 
708     // WdfDevStatePwrPolSystemSleepNeedWake
709     { FxPkgPnp::PowerPolSystemSleepNeedWake,
710       { PwrPolPowerUpHwStarted, WdfDevStatePwrPolSystemSleepNeedWakeCompletePowerUp DEBUGGED_EVENT },
711       FxPkgPnp::m_PowerPolSystemSleepNeedWakeOtherStates,
712       { FALSE,
713         0 },
714     },
715 
716     // WdfDevStatePwrPolSystemSleepNeedWakeCompletePowerUp
717     { FxPkgPnp::PowerPolSystemSleepNeedWakeCompletePowerUp,
718       { PwrPolPowerUp, WdfDevStatePwrPolSleeping DEBUGGED_EVENT },
719       FxPkgPnp::m_PowerPolSystemSleepNeedWakeCompletePowerUpOtherStates,
720       { FALSE,
721         0 },
722     },
723 
724     // WdfDevStatePwrPolSystemSleepPowerRequestFailed
725     { FxPkgPnp::PowerPolSystemSleepPowerRequestFailed,
726       { PwrPolNull, WdfDevStatePwrPolNull },
727       NULL,
728       { FALSE,
729         0, },
730     },
731 
732     // WdfDevStatePwrPolCheckPowerPageable
733     { FxPkgPnp::PowerPolCheckPowerPageable,
734       { PwrPolNull, WdfDevStatePwrPolNull }, // transition out based on which DO_POWER_Xxx flags set on DO
735       NULL,
736       { FALSE,
737         0 },
738     },
739 
740     // WdfDevStatePwrPolSleepingWakeWakeArrived
741     { FxPkgPnp::PowerPolSleepingWakeWakeArrived,
742       { PwrPolPowerDown, WdfDevStatePwrPolSystemAsleepWakeArmed DEBUGGED_EVENT },
743       FxPkgPnp::m_PowerPolSleepingWakeWakeArrivedOtherStates,
744       { FALSE,
745         PwrPolWakeFailed |  // wake completed before we could cancel
746                             // the request, so the event may end up here
747         PwrPolWakeSuccess|  // -do-
748         PwrPolWakeInterruptFired // Wake interrupt fired when during power
749                                  // down as part of system sleep transition
750 
751       },
752     },
753 
754     // WdfDevStatePwrPolSleepingWakeRevertArmWake
755     { FxPkgPnp::PowerPolSleepingWakeRevertArmWake,
756       { PwrPolWakeFailed, WdfDevStatePwrPolSleepingNoWakeCompletePowerDown DEBUGGED_EVENT },
757       FxPkgPnp::m_PowerPolSleepingWakeRevertArmWakeOtherStates,
758       { FALSE,
759         0 },
760     },
761 
762     // WdfDevStatePwrPolSystemAsleepWakeArmed
763     { FxPkgPnp::PowerPolSystemAsleepWakeArmed,
764       { PwrPolS0, WdfDevStatePwrPolSystemWakeDeviceWakeEnabled DEBUGGED_EVENT },
765       FxPkgPnp::m_PowerPolSystemAsleepWakeArmedOtherStates,
766       { TRUE,
767         PwrPolWakeFailed |        // Wake failed while in Sx
768         PwrPolIoPresent |         // IO arrived when the machine was going to Sx
769         PwrPolPowerTimeoutExpired | // we don't cancel the power timer when we goto
770                                     // sleep from an idleable state
771         PwrPolDevicePowerNotRequired // Upon receiving Sx, we simulated a device-power-
772                                      // not-required, so the device-power-requirement
773                                      // state machine sent us this event in response.
774                                      // We can drop it because we already powered down.
775         },
776     },
777 
778     // WdfDevStatePwrPolSystemWakeDeviceWakeEnabled
779     { FxPkgPnp::PowerPolSystemWakeDeviceWakeEnabled,
780       { PwrPolWakeFailed, WdfDevStatePwrPolSystemWakeDeviceWakeEnabledWakeCanceled DEBUGGED_EVENT },
781       FxPkgPnp::m_PowerPolSystemWakeDeviceWakeEnabledOtherStates,
782       { FALSE,
783         PwrPolWakeInterruptFired // wake interrupt fired as we were waking the
784                                  // device on receiving S0 due to other reasons.
785                                  // This event can fire until the wake interrupt
786                                  // machine is notified of the power up.
787       },
788     },
789 
790     // WdfDevStatePwrPolSystemWakeDeviceWakeEnabledWakeCanceled
791     { FxPkgPnp::PowerPolSystemWakeDeviceWakeEnabledWakeCanceled,
792       { PwrPolPowerUpHwStarted, WdfDevStatePwrPolSystemWakeDeviceWakeDisarm DEBUGGED_EVENT },
793       FxPkgPnp::m_PowerPolSystemWakeDeviceWakeEnabledWakeCanceledOtherStates,
794       { FALSE,
795         PwrPolWakeInterruptFired // wake interrupt fired as we were waking the
796                                  // device on receiving S0 due to other reasons.
797                                  // This event can fire until the wake interrupt
798                                  // machine is notified of the power up.
799       },
800     },
801 
802     // WdfDevStatePwrPolSystemWakeDeviceWakeDisarm
803     { FxPkgPnp::PowerPolSystemWakeDeviceWakeDisarm,
804       { PwrPolNull, WdfDevStatePwrPolNull }, // transition out is hardcoded in func
805       NULL,
806       { FALSE,
807         0 },
808     },
809 
810     // WdfDevStatePwrPolSystemWakeDeviceWakeTriggered
811     { NULL,
812       { PwrPolS0, WdfDevStatePwrPolSystemWakeDeviceWakeTriggeredS0 DEBUGGED_EVENT },
813       NULL,
814       { TRUE,
815         0 },
816     },
817 
818     // WdfDevStatePwrPolSystemWakeDeviceWakeTriggeredS0
819     { FxPkgPnp::PowerPolSystemWakeDeviceWakeTriggeredS0,
820       { PwrPolPowerUpHwStarted, WdfDevStatePwrPolSystemWakeDeviceWokeDisarm DEBUGGED_EVENT },
821       FxPkgPnp::m_PowerPolSystemWakeDeviceWakeTriggeredS0OtherStates,
822       { FALSE,
823         0 },
824     },
825 
826     // WdfDevStatePwrPolSystemWakeDeviceWokeDisarm
827     { FxPkgPnp::PowerPolSystemWakeDeviceWokeDisarm,
828       { PwrPolNull, WdfDevStatePwrPolNull }, // transition out is hardcoded in func
829       NULL,
830       { FALSE,
831         0 },
832     },
833 
834     // WdfDevStatePwrPolSleepingWakeWakeArrivedNP,
835     { FxPkgPnp::PowerPolSleepingWakeWakeArrivedNP,
836       { PwrPolPowerDown, WdfDevStatePwrPolSystemAsleepWakeArmedNP DEBUGGED_EVENT },
837       FxPkgPnp::m_PowerPolSleepingWakeWakeArrivedNPOtherStates,
838       { FALSE,
839         PwrPolWakeFailed |  // wake completed before we could cancel
840                             // the request, so the event may end up here
841         PwrPolWakeSuccess|  // -do-
842         PwrPolWakeInterruptFired // Wake interrupt fired when during power
843                                  // down as part of system sleep transition
844 
845       },
846     },
847 
848     // WdfDevStatePwrPolSleepingWakeRevertArmWakeNP,
849     { FxPkgPnp::PowerPolSleepingWakeRevertArmWakeNP,
850       { PwrPolWakeFailed, WdfDevStatePwrPolSleepingNoWakeCompletePowerDown DEBUGGED_EVENT },
851       FxPkgPnp::m_PowerPolSleepingWakeRevertArmWakeNPOtherStates,
852       { FALSE,
853         0 },
854     },
855 
856     // WdfDevStatePwrPolSleepingWakePowerDownFailed
857     { FxPkgPnp::PowerPolSleepingWakePowerDownFailed,
858       { PwrPolWakeSuccess, WdfDevStatePwrPolSleepingWakePowerDownFailedWakeCanceled TRAP_ON_EVENT },
859       FxPkgPnp::m_PowerPolSleepingWakePowerDownFailedOtherStates,
860       { FALSE,
861         0 },
862     },
863 
864     // WdfDevStatePwrPolSleepingWakePowerDownFailedWakeCanceled
865     { FxPkgPnp::PowerPolSleepingWakePowerDownFailedWakeCanceled,
866       { PwrPolNull, WdfDevStatePwrPolNull },
867       NULL,
868       { FALSE,
869         0 },
870     },
871 
872     // WdfDevStatePwrPolSystemAsleepWakeArmedNP
873     { FxPkgPnp::PowerPolSystemAsleepWakeArmedNP,
874       { PwrPolS0, WdfDevStatePwrPolSystemWakeDeviceWakeEnabledNP DEBUGGED_EVENT },
875       FxPkgPnp::m_PowerPolSystemAsleepWakeArmedNPOtherStates,
876       { TRUE,
877         PwrPolWakeFailed |        // Wake failed while in Sx
878         PwrPolIoPresent |         // IO arrived when the machine was going to Sx
879         PwrPolPowerTimeoutExpired // we don't cancel the power timer when we goto
880                                   // sleep from an idleable state
881         },
882     },
883 
884     // WdfDevStatePwrPolSystemWakeDeviceWakeEnabledNP
885     { FxPkgPnp::PowerPolSystemWakeDeviceWakeEnabledNP,
886       { PwrPolWakeFailed, WdfDevStatePwrPolSystemWakeDeviceWakeEnabledWakeCanceledNP DEBUGGED_EVENT },
887       FxPkgPnp::m_PowerPolSystemWakeDeviceWakeEnabledNPOtherStates,
888       { FALSE,
889         PwrPolWakeInterruptFired // wake interrupt fired as we were waking the
890                                  // device on receiving S0 due to other reasons.
891                                  // This event can fire until the wake interrupt
892                                  // machine is notified of the power up.
893       },
894     },
895 
896     // WdfDevStatePwrPolSystemWakeDeviceWakeEnabledWakeCanceledNP
897     { FxPkgPnp::PowerPolSystemWakeDeviceWakeEnabledWakeCanceledNP,
898       { PwrPolPowerUpHwStarted, WdfDevStatePwrPolSystemWakeDeviceWakeDisarmNP DEBUGGED_EVENT },
899       FxPkgPnp::m_PowerPolSystemWakeDeviceWakeEnabledWakeCanceledNPOtherStates,
900       { FALSE,
901         PwrPolWakeSuccess | // wake succeeded and completed before we could cancel
902                             // the request, so the event ends up here
903 
904         PwrPolWakeInterruptFired // wake interrupt fired as we were waking the
905                                  // device on receiving S0 due to other reasons.
906                                  // This event can fire until the wake interrupt
907                                  // machine is notified of the power up.
908       },
909     },
910 
911     // WdfDevStatePwrPolSystemWakeDeviceWakeDisarmNP
912     { FxPkgPnp::PowerPolSystemWakeDeviceWakeDisarmNP,
913       { PwrPolNull, WdfDevStatePwrPolNull }, // transition out is hardcoded in func
914       NULL,
915       { FALSE,
916         0 },
917     },
918 
919     // WdfDevStatePwrPolSystemWakeDeviceWakeTriggeredNP
920     { NULL,
921       { PwrPolS0, WdfDevStatePwrPolSystemWakeDeviceWakeTriggeredS0NP DEBUGGED_EVENT },
922       NULL,
923       { TRUE,
924         PwrPolIoPresent     // I/O arrived before S0 arrival
925         },
926     },
927 
928     // WdfDevStatePwrPolSystemWakeDeviceWakeTriggeredS0NP
929     { FxPkgPnp::PowerPolSystemWakeDeviceWakeTriggeredS0NP,
930       { PwrPolPowerUpHwStarted, WdfDevStatePwrPolSystemWakeDeviceWokeDisarmNP DEBUGGED_EVENT },
931       FxPkgPnp::m_PowerPolSystemWakeDeviceWakeTriggeredS0NPOtherStates,
932       { FALSE,
933         0 },
934     },
935 
936     // WdfDevStatePwrPolSystemWakeDeviceWokeDisarmNP
937     { FxPkgPnp::PowerPolSystemWakeDeviceWokeDisarmNP,
938       { PwrPolNull, WdfDevStatePwrPolNull }, // transition out is hardcoded in func
939       NULL,
940       { FALSE,
941         0 },
942     },
943 
944     // WdfDevStatePwrPolSystemWakeDeviceWakeCompletePowerUp
945     { FxPkgPnp::PowerPolSystemWakeDeviceWakeCompletePowerUp,
946       { PwrPolPowerUp, WdfDevStatePwrPolStartingDecideS0Wake DEBUGGED_EVENT },
947       FxPkgPnp::m_PowerPolSystemWakeDeviceWakeCompletePowerUpOtherStates,
948       { FALSE,
949         0 },
950     },
951 
952     // WdfDevStatePwrPolSleeping
953     { FxPkgPnp::PowerPolSleeping,
954       { PwrPolNull, WdfDevStatePwrPolNull },
955       NULL,
956       { FALSE,
957         0 },
958     },
959 
960     // WdfDevStatePwrPolSleepingNoWakePowerDown
961     { FxPkgPnp::PowerPolSleepingNoWakePowerDown,
962       { PwrPolPowerDownIoStopped, WdfDevStatePwrPolSleepingNoWakeCompletePowerDown DEBUGGED_EVENT },
963       FxPkgPnp::m_PowerPolSleepingNoWakePowerDownOtherStates,
964       { FALSE,
965         0 },
966     },
967 
968     // WdfDevStatePwrPolSleepingNoWakeCompletePowerDown
969     { FxPkgPnp::PowerPolSleepingNoWakeCompletePowerDown,
970       { PwrPolPowerDown, WdfDevStatePwrPolSystemAsleepNoWake DEBUGGED_EVENT },
971       FxPkgPnp::m_PowerPolSleepingNoWakeCompletePowerDownOtherStates,
972       { FALSE,
973         PwrPolWakeArrived   // wake arrived event posted after the ww irp
974                             // completed from SleepingSendWake state. Ignore this
975                             // event since wake is already trigged.
976       },
977     },
978 
979     // WdfDevStatePwrPolSleepingNoWakeDxRequestFailed
980     { FxPkgPnp::PowerPolSleepingNoWakeDxRequestFailed,
981       { PwrPolNull, WdfDevStatePwrPolNull }, // transition out is hardcoded in func
982       NULL,
983       { FALSE,
984         0 },
985     },
986 
987     // WdfDevStatePwrPolSleepingWakePowerDown
988     { FxPkgPnp::PowerPolSleepingWakePowerDown,
989       { PwrPolPowerDownIoStopped, WdfDevStatePwrPolSleepingSendWake DEBUGGED_EVENT },
990       FxPkgPnp::m_PowerPolSleepingWakePowerDownOtherStates,
991       { FALSE,
992         0 },
993     },
994 
995     // WdfDevStatePwrPolSleepingSendWake
996     { FxPkgPnp::PowerPolSleepingSendWake,
997       { PwrPolWakeArrived, WdfDevStatePwrPolCheckPowerPageable DEBUGGED_EVENT },
998       FxPkgPnp::m_PowerPolSleepingSendWakeOtherStates,
999       { FALSE,
1000         0 },
1001     },
1002 
1003     // WdfDevStatePwrPolSystemAsleepNoWake
1004     { FxPkgPnp::PowerPolSystemAsleepNoWake,
1005       { PwrPolS0, WdfDevStatePwrPolSystemWakeDeviceWakeDisabled DEBUGGED_EVENT },
1006       NULL,
1007       { TRUE,
1008         PwrPolS0IdlePolicyChanged | // Policy changed while the device is in Dx
1009                                     // because of Sx, we will reevaluate the idle
1010                                     // settings when we return to S0 anyways
1011         PwrPolWakeArrived | // If arming for wake from sx failed, the WakeArrived
1012                             // event that was a part of that arming is dequeued here
1013         PwrPolIoPresent   | // I/O showed up when going into Sx
1014         PwrPolPowerTimeoutExpired |
1015         PwrPolDevicePowerNotRequired // Upon receiving Sx, we simulated a device-power-
1016                                      // not-required, so the device-power-requirement
1017                                      // state machine sent us this event in response.
1018                                      // We can drop it because we already powered down.
1019        },
1020     },
1021 
1022     // WdfDevStatePwrPolSystemWakeDeviceWakeDisabled
1023     { FxPkgPnp::PowerPolSystemWakeDeviceWakeDisabled,
1024       { PwrPolNull, WdfDevStatePwrPolNull }, // transition out based on wake from S0 enabled
1025       NULL,
1026       { FALSE,
1027         0 },
1028     },
1029 
1030     // WdfDevStatePwrPolSystemWakeDeviceToD0
1031     { FxPkgPnp::PowerPolSystemWakeDeviceToD0,
1032       { PwrPolPowerUpHwStarted, WdfDevStatePwrPolSystemWakeDeviceToD0CompletePowerUp DEBUGGED_EVENT },
1033       FxPkgPnp::m_PowerPolSystemWakeDeviceToD0OtherStates,
1034       { FALSE,
1035         0 },
1036     },
1037 
1038     // WdfDevStatePwrPolSystemWakeDeviceToD0CompletePowerUp
1039     { FxPkgPnp::PowerPolSystemWakeDeviceToD0CompletePowerUp,
1040       { PwrPolPowerUp, WdfDevStatePwrPolStartingDecideS0Wake DEBUGGED_EVENT },
1041       FxPkgPnp::m_PowerPolSystemWakeDeviceToD0CompletePowerUpOtherStates,
1042       { FALSE,
1043         0 },
1044     },
1045 
1046     // WdfDevStatePwrPolSystemWakeQueryIdle
1047     { FxPkgPnp::PowerPolSystemWakeQueryIdle,
1048       { PwrPolNull, WdfDevStatePwrPolNull}, // transition out based on timer expiration state
1049       NULL,
1050       { FALSE,
1051         0 },
1052     },
1053 
1054     // WdfDevStatePwrPolStartedWakeCapable
1055     { FxPkgPnp::PowerPolStartedWakeCapable,
1056       { PwrPolPowerTimeoutExpired, WdfDevStatePwrPolWakeCapableDeviceIdle DEBUGGED_EVENT },
1057       FxPkgPnp::m_PowerPolStartedWakeCapableOtherStates,
1058       { TRUE,
1059         PwrPolS0 | // If the machine send a query Sx and it fails, it will send
1060                    // an S0 while in the running state (w/out ever sending a true set Sx irp)
1061         PwrPolPowerUp |
1062         PwrPolWakeArrived | // If the wake request is failed by the bus in between WakeArrived
1063                             // being posted in TimerExpiredWakeCapapble and being
1064                             // processed, this event will show up in this state
1065 
1066         PwrPolWakeSuccess | // wake succeeded while we were trying to cancel it
1067                             // while coming out of WaitingArmed b/c of io present
1068 
1069         PwrPolWakeFailed |  // wake request failed while we were trying to cancel it
1070                             // while coming out of WaitingArmed b/c of io present
1071 
1072         PwrPolUsbSelectiveSuspendCallback |
1073         PwrPolUsbSelectiveSuspendCompleted | // When returning from a success resume
1074                                              // from USB SS, the completion of the irp will
1075                                              // occur in the started state
1076 
1077         PwrPolIoPresent |   // posted by the idle state machine.  If we return
1078                             // to idle this can happen
1079         PwrPolDevicePowerNotRequired | // The device-power-not-required event arrived just after an
1080                                        // I/O request or or an S0-idle policy change caused us to
1081                                        // become active again. The event is ignored in this case.
1082         PwrPolDevicePowerRequired // The device-power-required event arrived, but we had already
1083                                   // powered-up the device proactively because we detected that
1084                                   // power was needed. The event is ignored in this case.
1085         },
1086     },
1087 
1088     // WdfDevStatePwrPolTimerExpiredDecideUsbSS
1089     { FxPkgPnp::PowerPolTimerExpiredDecideUsbSS,
1090       { PwrPolNull, WdfDevStatePwrPolNull },
1091       NULL,
1092       { FALSE,
1093         0 },
1094     },
1095 
1096     // WdfDevStatePwrPolTimerExpiredWakeCapablePowerDown
1097     { FxPkgPnp::PowerPolTimerExpiredWakeCapablePowerDown,
1098       { PwrPolPowerDownIoStopped, WdfDevStatePwrPolTimerExpiredWakeCapableSendWake DEBUGGED_EVENT },
1099       FxPkgPnp::m_PowerPolTimerExpiredWakeCapablePowerDownOtherStates,
1100       { FALSE,
1101         0 },
1102     },
1103 
1104     // WdfDevStatePwrPolTimerExpiredWakeCapableSendWake
1105     { FxPkgPnp::PowerPolTimerExpiredWakeCapableSendWake,
1106       { PwrPolWakeArrived, WdfDevStatePwrPolTimerExpiredWakeCapableWakeArrived DEBUGGED_EVENT },
1107       FxPkgPnp::m_PowerPolTimerExpiredWakeCapableSendWakeOtherStates,
1108       { FALSE,
1109         0 },
1110     },
1111 
1112     // WdfDevStatePwrPolTimerExpiredWakeCapableUsbSS
1113     { FxPkgPnp::PowerPolTimerExpiredWakeCapableUsbSS,
1114       { PwrPolUsbSelectiveSuspendCallback, WdfDevStatePwrPolTimerExpiredWakeCapablePowerDown DEBUGGED_EVENT },
1115       FxPkgPnp::m_PowerPolTimerExpiredWakeCapableUsbSSOtherStates,
1116       { TRUE,
1117         0 },
1118     },
1119 
1120     // WdfDevStatePwrPolTimerExpiredWakeCapableWakeArrived
1121     { FxPkgPnp::PowerPolTimerExpiredWakeCapableWakeArrived,
1122       { PwrPolPowerDown, WdfDevStatePwrPolWaitingArmedUsbSS DEBUGGED_EVENT },
1123       FxPkgPnp::m_PowerPolTimerExpiredWakeCapableWakeArrivedOtherStates,
1124       { FALSE,
1125         0 },
1126     },
1127 
1128     // WdfDevStatePwrPolTimerExpiredWakeCapableCancelWake
1129     { FxPkgPnp::PowerPolTimerExpiredWakeCapableCancelWake,
1130       { PwrPolWakeSuccess, WdfDevStatePwrPolTimerExpiredWakeCapableWakeCanceled TRAP_ON_EVENT },
1131       FxPkgPnp::m_PowerPolTimerExpiredWakeCapableCancelWakeOtherStates,
1132       { FALSE,
1133         0 },
1134     },
1135 
1136     // WdfDevStatePwrPolTimerExpiredWakeCapableWakeCanceled
1137     { FxPkgPnp::PowerPolTimerExpiredWakeCapableWakeCanceled,
1138       { PwrPolNull, WdfDevStatePwrPolNull },
1139       NULL,
1140       { FALSE,
1141         0 },
1142     },
1143 
1144     // WdfDevStatePwrPolTimerExpiredWakeCapableCleanup
1145     { FxPkgPnp::PowerPolTimerExpiredWakeCapableCleanup,
1146       { PwrPolUsbSelectiveSuspendCompleted, WdfDevStatePwrPolTimerExpiredWakeCompletedPowerDown TRAP_ON_EVENT },
1147       NULL,
1148       { FALSE,
1149         0 },
1150     },
1151 
1152     // WdfDevStatePwrPolTimerExpiredWakeCapableDxAllocFailed
1153     { FxPkgPnp::PowerPolTimerExpiredWakeCapableDxAllocFailed,
1154       { PwrPolUsbSelectiveSuspendCompleted, WdfDevStatePwrPolTimerExpiredWakeCapableUndoPowerDown TRAP_ON_EVENT },
1155       NULL,
1156       { FALSE,
1157         0 },
1158     },
1159 
1160     // WdfDevStatePwrPolTimerExpiredWakeCompletedPowerDown
1161     { FxPkgPnp::PowerPolTimerExpiredWakeCompletedPowerDown,
1162       { PwrPolPowerDown, WdfDevStatePwrPolTimerExpiredWakeCompletedPowerUp DEBUGGED_EVENT },
1163       FxPkgPnp::m_PowerPolTimerExpiredWakeCompletedPowerDownOtherStates,
1164       { FALSE,
1165         PwrPolWakeSuccess | // arming callback failed while going into Dx armed for wake from S0
1166                             // but bus completed wake request with success
1167 
1168         PwrPolWakeArrived   // if the wake request completes before PwrPolWakeArrived
1169                             // can be processed in the PwrPolTimerExpiredWakeCapableSendWake
1170                             // state, it will show up here
1171       },
1172     },
1173 
1174     // WdfDevStatePwrPolTimerExpiredWakeCompletedPowerUp
1175     { FxPkgPnp::PowerPolTimerExpiredWakeCompletedPowerUp,
1176       { PwrPolPowerUpHwStarted, WdfDevStatePwrPolTimerExpiredWakeCompletedHardwareStarted DEBUGGED_EVENT },
1177       FxPkgPnp::m_PowerPolTimerExpiredWakeCompletedPowerUpOtherStates,
1178       { FALSE,
1179         PwrPolWakeSuccess | // arming callback failed while going into Dx armed for wake from S0
1180                             // but bus completed wake request with success
1181 
1182         PwrPolWakeArrived   // if the wake request completes before PwrPolWakeArrived
1183                             // can be processed in the WdfDevStatePwrPolTimerExpiredWakeCapableSendWake
1184                             // state, it will show up here
1185       },
1186     },
1187 
1188     // WdfDevStatePwrPolWaitingArmedUsbSS
1189     { FxPkgPnp::PowerPolWaitingArmedUsbSS,
1190       { PwrPolNull, WdfDevStatePwrPolNull },
1191       NULL,
1192       { FALSE,
1193         0 },
1194     },
1195 
1196     // WdfDevStatePwrPolWaitingArmed
1197     { NULL,
1198       { PwrPolIoPresent, WdfDevStatePwrPolWaitingArmedQueryIdle DEBUGGED_EVENT },
1199       FxPkgPnp::m_PowerPolWaitingArmedOtherStates,
1200       { TRUE,
1201         PwrPolS0 // If the machine send a query Sx and it fails, it will send
1202                  // an S0 while in the running state (w/out ever sending a true set Sx irp)
1203       },
1204     },
1205 
1206     // WdfDevStatePwrPolWaitingArmedQueryIdle
1207     { FxPkgPnp::PowerPolWaitingArmedQueryIdle,
1208       { PwrPolNull, WdfDevStatePwrPolNull },
1209       NULL,
1210       { FALSE,
1211         0 },
1212     },
1213 
1214     // WdfDevStatePwrPolIoPresentArmed
1215     { FxPkgPnp::PowerPolIoPresentArmed,
1216       { PwrPolWakeFailed, WdfDevStatePwrPolIoPresentArmedWakeCanceled DEBUGGED_EVENT },
1217       FxPkgPnp::m_PowerPolIoPresentArmedOtherStates,
1218       { FALSE,
1219         PwrPolWakeInterruptFired // wake interrupt fired as we were waking the
1220                                  // device on receiving IO.This event can fire
1221                                  // until the wake interrupt machine is notified
1222                                  // of the power up.
1223       },
1224     },
1225 
1226     // WdfDevStatePwrPolIoPresentArmedWakeCanceled
1227     { FxPkgPnp::PowerPolIoPresentArmedWakeCanceled,
1228       { PwrPolPowerUpHwStarted, WdfDevStatePwrPolS0WakeDisarm DEBUGGED_EVENT },
1229       FxPkgPnp::m_PowerPolIoPresentArmedWakeCanceledOtherStates,
1230       { FALSE,
1231         PwrPolWakeSuccess | // The wake status was already processed before entering
1232                             // this state - indicates that the client driver is
1233                             // probably propagating a duplicate wake status using
1234                             // the WdfDeviceIndicateWakeStatus ddi.
1235 
1236         PwrPolWakeFailed  |  // The wake status was already processed before entering
1237                              // this state - indicates that the client driver is
1238                              // probably propagating a duplicate wake status using
1239                              // the WdfDeviceIndicateWakeStatus ddi.
1240 
1241         PwrPolWakeInterruptFired // wake interrupt fired as we were waking the
1242                                  // device on receiving IO.This event can fire
1243                                  // until the wake interrupt machine is notified
1244                                  // of the power up.
1245 
1246       },
1247     },
1248 
1249     // WdfDevStatePwrPolS0WakeDisarm,
1250     { FxPkgPnp::PowerPolS0WakeDisarm,
1251       { PwrPolNull, WdfDevStatePwrPolNull }, // transition out is hardcoded in func
1252       NULL,
1253       { FALSE,
1254         0 },
1255     },
1256 
1257     // WdfDevStatePwrPolS0WakeCompletePowerUp
1258     { FxPkgPnp::PowerPolS0WakeCompletePowerUp,
1259       { PwrPolPowerUp, WdfDevStatePwrPolStartingDecideS0Wake DEBUGGED_EVENT },
1260       FxPkgPnp::m_PowerPolS0WakeCompletePowerUpOtherStates,
1261       { FALSE,
1262         0 },
1263     },
1264 
1265     // WdfDevStatePwrPolTimerExpiredWakeSucceeded
1266     { FxPkgPnp::PowerPolTimerExpiredWakeSucceeded,
1267       { PwrPolNull, WdfDevStatePwrPolNull }, // transition out is hardcoded in func
1268       NULL,
1269       { FALSE,
1270         0 },
1271     },
1272 
1273     // WdfDevStatePwrPolTimerExpiredWakeCompletedDisarm
1274     { FxPkgPnp::PowerPolTimerExpiredWakeCompletedDisarm,
1275       { PwrPolNull, WdfDevStatePwrPolNull },
1276       NULL,
1277       { FALSE,
1278         0 },
1279     },
1280 
1281     // WdfDevStatePwrPolTimerExpiredWakeCapableWakeSucceeded
1282     { NULL,
1283       { PwrPolPowerDown, WdfDevStatePwrPolWokeFromS0UsbSS DEBUGGED_EVENT },
1284       FxPkgPnp::m_PowerPolTimerExpiredWakeCapableWakeSucceededOtherStates,
1285       { FALSE,
1286         0 },
1287     },
1288 
1289     // WdfDevStatePwrPolTimerExpiredWakeCapableWakeFailed
1290     { NULL,
1291       { PwrPolPowerDown, WdfDevStatePwrPolWakeFailedUsbSS DEBUGGED_EVENT },
1292       FxPkgPnp::m_PowerPolTimerExpiredWakeCapableWakeFailedOtherStates,
1293       { FALSE,
1294         0 },
1295     },
1296 
1297     // WdfDevStatePwrPolWakeFailedUsbSS
1298     { FxPkgPnp::PowerPolWakeFailedUsbSS,
1299       { PwrPolUsbSelectiveSuspendCompleted, WdfDevStatePwrPolIoPresentArmedWakeCanceled TRAP_ON_EVENT },
1300       NULL,
1301       { FALSE,
1302         0 },
1303     },
1304 
1305     // WdfDevStatePwrPolTimerExpiredWakeCapablePowerDownFailedCancelWake
1306     { FxPkgPnp::PowerPolTimerExpiredWakeCapablePowerDownFailedCancelWake,
1307       { PwrPolWakeSuccess, WdfDevStatePwrPolTimerExpiredWakeCapablePowerDownFailedWakeCanceled DEBUGGED_EVENT },
1308       FxPkgPnp::m_PowerPolTimerExpiredWakeCapablePowerDownFailedCancelWakeOtherStates,
1309       { FALSE,
1310         0 },
1311     },
1312 
1313     // WdfDevStatePwrPolTimerExpiredWakeCapablePowerDownFailedWakeCanceled
1314     { FxPkgPnp::PowerPolTimerExpiredWakeCapablePowerDownFailedWakeCanceled,
1315       { PwrPolNull, WdfDevStatePwrPolNull },
1316       NULL,
1317       { FALSE,
1318         0 },
1319     },
1320 
1321     // WdfDevStatePwrPolTimerExpiredWakeCapablePowerDownFailedUsbSS
1322     { FxPkgPnp::PowerPolTimerExpiredWakeCapablePowerDownFailedUsbSS,
1323       { PwrPolUsbSelectiveSuspendCompleted, WdfDevStatePwrPolDevicePowerRequestFailed TRAP_ON_EVENT },
1324       NULL,
1325       { FALSE,
1326         0 },
1327     },
1328 
1329     // WdfDevStatePwrPolCancelingWakeForSystemSleep
1330     { FxPkgPnp::PowerPolCancelingWakeForSystemSleep,
1331       { PwrPolWakeFailed, WdfDevStatePwrPolCancelingWakeForSystemSleepWakeCanceled DEBUGGED_EVENT },
1332       FxPkgPnp::m_PowerPolCancelingWakeForSystemSleepOtherStates,
1333       { FALSE,
1334         0 },
1335     },
1336 
1337     // WdfDevStatePwrPolCancelingWakeForSystemSleepWakeCanceled
1338     { FxPkgPnp::PowerPolCancelingWakeForSystemSleepWakeCanceled,
1339       { PwrPolPowerUpHwStarted, WdfDevStatePwrPolDisarmingWakeForSystemSleepCompletePowerUp DEBUGGED_EVENT },
1340       FxPkgPnp::m_PowerPolCancelingWakeForSystemSleepWakeCanceledOtherStates,
1341       { FALSE,
1342         PwrPolWakeSuccess   // Wake completed successfully right as the transition
1343                             // from WaitingArmed to goto Sx occurred
1344       },
1345     },
1346 
1347     // WdfDevStatePwrPolDisarmingWakeForSystemSleepCompletePowerUp
1348     { FxPkgPnp::PowerPolDisarmingWakeForSystemSleepCompletePowerUp,
1349       { PwrPolPowerUp, WdfDevStatePwrPolStartedWakeCapableCancelTimerForSleep DEBUGGED_EVENT },
1350       FxPkgPnp::m_PowerPolDisarmingWakeForSystemSleepCompletePowerUpOtherStates,
1351       { FALSE,
1352         0, },
1353     },
1354 
1355     // WdfDevStatePwrPolPowerUpForSystemSleepFailed
1356     { FxPkgPnp::PowerPolPowerUpForSystemSleepFailed,
1357       { PwrPolNull, WdfDevStatePwrPolNull },
1358       NULL,
1359       { FALSE,
1360         0 },
1361     },
1362 
1363     // WdfDevStatePwrPolWokeFromS0UsbSS
1364     { FxPkgPnp::PowerPolWokeFromS0UsbSS,
1365       { PwrPolUsbSelectiveSuspendCompleted, WdfDevStatePwrPolWokeFromS0 DEBUGGED_EVENT },
1366       NULL,
1367       { FALSE,
1368         0 },
1369     },
1370 
1371     // WdfDevStatePwrPolWokeFromS0
1372     { FxPkgPnp::PowerPolWokeFromS0,
1373       { PwrPolPowerUpHwStarted, WdfDevStatePwrPolWokeFromS0NotifyDriver DEBUGGED_EVENT },
1374       FxPkgPnp::m_PowerPolWokeFromS0OtherStates,
1375       { FALSE,
1376         0 },
1377     },
1378 
1379     // WdfDevStatePwrPolWokeFromS0NotifyDriver
1380     { FxPkgPnp::PowerPolWokeFromS0NotifyDriver,
1381       { PwrPolNull, WdfDevStatePwrPolNull },
1382       NULL,
1383       { FALSE,
1384         0 },
1385     },
1386 
1387     // WdfDevStatePwrPolStoppingResetDevice
1388     { FxPkgPnp::PowerPolStoppingResetDevice,
1389       { PwrPolPowerUpHwStarted, WdfDevStatePwrPolStoppingResetDeviceCompletePowerUp DEBUGGED_EVENT },
1390       FxPkgPnp::m_PowerPolStoppingResetDeviceOtherStates,
1391       { FALSE,
1392         0 },
1393     },
1394 
1395     // WdfDevStatePwrPolStoppingResetDeviceCompletePowerUp
1396     { FxPkgPnp::PowerPolStoppingResetDeviceCompletePowerUp,
1397       { PwrPolPowerUp, WdfDevStatePwrPolStopping DEBUGGED_EVENT },
1398       FxPkgPnp::m_PowerPolStoppingResetDeviceCompletePowerUpOtherStates,
1399       { FALSE,
1400         0 },
1401     },
1402 
1403     // WdfDevStatePwrPolStoppingResetDeviceFailed
1404     { FxPkgPnp::PowerPolStoppingResetDeviceFailed,
1405       { PwrPolNull, WdfDevStatePwrPolNull },
1406       NULL,
1407       { FALSE,
1408         0 },
1409     },
1410 
1411     // WdfDevStatePwrPolStoppingD0
1412     { FxPkgPnp::PowerPolStoppingD0,
1413       { PwrPolPowerUpHwStarted, WdfDevStatePwrPolStoppingDisarmWake DEBUGGED_EVENT },
1414       FxPkgPnp::m_PowerPolStoppingD0OtherStates,
1415       { FALSE,
1416         PwrPolWakeSuccess | // In the waiting armed state, the wake completed
1417                             // right after PwrPolStop arrived
1418         PwrPolWakeFailed    // wake completed before we could cancel
1419                             // the request, so the event may end up here
1420       },
1421     },
1422 
1423     // WdfDevStatePwrPolStoppingD0Failed
1424     { FxPkgPnp::PowerPolStoppingD0Failed,
1425       { PwrPolNull, WdfDevStatePwrPolNull },
1426       NULL,
1427       { FALSE,
1428         0 },
1429     },
1430 
1431     // WdfDevStatePwrPolStoppingDisarmWake
1432     { FxPkgPnp::PowerPolStoppingDisarmWake,
1433       { PwrPolPowerUp, WdfDevStatePwrPolStoppingDisarmWakeCancelWake DEBUGGED_EVENT },
1434       FxPkgPnp::m_PowerPolStoppingDisarmWakeOtherStates,
1435       { FALSE,
1436         PwrPolWakeFailed |  // wake completed before we could cancel
1437                             // the request, so the event may end up here
1438         PwrPolWakeSuccess   // -do-
1439       },
1440     },
1441 
1442     // WdfDevStatePwrPolStoppingDisarmWakeCancelWake
1443     { FxPkgPnp::PowerPolStoppingDisarmWakeCancelWake,
1444       { PwrPolWakeFailed, WdfDevStatePwrPolStoppingDisarmWakeWakeCanceled DEBUGGED_EVENT },
1445       FxPkgPnp::m_PowerPolStoppingDisarmWakeCancelWakeOtherStates,
1446       { FALSE,
1447         PwrPolUsbSelectiveSuspendCompleted // pwr pol stopped from a usb SS device
1448                                            // in Dx and the irp completed when the D0
1449                                            // irp was sent
1450       },
1451     },
1452 
1453     // WdfDevStatePwrPolStoppingDisarmWakeWakeCanceled
1454     { FxPkgPnp::PowerPolStoppingDisarmWakeWakeCanceled,
1455       { PwrPolNull, WdfDevStatePwrPolNull}, // transition to Stopping occurs in function
1456       NULL,
1457       { FALSE,
1458         PwrPolUsbSelectiveSuspendCompleted // pwr pol stopped from a usb SS device
1459                                            // in Dx and the irp completed when the D0
1460                                            // irp was sent
1461       },
1462     },
1463 
1464     // WdfDevStatePwrPolStopping
1465     { FxPkgPnp::PowerPolStopping,
1466       { PwrPolPowerDown, WdfDevStatePwrPolStoppingSendStatus DEBUGGED_EVENT },
1467       FxPkgPnp::m_PowerPolStoppingOtherStates,
1468       { FALSE,
1469         PwrPolUsbSelectiveSuspendCompleted // pwr pol stopped from a usb SS device
1470                                            // in Dx and the irp completed when the D0
1471                                            // irp was sent
1472       },
1473     },
1474 
1475     // WdfDevStatePwrPolStoppingFailed
1476     { FxPkgPnp::PowerPolStoppingFailed,
1477       { PwrPolNull, WdfDevStatePwrPolNull },
1478       NULL,
1479       { FALSE,
1480         0 },
1481     },
1482 
1483     // WdfDevStatePwrPolStoppingSendStatus
1484     { FxPkgPnp::PowerPolStoppingSendStatus,
1485       { PwrPolNull, WdfDevStatePwrPolNull },
1486       NULL,
1487       { FALSE,
1488         0 },
1489     },
1490 
1491     // WdfDevStatePwrPolStoppingCancelTimer
1492     { FxPkgPnp::PowerPolStoppingCancelTimer,
1493       { PwrPolNull, WdfDevStatePwrPolNull },
1494       NULL,
1495       { FALSE,
1496         0 },
1497     },
1498 
1499     // WdfDevStatePwrPolStoppingWaitForIdleTimeout
1500     { NULL,
1501       { PwrPolPowerTimeoutExpired, WdfDevStatePwrPolStopping DEBUGGED_EVENT },
1502       NULL,
1503       { TRUE,
1504         0 },
1505     },
1506 
1507     // WdfDevStatePwrPolStoppingCancelUsbSS
1508     { FxPkgPnp::PowerPolStoppingCancelUsbSS,
1509       { PwrPolNull, WdfDevStatePwrPolNull },
1510       NULL,
1511       { FALSE,
1512         0 },
1513     },
1514 
1515     // WdfDevStatePwrPolStoppingWaitForUsbSSCompletion
1516     { NULL,
1517      { PwrPolUsbSelectiveSuspendCompleted, WdfDevStatePwrPolStoppingCancelTimer DEBUGGED_EVENT },
1518      NULL,
1519      { TRUE,
1520        0 },
1521     },
1522 
1523     // WdfDevStatePwrPolStoppingCancelWake
1524     { FxPkgPnp::PowerPolStoppingCancelWake,
1525       { PwrPolWakeFailed, WdfDevStatePwrPolStopping DEBUGGED_EVENT },
1526       FxPkgPnp::m_PowerPolStoppingCancelWakeOtherStates,
1527       { TRUE,
1528         0 },
1529     },
1530 
1531     // WdfDevStatePwrPolStopped
1532     { NULL,
1533       { PwrPolStart, WdfDevStatePwrPolRestarting DEBUGGED_EVENT },
1534       FxPkgPnp::m_PowerPolStoppedOtherStates,
1535       { TRUE,
1536         PwrPolPowerTimeoutExpired | // idle timer fired right before stopping
1537                                     // pwr policy and before pwr pol could process
1538                                     // the timeout
1539         PwrPolIoPresent |         // I/O arrived while transitioning to the
1540                                   // stopped state
1541         PwrPolDevicePowerRequired // Due to a power-related failure, we declared our device state
1542                                   // as failed and stopped the power policy state machine. But
1543                                   // before stopping the power policy machine, we would have
1544                                   // declared ourselves as powered-on (maybe fake) in order to
1545                                   // move the power framework to a consistent state. Since we've
1546                                   // already declared ourselves as powered-on, we can drop this.
1547       },
1548     },
1549 
1550     // WdfDevStatePwrPolCancelUsbSS
1551     { FxPkgPnp::PowerPolCancelUsbSS,
1552       { PwrPolUsbSelectiveSuspendCompleted, WdfDevStatePwrPolStartedCancelTimer DEBUGGED_EVENT },
1553       FxPkgPnp::m_PowerPolCancelUsbSSOtherStates,
1554       { TRUE,
1555         PwrPolIoPresent // I/O arrived while we were waiting for the USB idle notification IOCTL
1556                         // to be completed after we had canceled it. It is okay to drop this
1557                         // event because we are already in the process to returning to the powered-
1558                         // up state.
1559       },
1560     },
1561 
1562     // WdfDevStatePwrPolStarted
1563     { FxPkgPnp::PowerPolStarted,
1564       { PwrPolSx, WdfDevStatePwrPolSleeping DEBUGGED_EVENT },
1565       FxPkgPnp::m_PowerPolStartedOtherStates,
1566       { TRUE,
1567         PwrPolS0 | // If the machine send a query Sx and it fails, it will send
1568                    // an S0 while in the running state (w/out ever sending a true set Sx irp)
1569         PwrPolWakeArrived | // If the wake request is failed by the bus in between WakeArrived
1570                             // being posted in TimerExpiredWakeCapapble and being
1571                             // processed, this event will show up in this state if the idle
1572                             // setting changed at this exact moment as well
1573         PwrPolWakeSuccess | // returning from Dx armed for wake from Sx, wake
1574                             // is completed w/success after S0 irp arrives
1575         PwrPolPowerUp |
1576         PwrPolUsbSelectiveSuspendCompleted  | // sent when we move out of the armed
1577                                               // & idle enabled state into the
1578                                               // idle disabled state
1579         PwrPolIoPresent  |// This just indicates that I/O arrived, which is fine here
1580         PwrPolPowerTimeoutExpired | // this can happen when idle timer is disabled
1581                                     // due to policy change while powering up.
1582         PwrPolDevicePowerRequired // idle policy changed when device was powered down
1583                                   // due to S0-idle. The policy change caused us to power
1584                                   // up. As part of powering up, the device-power-required
1585                                   // event arrived. Can drop because we already powered-up.
1586       },
1587     },
1588 
1589     // WdfDevStatePwrPolStartedCancelTimer
1590     { FxPkgPnp::PowerPolStartedCancelTimer,
1591       { PwrPolNull, WdfDevStatePwrPolNull },
1592       NULL,
1593       { FALSE,
1594         0 },
1595     },
1596 
1597     // WdfDevStatePwrPolStartedWaitForIdleTimeout
1598     { NULL,
1599       { PwrPolPowerTimeoutExpired, WdfDevStatePwrPolStartingDecideS0Wake TRAP_ON_EVENT },
1600       FxPkgPnp::m_PowerPolStartedWaitForIdleTimeoutOtherStates,
1601       { TRUE,
1602         0 },
1603     },
1604 
1605     // WdfDevStatePwrPolStartedWakeCapableCancelTimerForSleep
1606     { FxPkgPnp::PowerPolStartedWakeCapableCancelTimerForSleep,
1607       { PwrPolNull, WdfDevStatePwrPolNull },
1608       NULL,
1609       { FALSE,
1610         0 },
1611     },
1612 
1613     // WdfDevStatePwrPolStartedWakeCapableWaitForIdleTimeout
1614     { NULL,
1615       { PwrPolPowerTimeoutExpired, WdfDevStatePwrPolSleeping TRAP_ON_EVENT },
1616       NULL,
1617       { TRUE,
1618         0 },
1619     },
1620 
1621     // WdfDevStatePwrPolStartedWakeCapableSleepingUsbSS
1622     { FxPkgPnp::PowerPolStartedWakeCapableSleepingUsbSS,
1623       { PwrPolUsbSelectiveSuspendCompleted, WdfDevStatePwrPolSleeping DEBUGGED_EVENT },
1624       NULL,
1625       { TRUE,
1626         0 },
1627     },
1628 
1629     // WdfDevStatePwrPolStartedIdleCapableCancelTimerForSleep
1630     { FxPkgPnp::PowerPolStartedIdleCapableCancelTimerForSleep,
1631       { PwrPolNull, WdfDevStatePwrPolNull },
1632       NULL,
1633       { FALSE,
1634         0 },
1635     },
1636 
1637     // WdfDevStatePwrPolStartedIdleCapableWaitForIdleTimeout
1638     { NULL,
1639       { PwrPolPowerTimeoutExpired, WdfDevStatePwrPolSleeping TRAP_ON_EVENT },
1640       NULL,
1641       { TRUE,
1642         0 },
1643     },
1644 
1645     // WdfDevStatePwrPolDeviceD0PowerRequestFailed
1646     { FxPkgPnp::PowerPolDeviceD0PowerRequestFailed,
1647       { PwrPolNull, WdfDevStatePwrPolNull},
1648       NULL,
1649       { FALSE,
1650         0 },
1651     },
1652 
1653     // WdfDevStatePwrPolDevicePowerRequestFailed
1654     { FxPkgPnp::PowerPolDevicePowerRequestFailed,
1655       { PwrPolStop, WdfDevStatePwrPolStoppingCancelTimer DEBUGGED_EVENT },
1656       FxPkgPnp::m_PowerPolDevicePowerRequestFailedOtherStates,
1657       { TRUE,
1658         PwrPolUsbSelectiveSuspendCompleted | // Device was suspened and surprise
1659                                              // removed while in Dx
1660         PwrPolS0 | // If the device failed D0Exit while the machine was going into
1661                    // Sx, then we will get this event when the machine comes back up
1662 
1663         PwrPolWakeArrived | // wake was completed before PwrPolWakeArrived was
1664                             // sent.  On immediate power down or up, the power
1665                             // operation failed
1666 
1667         PwrPolWakeFailed | // If the device failed exit d0 after being armed, the
1668                            // this event will be processed in the failed state
1669         PwrPolDevicePowerRequired | // We can drop because we already declared ourselves
1670                                     // as being powered on (fake power-on in order to
1671                                     // move the power framework to consistent state).
1672         PwrPolIoPresent // We're being notified that we need to be powered-on because
1673                         // there is I/O to process, but the device is already in failed
1674                         // state and is about to be removed.
1675       },
1676     },
1677 
1678     // State exists only for the non power policy owner state machine
1679     // WdfDevStatePwrPolGotoDx
1680     { NULL,
1681       { PwrPolNull, WdfDevStatePwrPolNull },
1682       NULL,
1683       { TRUE,
1684         0 },
1685     },
1686 
1687     // WdfDevStatePwrPolGotoDxInDx
1688     { NULL,
1689       { PwrPolNull, WdfDevStatePwrPolNull },
1690       NULL,
1691       { TRUE,
1692         0 },
1693     },
1694 
1695     // State exists only for the non power policy owner state machine
1696     // WdfDevStatePwrPolDx
1697     { NULL,
1698       { PwrPolNull, WdfDevStatePwrPolNull },
1699       NULL,
1700       { TRUE,
1701         0 },
1702     },
1703 
1704     // State exists only for the non power policy owner state machine
1705     // WdfDevStatePwrPolGotoD0
1706     { NULL,
1707       { PwrPolNull, WdfDevStatePwrPolNull },
1708       NULL,
1709       { TRUE,
1710         0 },
1711     },
1712 
1713     // WdfDevStatePwrPolGotoD0InD0
1714     { NULL,
1715       { PwrPolNull, WdfDevStatePwrPolNull },
1716       NULL,
1717       { TRUE,
1718         0 },
1719     },
1720 
1721     // WdfDevStatePwrPolFinal
1722     { NULL,
1723       { PwrPolNull, WdfDevStatePwrPolNull },
1724       NULL,
1725       { TRUE,
1726         0 },
1727     },
1728 
1729     // WdfDevStatePwrPolSleepingPowerDownNotProcessed
1730     { FxPkgPnp::PowerPolSleepingPowerDownNotProcessed,
1731       { PwrPolNull, WdfDevStatePwrPolNull },
1732       NULL,
1733       { FALSE,
1734         0 },
1735     },
1736 
1737     // WdfDevStatePwrPolTimerExpiredWakeCapablePowerDownNotProcessed
1738     { FxPkgPnp::PowerPolTimerExpiredWakeCapablePowerDownNotProcessed,
1739       { PwrPolNull, WdfDevStatePwrPolNull },
1740       NULL,
1741       { FALSE,
1742         0 },
1743     },
1744 
1745     // WdfDevStatePwrPolTimerExpiredNoWakePowerDownNotProcessed
1746     { FxPkgPnp::PowerPolTimerExpiredNoWakePowerDownNotProcessed,
1747       { PwrPolNull, WdfDevStatePwrPolNull },
1748       NULL,
1749       { FALSE,
1750         0 },
1751     },
1752 
1753     // WdfDevStatePwrPolTimerExpiredNoWakePoweredDownDisableIdleTimer
1754     { FxPkgPnp::PowerPolTimerExpiredNoWakePoweredDownDisableIdleTimer,
1755       { PwrPolNull, WdfDevStatePwrPolNull },
1756       NULL,
1757       { FALSE,
1758         0 },
1759     },
1760 
1761     // WdfDevStatePwrPolStoppingWaitingForImplicitPowerDown
1762     { NULL,
1763       { PwrPolNull, WdfDevStatePwrPolNull },
1764       NULL,
1765       { FALSE,
1766         0 },
1767     },
1768 
1769     // WdfDevStatePwrPolStoppingPoweringUp
1770     { NULL,
1771       { PwrPolNull, WdfDevStatePwrPolNull },
1772       NULL,
1773       { FALSE,
1774         0 },
1775     },
1776 
1777     // WdfDevStatePwrPolStoppingPoweringDown
1778     { NULL,
1779       { PwrPolNull, WdfDevStatePwrPolNull },
1780       NULL,
1781       { FALSE,
1782         0 },
1783     },
1784 
1785     // WdfDevStatePwrPolPowerUpForSystemSleepNotSeen
1786     { FxPkgPnp::PowerPolPowerUpForSystemSleepNotSeen,
1787       { PwrPolNull, WdfDevStatePwrPolNull },
1788       NULL,
1789       { FALSE,
1790         0 },
1791     },
1792 
1793     // WdfDevStatePwrPolWaitingArmedStoppingCancelUsbSS
1794     { FxPkgPnp::PowerPolWaitingArmedStoppingCancelUsbSS,
1795       { PwrPolUsbSelectiveSuspendCompleted, WdfDevStatePwrPolStoppingCancelWake DEBUGGED_EVENT },
1796       NULL,
1797       { FALSE,
1798         PwrPolWakeFailed |  // wake completed before we could cancel
1799                             // the request, so the event may end up here
1800         PwrPolWakeSuccess   // -do-
1801       },
1802     },
1803 
1804     // WdfDevStatePwrPolWaitingArmedWakeFailedCancelUsbSS
1805     { FxPkgPnp::PowerPolWaitingArmedWakeFailedCancelUsbSS,
1806       { PwrPolUsbSelectiveSuspendCompleted, WdfDevStatePwrPolIoPresentArmedWakeCanceled TRAP_ON_EVENT },
1807       NULL,
1808       { FALSE,
1809           0 },
1810     },
1811 
1812     // WdfDevStatePwrPolWaitingArmedIoPresentCancelUsbSS
1813     { FxPkgPnp::PowerPolWaitingArmedIoPresentCancelUsbSS,
1814       { PwrPolUsbSelectiveSuspendCompleted, WdfDevStatePwrPolIoPresentArmed DEBUGGED_EVENT },
1815       NULL,
1816       { FALSE,
1817         PwrPolWakeFailed  |  // wake completed before we could cancel
1818                              // the request, so the event may end up here
1819         PwrPolWakeSuccess |  // -do-
1820         PwrPolWakeInterruptFired // wake interrupt fired as we were waking the
1821                                  // device on receiving IO.This event can fire
1822                                  // until the wake interrupt machine is notified
1823                                  // of the power up.
1824       },
1825     },
1826 
1827     // WdfDevStatePwrPolWaitingArmedWakeSucceededCancelUsbSS
1828     { FxPkgPnp::PowerPolWaitingArmedWakeSucceededCancelUsbSS,
1829       { PwrPolUsbSelectiveSuspendCompleted, WdfDevStatePwrPolWokeFromS0 DEBUGGED_EVENT },
1830       NULL,
1831       { FALSE,
1832         0 },
1833     },
1834 
1835     // WdfDevStatePwrPolCancelingUsbSSForSystemSleep
1836     { FxPkgPnp::PowerPolCancelingUsbSSForSystemSleep,
1837       { PwrPolUsbSelectiveSuspendCompleted, WdfDevStatePwrPolCancelingWakeForSystemSleep DEBUGGED_EVENT },
1838       NULL,
1839       { FALSE,
1840         PwrPolWakeFailed |  // wake completed before we could cancel
1841                             // the request, so the event may end up here
1842         PwrPolWakeSuccess   // -do-
1843       },
1844     },
1845 
1846     // WdfDevStatePwrPolStoppingD0CancelUsbSS
1847     { FxPkgPnp::PowerPolStoppingD0CancelUsbSS,
1848       { PwrPolUsbSelectiveSuspendCompleted, WdfDevStatePwrPolStoppingD0 TRAP_ON_EVENT },
1849       NULL,
1850       { FALSE,
1851         PwrPolWakeFailed |  // wake completed before we could cancel
1852                             // the request, so the event may end up here
1853         PwrPolWakeSuccess   // -do-
1854       },
1855     },
1856 
1857     // WdfDevStatePwrPolStartingPoweredUp
1858     { FxPkgPnp::PowerPolStartingPoweredUp,
1859       { PwrPolNull, WdfDevStatePwrPolNull },
1860       NULL,
1861       { FALSE,
1862         0 },
1863     },
1864 
1865     // WdfDevStatePwrPolIdleCapableDeviceIdle
1866     { FxPkgPnp::PowerPolIdleCapableDeviceIdle,
1867       { PwrPolDevicePowerNotRequired, WdfDevStatePwrPolTimerExpiredNoWake DEBUGGED_EVENT },
1868       FxPkgPnp::m_PowerPolIdleCapableDeviceIdleOtherStates,
1869       { TRUE,
1870         0 },
1871     },
1872 
1873     // WdfDevStatePwrPolDeviceIdleReturnToActive
1874     { FxPkgPnp::PowerPolDeviceIdleReturnToActive,
1875       { PwrPolNull, WdfDevStatePwrPolNull },
1876       NULL,
1877       { FALSE,
1878         0 },
1879     },
1880 
1881     // WdfDevStatePwrPolDeviceIdleSleeping
1882     { FxPkgPnp::PowerPolDeviceIdleSleeping,
1883       { PwrPolNull, WdfDevStatePwrPolNull },
1884       NULL,
1885       { FALSE,
1886         0 },
1887     },
1888 
1889     // WdfDevStatePwrPolDeviceIdleStopping
1890     { FxPkgPnp::PowerPolDeviceIdleStopping,
1891       { PwrPolNull, WdfDevStatePwrPolNull },
1892       NULL,
1893       { FALSE,
1894         0 },
1895     },
1896 
1897     // WdfDevStatePwrPolTimerExpiredNoWakeUndoPowerDown
1898     { FxPkgPnp::PowerPolTimerExpiredNoWakeUndoPowerDown,
1899       { PwrPolNull, WdfDevStatePwrPolNull },
1900       NULL,
1901       { FALSE,
1902         0 },
1903     },
1904 
1905     // WdfDevStatePwrPolWakeCapableDeviceIdle
1906     { FxPkgPnp::PowerPolWakeCapableDeviceIdle,
1907       { PwrPolDevicePowerNotRequired, WdfDevStatePwrPolTimerExpiredDecideUsbSS DEBUGGED_EVENT },
1908       FxPkgPnp::m_PowerPolWakeCapableDeviceIdleOtherStates,
1909       { TRUE,
1910         PwrPolDevicePowerRequired // The device-power-required event arrived, but we had already
1911                                   // powered-up the device proactively because we detected that
1912                                   // power was needed. And after we powered up, we become idle
1913                                   // again and arrived in our current state before the device-
1914                                   // power-required event was received. The event is ignored in
1915                                   // this case.
1916       },
1917     },
1918 
1919     // WdfDevStatePwrPolWakeCapableUsbSSCompleted
1920     { FxPkgPnp::PowerPolWakeCapableUsbSSCompleted,
1921       { PwrPolNull, WdfDevStatePwrPolNull },
1922       NULL,
1923       { FALSE,
1924         0 },
1925     },
1926 
1927     // WdfDevStatePwrPolTimerExpiredWakeCapableUndoPowerDown
1928     { FxPkgPnp::PowerPolTimerExpiredWakeCapableUndoPowerDown,
1929       { PwrPolNull, WdfDevStatePwrPolNull },
1930       NULL,
1931       { FALSE,
1932         0 },
1933     },
1934 
1935     // WdfDevStatePwrPolTimerExpiredWakeCompletedHardwareStarted
1936     { FxPkgPnp::PowerPolTimerExpiredWakeCompletedHardwareStarted,
1937       { PwrPolNull, WdfDevStatePwrPolNull },
1938       NULL,
1939       { FALSE,
1940         0 },
1941     },
1942 
1943     // WdfDevStatePwrPolStoppedRemoving
1944     { FxPkgPnp::PowerPolStoppedRemoving,
1945       { PwrPolNull, WdfDevStatePwrPolNull },
1946       NULL,
1947       { FALSE,
1948         0 },
1949     },
1950 
1951     // WdfDevStatePwrPolRemoved
1952     { FxPkgPnp::PowerPolRemoved,
1953       { PwrPolStart, WdfDevStatePwrPolStarting DEBUGGED_EVENT },
1954       FxPkgPnp::m_PowerPolRemovedOtherStates,
1955       { TRUE,
1956         PwrPolSx | // device is disabled (must be a PDO) and then the machine
1957                    // moves into an Sx state
1958         PwrPolS0 |  // driver failed power up when moving out of S0 Dx idle
1959                     // state and system resumed after failure
1960         PwrPolS0IdlePolicyChanged // driver changes S0 idle settings while being
1961                                   // removed
1962       },
1963     },
1964 
1965     // WdfDevStatePwrPolRestarting
1966     { FxPkgPnp::PowerPolRestarting,
1967       { PwrPolPowerUp, WdfDevStatePwrPolStartingSucceeded DEBUGGED_EVENT },
1968       FxPkgPnp::m_PowerPolRestartingOtherStates,
1969       { FALSE,
1970         0 },
1971     },
1972 
1973     // WdfDevStatePwrPolRestartingFailed
1974     { FxPkgPnp::PowerPolRestartingFailed,
1975       { PwrPolNull, WdfDevStatePwrPolNull },
1976       NULL,
1977       { FALSE,
1978         0 },
1979     },
1980 
1981     // WdfDevStatePwrPolStartingPoweredUpFailed
1982     { FxPkgPnp::PowerPolStartingPoweredUpFailed,
1983       { PwrPolPowerDown, WdfDevStatePwrPolStartingFailed DEBUGGED_EVENT },
1984       NULL,
1985       { FALSE,
1986         0 },
1987     },
1988 
1989     // WdfDevStatePwrPolTimerExpiredNoWakeReturnToActive
1990     { FxPkgPnp::PowerPolTimerExpiredNoWakeReturnToActive,
1991       { PwrPolNull, WdfDevStatePwrPolNull },
1992       NULL,
1993       { FALSE,
1994         0 },
1995     },
1996 
1997     // WdfDevStatePwrPolWaitingArmedWakeInterruptFired
1998     { FxPkgPnp::PowerPolWaitingArmedWakeInterruptFired,
1999       { PwrPolWakeFailed, WdfDevStatePwrPolWaitingArmedWakeSucceededCancelUsbSS DEBUGGED_EVENT },
2000       FxPkgPnp::m_PowerPolWaitingArmedWakeInterruptFiredOtherStates,
2001       { FALSE,
2002         0 },
2003     },
2004 
2005     // WdfDevStatePwrPolSystemWakeDeviceWakeInterruptFired
2006     { FxPkgPnp::PowerPolSystemWakeDeviceWakeInterruptFired,
2007       { PwrPolWakeFailed, WdfDevStatePwrPolSystemWakeDeviceWakeTriggered TRAP_ON_EVENT },
2008       FxPkgPnp::m_PowerPolSystemWakeDeviceWakeInterruptFiredOtherStates,
2009       { FALSE,
2010         0 },
2011     },
2012 
2013     // WdfDevStatePwrPolSystemWakeDeviceWakeInterruptFiredNP
2014     { FxPkgPnp::PowerPolSystemWakeDeviceWakeInterruptFiredNP,
2015       { PwrPolWakeFailed, WdfDevStatePwrPolSystemWakeDeviceWakeTriggeredNP TRAP_ON_EVENT },
2016       FxPkgPnp::m_PowerPolSystemWakeDeviceWakeInterruptFiredNPOtherStates,
2017       { FALSE,
2018         0 },
2019     },
2020 
2021     // WdfDevStatePwrPolTimerExpiredWakeCapableWakeInterruptArrived
2022     { FxPkgPnp::PowerPolTimerExpiredWakeCapableWakeInterruptArrived,
2023       { PwrPolWakeFailed, WdfDevStatePwrPolTimerExpiredWakeCapableWakeSucceeded DEBUGGED_EVENT },
2024       FxPkgPnp::m_PowerPolTimerExpiredWakeCapableWakeInterruptArrivedOtherStates,
2025       { FALSE,
2026         0 },
2027     },
2028 
2029     // WdfDevStatePwrPolTimerExpiredWakeCapablePowerDownFailedWakeInterruptArrived
2030     { NULL,
2031       { PwrPolWakeFailed, WdfDevStatePwrPolTimerExpiredWakeCapablePowerDownFailedWakeCanceled DEBUGGED_EVENT },
2032       FxPkgPnp::m_PowerPolTimerExpiredWakeCapablePowerDownFailedWakeInterruptArrivedOtherStates,
2033       { FALSE,
2034         0 },
2035     },
2036 
2037     // WdfDevStatePwrPolWaitingArmedWakeInterruptFiredDuringPowerDown
2038     { NULL,
2039       { PwrPolWakeFailed, WdfDevStatePwrPolWaitingArmedWakeSucceededCancelUsbSS DEBUGGED_EVENT },
2040       FxPkgPnp::m_PowerPolWaitingArmedWakeInterruptFiredDuringPowerDownOtherStates,
2041       { FALSE,
2042         0 },
2043     },
2044 
2045     // WdfDevStatePwrPolNull
2046     // *** no entry for this state ***
2047 };
2048 
2049 // @@SMVERIFY_SPLIT_END
2050 
2051 VOID
PowerPolicyCheckAssumptions(VOID)2052 FxPkgPnp::PowerPolicyCheckAssumptions(
2053     VOID
2054     )
2055 /*++
2056 
2057 Routine Description:
2058     This routine is never actually called by running code, it just has
2059     WDFCASSERTs who upon failure, would not allow this file to be compiled.
2060 
2061     DO NOT REMOVE THIS FUNCTION just because it is not callec by any running
2062     code.
2063 
2064 Arguments:
2065     None
2066 
2067 Return Value:
2068     None
2069 
2070   --*/
2071 {
2072     WDFCASSERT(sizeof(FxPwrPolStateInfo) == sizeof(ULONG));
2073 
2074     WDFCASSERT((sizeof(m_WdfPowerPolicyStates)/sizeof(m_WdfPowerPolicyStates[0]))
2075                  ==
2076                (WdfDevStatePwrPolNull - WdfDevStatePwrPolObjectCreated));
2077 
2078     // we assume these are the same length when we update the history index
2079     WDFCASSERT((sizeof(m_PowerPolicyMachine.m_Queue)/
2080                 sizeof(m_PowerPolicyMachine.m_Queue[0]))
2081                ==
2082                (sizeof(m_PowerPolicyMachine.m_States.History)/
2083                 sizeof(m_PowerPolicyMachine.m_States.History[0])));
2084 }
2085 
2086 CfxDevice *
GetDevice(VOID)2087 IdleTimeoutManagement::GetDevice(
2088     VOID
2089     )
2090 {
2091     IdlePolicySettings * idlePolicySettings = NULL;
2092     FxPowerPolicyOwnerSettings * ppoSettings = NULL;
2093     FxPkgPnp * pPkgPnp = NULL;
2094 
2095     idlePolicySettings = (IdlePolicySettings *) CONTAINING_RECORD(
2096                                                             this,
2097                                                             IdlePolicySettings,
2098                                                             m_TimeoutMgmt
2099                                                             );
2100     ppoSettings = (FxPowerPolicyOwnerSettings *) CONTAINING_RECORD(
2101                                                     idlePolicySettings,
2102                                                     FxPowerPolicyOwnerSettings,
2103                                                     m_IdleSettings
2104                                                     );
2105     pPkgPnp = ppoSettings->m_PkgPnp;
2106 
2107     return pPkgPnp->GetDevice();
2108 }
2109 
2110 IdleTimeoutManagement::IdleTimeoutStatusUpdateResult
UpdateIdleTimeoutStatus(__in IdleTimeoutManagement::IdleTimeoutStatusFlag Flag)2111 IdleTimeoutManagement::UpdateIdleTimeoutStatus(
2112     __in IdleTimeoutManagement::IdleTimeoutStatusFlag Flag
2113     )
2114 {
2115     LONG idleTimeoutStatusSnapshot;
2116     LONG updatedIdleTimeoutStatus;
2117     LONG preInterlockedIdleTimeoutStatus;
2118 
2119     //
2120     // Take a snapshot of the idle timeout management status
2121     //
2122     idleTimeoutStatusSnapshot = m_IdleTimeoutStatus;
2123 
2124     //
2125     // Verify that the flag we're trying to set is not already set
2126     //
2127     if (0 != (idleTimeoutStatusSnapshot & Flag)) {
2128         return IdleTimeoutStatusFlagAlreadySet;
2129     }
2130 
2131     //
2132     // Verify that the idle timeout management status is not already
2133     // "frozen"
2134     //
2135     if (0 != (idleTimeoutStatusSnapshot & IdleTimeoutStatusFrozen)) {
2136         //
2137         // It was too late to set the flag. The flag value was already
2138         // "frozen".
2139         //
2140         return IdleTimeoutStatusFlagsAlreadyFrozen;
2141     }
2142 
2143     //
2144     // Try to set the flag
2145     //
2146     updatedIdleTimeoutStatus = idleTimeoutStatusSnapshot | Flag;
2147 
2148     preInterlockedIdleTimeoutStatus = InterlockedCompareExchange(
2149                                                 &m_IdleTimeoutStatus,
2150                                                 updatedIdleTimeoutStatus,
2151                                                 idleTimeoutStatusSnapshot
2152                                                 );
2153     if (preInterlockedIdleTimeoutStatus != idleTimeoutStatusSnapshot) {
2154 
2155         if (0 != (preInterlockedIdleTimeoutStatus &
2156                                 IdleTimeoutStatusFrozen)) {
2157             //
2158             // It was too late to set the flag. The flag value was already
2159             // "frozen".
2160             //
2161             return IdleTimeoutStatusFlagsAlreadyFrozen;
2162         }
2163         else {
2164             //
2165             // Idle timeout management status is being changed by multiple
2166             // threads in parallel. This is not supported.
2167             //
2168             return IdleTimeoutStatusFlagsUnexpected;
2169         }
2170     }
2171 
2172     //
2173     // We have successfully set the flag
2174     //
2175     return IdleTimeoutStatusFlagsUpdated;
2176 }
2177 
2178 NTSTATUS
UseSystemManagedIdleTimeout(__in PFX_DRIVER_GLOBALS DriverGlobals)2179 IdleTimeoutManagement::UseSystemManagedIdleTimeout(
2180     __in PFX_DRIVER_GLOBALS DriverGlobals
2181     )
2182 {
2183     NTSTATUS status;
2184     IdleTimeoutStatusUpdateResult statusUpdateResult;
2185     CfxDevice * device;
2186 
2187     //
2188     // First check if we are running on Windows 8 or above
2189     //
2190     if (_SystemManagedIdleTimeoutAvailable()) {
2191 
2192         //
2193         // Get the device object so we can use it for logging
2194         //
2195         device = GetDevice();
2196 
2197         //
2198         // Try to update the flag that specifies that the power framework should
2199         // determine the idle timeout.
2200         //
2201         statusUpdateResult = UpdateIdleTimeoutStatus(IdleTimeoutSystemManaged);
2202 
2203         switch (statusUpdateResult) {
2204             case IdleTimeoutStatusFlagsAlreadyFrozen:
2205             {
2206                 //
2207                 // Status is already frozen. Too late to update it.
2208                 //
2209                 status = STATUS_INVALID_DEVICE_REQUEST;
2210                 DoTraceLevelMessage(
2211                     DriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
2212                     "WDFDEVICE %p !devobj %p If the power framework is made "
2213                     "responsible for determining the idle timeout, then the "
2214                     "first call to assign S0-idle policy must occur before the "
2215                     "first start IRP is completed. However, in this case, it "
2216                     "occurred after the first start IRP was completed. "
2217                     "%!STATUS!.",
2218                     device->GetHandle(),
2219                     device->GetDeviceObject(),
2220                     status
2221                     );
2222                 FxVerifierDbgBreakPoint(DriverGlobals);
2223             }
2224             break;
2225 
2226             case IdleTimeoutStatusFlagsUnexpected:
2227             {
2228                 //
2229                 // Status being updated from multiple threads in parallel. Not
2230                 // supported.
2231                 //
2232                 status = STATUS_INVALID_DEVICE_REQUEST;
2233                 DoTraceLevelMessage(
2234                     DriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
2235                     "WDFDEVICE %p !devobj %p Calls to assign S0-idle settings "
2236                     "and to specify power framework settings are happening in "
2237                     "parallel. The driver needs to serialize these calls with "
2238                     "respect to each other. %!STATUS!.",
2239                     device->GetHandle(),
2240                     device->GetDeviceObject(),
2241                     status
2242                     );
2243                 FxVerifierDbgBreakPoint(DriverGlobals);
2244             }
2245             break;
2246 
2247             case IdleTimeoutStatusFlagAlreadySet:
2248             {
2249                 //
2250                 // Status flag was already set. This should never happen for the
2251                 // IdleTimeoutSystemManaged flag. The caller ensures this.
2252                 //
2253                 ASSERTMSG(
2254                     "IdleTimeoutManagement::UseSystemManagedIdleTimeout was "
2255                     "called more than once\n", FALSE);
2256             }
2257 
2258             //
2259             //     Fall through
2260             //
2261             //      ||  ||  ||
2262             //      \/  \/  \/
2263             //
2264             case IdleTimeoutStatusFlagsUpdated:
2265             {
2266                 status = STATUS_SUCCESS;
2267             }
2268             break;
2269 
2270             default:
2271             {
2272                 ASSERTMSG("Unexpected IdleTimeoutStatusUpdateResult value\n",
2273                           FALSE);
2274                 status = STATUS_INTERNAL_ERROR;
2275             }
2276         }
2277 
2278     } else {
2279         //
2280         // If we're not running on Windows 8 or above, then there is nothing to
2281         // do.
2282         //
2283         status = STATUS_SUCCESS;
2284     }
2285 
2286     return status;
2287 }
2288 
2289 VOID
FreezeIdleTimeoutManagementStatus(__in PFX_DRIVER_GLOBALS DriverGlobals)2290 IdleTimeoutManagement::FreezeIdleTimeoutManagementStatus(
2291     __in PFX_DRIVER_GLOBALS DriverGlobals
2292     )
2293 {
2294     LONG idleTimeoutSnapshot;
2295     LONG idleTimeoutStatus;
2296     LONG idleTimeoutPreviousStatus;
2297     CfxDevice * device;
2298 
2299     //
2300     // Get the device object so we can use it for logging
2301     //
2302     device = GetDevice();
2303 
2304     //
2305     // Take a snapshot of the idle timeout management status
2306     //
2307     idleTimeoutSnapshot = m_IdleTimeoutStatus;
2308 
2309     //
2310     // Set the bit that freezes the status
2311     //
2312     idleTimeoutStatus = idleTimeoutSnapshot | IdleTimeoutStatusFrozen;
2313 
2314     //
2315     // Update the status
2316     //
2317     idleTimeoutPreviousStatus = InterlockedExchange(&m_IdleTimeoutStatus,
2318                                                     idleTimeoutStatus);
2319 
2320     if (idleTimeoutPreviousStatus != idleTimeoutSnapshot) {
2321         //
2322         // An update of idle timeout status is racing with the freezing of idle
2323         // timeout status
2324         //
2325         DoTraceLevelMessage(
2326             DriverGlobals, TRACE_LEVEL_WARNING, TRACINGPNP,
2327             "WDFDEVICE %p !devobj %p The driver's S0-idle settings and/or power"
2328             " framework settings did not take effect because they were supplied"
2329             " too late. The driver must ensure that the settings are provided "
2330             "before the first start IRP is completed.",
2331             device->GetHandle(),
2332             device->GetDeviceObject()
2333             );
2334         FxVerifierDbgBreakPoint(DriverGlobals);
2335     }
2336 
2337     //
2338     // If the driver has specified power framework settings and system managed
2339     // idle timeout is available on this OS, then the driver must have opted for
2340     // system managed idle timeout.
2341     //
2342     if ((0 != (idleTimeoutStatus & IdleTimeoutPoxSettingsSpecified)) &&
2343         (_SystemManagedIdleTimeoutAvailable()) &&
2344         (0 == (idleTimeoutStatus & IdleTimeoutSystemManaged))) {
2345         DoTraceLevelMessage(
2346             DriverGlobals, TRACE_LEVEL_WARNING, TRACINGPNP,
2347             "WDFDEVICE %p !devobj %p The driver specified power framework "
2348             "settings, but did not opt for system-managed idle timeout.",
2349             device->GetHandle(),
2350             device->GetDeviceObject()
2351             );
2352         FxVerifierDbgBreakPoint(DriverGlobals);
2353     }
2354 }
2355 
2356 BOOLEAN
UsingSystemManagedIdleTimeout(VOID)2357 IdleTimeoutManagement::UsingSystemManagedIdleTimeout(
2358     VOID
2359     )
2360 {
2361     //
2362     // If the value of this constant is changed, the debugger extension needs
2363     // to be fixed as well.
2364     //
2365     C_ASSERT(0x2 == IdleTimeoutSystemManaged);
2366 
2367     return (0 != (m_IdleTimeoutStatus & IdleTimeoutSystemManaged));
2368 }
2369 
2370 BOOLEAN
DriverSpecifiedPowerFrameworkSettings(VOID)2371 IdleTimeoutManagement::DriverSpecifiedPowerFrameworkSettings(
2372     VOID
2373     )
2374 {
2375     return (0 != (m_IdleTimeoutStatus & IdleTimeoutPoxSettingsSpecified));
2376 }
2377 
2378 NTSTATUS
CommitPowerFrameworkSettings(__in PFX_DRIVER_GLOBALS DriverGlobals,__in PPOX_SETTINGS PoxSettings)2379 IdleTimeoutManagement::CommitPowerFrameworkSettings(
2380     __in PFX_DRIVER_GLOBALS DriverGlobals,
2381     __in PPOX_SETTINGS PoxSettings
2382     )
2383 {
2384     NTSTATUS status;
2385     IdleTimeoutStatusUpdateResult statusUpdateResult;
2386     PVOID oldPoxSettings = NULL;
2387     BOOLEAN settingsSuccessfullySaved = FALSE;
2388     CfxDevice * device;
2389 
2390     //
2391     // We should never get here if system-managed idle timeout is not available
2392     //
2393     ASSERT(_SystemManagedIdleTimeoutAvailable());
2394 
2395     //
2396     // Get the device object so we can use it for logging
2397     //
2398     device = GetDevice();
2399 
2400     //
2401     // Try to save the driver's power framework settings
2402     //
2403     oldPoxSettings = InterlockedCompareExchangePointer((PVOID*) &m_PoxSettings,
2404                                                        PoxSettings,
2405                                                        NULL // Comparand
2406                                                        );
2407     if (NULL != oldPoxSettings) {
2408         //
2409         // The driver's power framework settings have already been specified
2410         // earlier. The driver should not be attempting to specify them more
2411         // than once.
2412         //
2413         status = STATUS_INVALID_DEVICE_REQUEST;
2414         DoTraceLevelMessage(
2415             DriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
2416             "WDFDEVICE %p !devobj %p The driver attempted to specify power "
2417             "framework settings more than once. %!STATUS!.",
2418             device->GetHandle(),
2419             device->GetDeviceObject(),
2420             status
2421             );
2422         FxVerifierDbgBreakPoint(DriverGlobals);
2423         goto exit;
2424     }
2425     settingsSuccessfullySaved = TRUE;
2426 
2427     //
2428     // Try to update the flag that indicates that the client driver has
2429     // specified settings that are to be used when we register with the power
2430     // framework.
2431     //
2432     statusUpdateResult = UpdateIdleTimeoutStatus(
2433                                 IdleTimeoutPoxSettingsSpecified
2434                                 );
2435     switch (statusUpdateResult) {
2436         case IdleTimeoutStatusFlagsAlreadyFrozen:
2437         {
2438             //
2439             // Status is already frozen. Too late to update it.
2440             //
2441             status = STATUS_INVALID_DEVICE_REQUEST;
2442             DoTraceLevelMessage(
2443                 DriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
2444                 "WDFDEVICE %p !devobj %p Power framework settings must be "
2445                 "specified before the first start IRP is completed. %!STATUS!.",
2446                 device->GetHandle(),
2447                 device->GetDeviceObject(),
2448                 status
2449                 );
2450             FxVerifierDbgBreakPoint(DriverGlobals);
2451             goto exit;
2452         }
2453         break;
2454 
2455         case IdleTimeoutStatusFlagsUnexpected:
2456         {
2457             //
2458             // Status being updated from multiple threads in parallel. Not
2459             // supported.
2460             //
2461             status = STATUS_INVALID_DEVICE_REQUEST;
2462             DoTraceLevelMessage(
2463                 DriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
2464                 "WDFDEVICE %p !devobj %p Calls to assign S0-idle settings and "
2465                 "to specify power framework settings are happening in parallel."
2466                 " The driver needs to serialize these calls with respect to "
2467                 "each other. %!STATUS!.",
2468                 device->GetHandle(),
2469                 device->GetDeviceObject(),
2470                 status
2471                 );
2472             FxVerifierDbgBreakPoint(DriverGlobals);
2473             goto exit;
2474         }
2475         break;
2476 
2477         case IdleTimeoutStatusFlagAlreadySet:
2478         {
2479             //
2480             // Status flag was already set. This should never happen for the
2481             // IdleTimeoutPoxSettingsSpecified flag because we have logic in the
2482             // beginning of this function to ensure that only the first caller
2483             // attempts to set this flag.
2484             //
2485             ASSERTMSG(
2486                 "Attempt to set the IdleTimeoutPoxSettingsSpecified flag more "
2487                 "than once\n", FALSE);
2488             status = STATUS_INTERNAL_ERROR;
2489             goto exit;
2490         }
2491 
2492         case IdleTimeoutStatusFlagsUpdated:
2493         {
2494             status = STATUS_SUCCESS;
2495         }
2496         break;
2497 
2498         default:
2499         {
2500             ASSERTMSG("Unexpected IdleTimeoutStatusUpdateResult value\n",
2501                       FALSE);
2502             status = STATUS_INTERNAL_ERROR;
2503             goto exit;
2504         }
2505     }
2506 
2507     //
2508     // If we get here, we must have a successful status
2509     //
2510     ASSERT(STATUS_SUCCESS == status);
2511 
2512 exit:
2513     if (FALSE == NT_SUCCESS(status)) {
2514         if (settingsSuccessfullySaved) {
2515             //
2516             // Since a failure has occurred, we must reset the pointer to the
2517             // power framework settings.
2518             //
2519             m_PoxSettings = NULL;
2520         }
2521     }
2522     return status;
2523 }
2524 
~PolicySettings()2525 PolicySettings::~PolicySettings()
2526 {
2527 
2528 
2529 
2530 
2531 
2532 
2533 
2534 }
2535 
FxPowerPolicyMachine(VOID)2536 FxPowerPolicyMachine::FxPowerPolicyMachine(
2537     VOID
2538     ) : FxThreadedEventQueue(FxPowerPolicyEventQueueDepth)
2539 {
2540     m_Owner = NULL;
2541 
2542     RtlZeroMemory(&m_Queue[0], sizeof(m_Queue));
2543     RtlZeroMemory(&m_States, sizeof(m_States));
2544 
2545     m_States.History[IncrementHistoryIndex()] = WdfDevStatePwrPolObjectCreated;
2546 
2547     m_SingularEventsPresent = 0x0;
2548 }
2549 
~FxPowerPolicyMachine(VOID)2550 FxPowerPolicyMachine::~FxPowerPolicyMachine(
2551     VOID
2552     )
2553 {
2554     if (m_Owner != NULL) {
2555         delete m_Owner;
2556         m_Owner = NULL;
2557     }
2558 }
2559 
2560 _Must_inspect_result_
2561 NTSTATUS
InitUsbSS(VOID)2562 FxPowerPolicyMachine::InitUsbSS(
2563     VOID
2564     )
2565 {
2566     FxUsbIdleInfo* pInfo;
2567     NTSTATUS status;
2568 
2569     //
2570     // The field is already set, we are good to go
2571     //
2572     if (m_Owner->m_UsbIdle != NULL) {
2573         return STATUS_SUCCESS;
2574     }
2575 
2576     pInfo = new (m_PkgPnp->GetDriverGlobals()) FxUsbIdleInfo(m_PkgPnp);
2577 
2578     if (pInfo == NULL) {
2579         return STATUS_INSUFFICIENT_RESOURCES;
2580     }
2581 
2582     status = pInfo->Initialize();
2583     if (!NT_SUCCESS(status)) {
2584         delete pInfo;
2585         return status;
2586     }
2587 
2588     if (InterlockedCompareExchangePointer((PVOID*) &m_Owner->m_UsbIdle,
2589                                           pInfo,
2590                                           NULL) == NULL) {
2591         //
2592         // This thread was the one that set the field value.
2593         //
2594         DO_NOTHING();
2595     }
2596     else {
2597         //
2598         // Another thread raced in and beat this thread in setting the field,
2599         // just delete our allocation and use the other allocated FxUsbIdleInfo.
2600         //
2601         delete pInfo;
2602     }
2603 
2604     return STATUS_SUCCESS;
2605 }
2606 
FxPowerPolicyOwnerSettings(__in FxPkgPnp * PkgPnp)2607 FxPowerPolicyOwnerSettings::FxPowerPolicyOwnerSettings(
2608     __in FxPkgPnp* PkgPnp
2609     ) : m_PoxInterface(PkgPnp)
2610 {
2611     ULONG i;
2612 
2613     m_UsbIdle = NULL;
2614 
2615     m_PkgPnp = PkgPnp;
2616 
2617     //
2618     // Default every state to D3 except for system working which is D0 by
2619     // default.
2620     //
2621     m_SystemToDeviceStateMap = 0x0;
2622 
2623     for (i = 0; i < PowerSystemMaximum; i++) {
2624         FxPkgPnp::_SetPowerCapState(i,
2625                                     i == PowerSystemWorking ? PowerDeviceD0
2626                                                             : PowerDeviceD3,
2627                                     &m_SystemToDeviceStateMap);
2628     }
2629 
2630     m_IdealDxStateForSx = PowerDeviceD3;
2631 
2632     m_RequestedPowerUpIrp = FALSE;
2633     m_RequestedPowerDownIrp = FALSE;
2634     m_RequestedWaitWakeIrp = FALSE;
2635     m_WakeCompletionEventDropped = FALSE;
2636     m_PowerFailed = FALSE;
2637     m_CanSaveState = TRUE;
2638 
2639     m_ChildrenCanPowerUp = FALSE;
2640     m_ChildrenPoweredOnCount = 0;
2641     m_ChildrenArmedCount = 0;
2642 
2643     m_WaitWakeStatus = STATUS_NOT_SUPPORTED;
2644     m_SystemWakeSource = FALSE;
2645     m_WaitWakeCancelCompletionOwnership = CancelOwnershipUnclaimed;
2646 
2647     m_PowerCallbackObject = NULL;
2648     m_PowerCallbackRegistration = NULL;
2649 }
2650 
~FxPowerPolicyOwnerSettings(VOID)2651 FxPowerPolicyOwnerSettings::~FxPowerPolicyOwnerSettings(
2652     VOID
2653     )
2654 {
2655     //
2656     // There are paths which cleanup this object which  do not go through the
2657     // pnp state machine, so make sure the power object callback fields are
2658     // freed.  In these paths, we are guaranteed PASSIVE_LEVEL b/c there will
2659     // be no dangling references which can cause deletion at a greater IRQL.
2660     //
2661     CleanupPowerCallback();
2662 
2663     if (m_UsbIdle != NULL) {
2664         delete m_UsbIdle;
2665         m_UsbIdle = NULL;
2666     }
2667 }
2668 
2669 VOID
CleanupPowerCallback(VOID)2670 FxPowerPolicyOwnerSettings::CleanupPowerCallback(
2671     VOID
2672     )
2673 /*++
2674 
2675 Routine Description:
2676     Cleans up the power state callback registration for this object.
2677 
2678 Arguments:
2679     None
2680 
2681 Return Value:
2682     None
2683 
2684   --*/
2685 {
2686     if (m_PowerCallbackRegistration != NULL) {
2687         Mx::UnregisterCallback(m_PowerCallbackRegistration);
2688         m_PowerCallbackRegistration = NULL;
2689 
2690     }
2691 
2692     if (m_PowerCallbackObject != NULL) {
2693         Mx::MxDereferenceObject(m_PowerCallbackObject);
2694         m_PowerCallbackObject = NULL;
2695     }
2696 }
2697 
2698 _Must_inspect_result_
2699 NTSTATUS
Init(VOID)2700 FxPowerPolicyOwnerSettings::Init(
2701     VOID
2702     )
2703 /*++
2704 
2705 Routine Description:
2706     Initialize the object.  We will try to register a power state callback so
2707     that we can be informed of when the machine is changing S states.  We are
2708     interested in system state changes because we need to know when NOT to write
2709     to the registry (to save wake settings) so that we don't cause a deadlock
2710     in a non power pageable device while moving into Sx.
2711 
2712 Arguments:
2713     None
2714 
2715 Return Value:
2716     NTSTATUS
2717 
2718   --*/
2719 {
2720     OBJECT_ATTRIBUTES oa;
2721     UNICODE_STRING string;
2722     NTSTATUS status;
2723 
2724     RtlInitUnicodeString(&string, L"\\Callback\\PowerState");
2725     InitializeObjectAttributes(
2726         &oa,
2727         &string,
2728         OBJ_CASE_INSENSITIVE,
2729         NULL,
2730         NULL
2731         );
2732 
2733     //
2734     // Create a callback object, but we do not want to be the first ones
2735     // to create it (it should be created way before we load in NTOS
2736     // anyways)
2737     //
2738     status = Mx::CreateCallback(&m_PowerCallbackObject, &oa, FALSE, TRUE);
2739 
2740     if (NT_SUCCESS(status)) {
2741         m_PowerCallbackRegistration = Mx::RegisterCallback(
2742             m_PowerCallbackObject,
2743             _PowerStateCallback,
2744             this
2745             );
2746 
2747         if (m_PowerCallbackRegistration == NULL) {
2748             //
2749             // Non-critical failure, so we'll free the callback object and keep
2750             // going
2751             //
2752             Mx::MxDereferenceObject(m_PowerCallbackObject);
2753             m_PowerCallbackObject = NULL;
2754         }
2755     }
2756 
2757     //
2758     // Initialize FxPowerIdleMachine
2759     //
2760     status = m_PowerIdleMachine.Init();
2761     if (!NT_SUCCESS(status)) {
2762         return status;
2763     }
2764 
2765     return status;
2766 }
2767 
2768 VOID
_PowerStateCallback(__in PVOID Context,__in_opt PVOID Argument1,__in_opt PVOID Argument2)2769 FxPowerPolicyOwnerSettings::_PowerStateCallback(
2770     __in     PVOID Context,
2771     __in_opt PVOID Argument1,
2772     __in_opt PVOID Argument2
2773     )
2774 /*++
2775 
2776 Routine Description:
2777     Callback invoked by the power subsystem when the system is changing S states
2778 
2779 Arguments:
2780     Context -  FxPowerPolicyOwnerSettings pointer (the "this" pointer)
2781 
2782     Argument1 - Reason why the callback was invoked, we only care about
2783                 PO_CB_SYSTEM_STATE_LOCK
2784 
2785     Argument2 - State transition that is occurring
2786 
2787 Return Value:
2788     None
2789 
2790   --*/
2791 {
2792     FxPowerPolicyOwnerSettings* pThis;
2793 
2794     pThis = (FxPowerPolicyOwnerSettings*) Context;
2795 
2796     if (Argument1 != (PVOID) PO_CB_SYSTEM_STATE_LOCK) {
2797         return;
2798     }
2799 
2800     pThis->m_PkgPnp->m_PowerPolicyMachine.m_StateMachineLock.AcquireLock(
2801         pThis->m_PkgPnp->GetDriverGlobals(),
2802         NULL
2803         );
2804 
2805     if (Argument2 == (PVOID) 0) {
2806         //
2807         // Write out the state if necessary before we turn off the paging path.
2808         //
2809         pThis->m_PkgPnp->SaveState(TRUE);
2810 
2811         //
2812         // Exiting S0
2813         //
2814         pThis->m_CanSaveState = FALSE;
2815     }
2816     else if (Argument2 == (PVOID) 1) {
2817         //
2818         // We have reentered S0
2819         //
2820         pThis->m_CanSaveState = TRUE;
2821 
2822         //
2823         // Write out the state if necessary now that the paging path is back
2824         //
2825         pThis->m_PkgPnp->SaveState(TRUE);
2826     }
2827 
2828     pThis->m_PkgPnp->m_PowerPolicyMachine.m_StateMachineLock.ReleaseLock(
2829         pThis->m_PkgPnp->GetDriverGlobals()
2830         );
2831 }
2832 
2833 /*++
2834 
2835 The locking model for the Power policy state machine requires that events be enqueued
2836 possibly at DISPATCH_LEVEL.  It also requires that the state machine be
2837 runnable at PASSIVE_LEVEL.  Consequently, we have two locks, one DISPATCH_LEVEL
2838 lock that guards the event queue and one PASSIVE_LEVEL lock that guards the
2839 state machine itself.
2840 
2841 The Power policy state machine has a few constraints that the PnP state machine
2842 doesn't.  Sometimes it has to call some driver functions at PASSIVE_LEVEL, but
2843 with the disks turned off.  This means that these functions absolutely must not
2844 page fault.  You might think that this means that we should call the driver at
2845 DISPATCH_LEVEL, and you'd be right if your only concern were for perfectly
2846 safe code.  The problem with that approach, though is that it will force much
2847 of the rest of the driver to DISPATCH_LEVEL, which will only push the driver
2848 writer into using lots of asynchronous work items, which will complicate their
2849 code and make it unsafe in a new variety of ways.  So we're going to go with
2850 PASSIVE_LEVEL here and setting a timeout of 20 seconds.  If the driver faults,
2851 the timer will fire and log the failure.  This also means that the driver must
2852 complete these callbacks within 20 seconds.  Even beyond that, it means that
2853 the work items must be queued onto a special thread, one that once the machine
2854 has started to go to sleep, never handles any work items that may fault.
2855 
2856 Algorithm:
2857 
2858 1)  Acquire the Power policy queue lock.
2859 2)  Enqueue the event.  events are put at the end of the queue.
2860 3)  Drop the Power policy queue lock.
2861 4)  If the thread is running at PASSIVE_LEVEL, skip to step 6.
2862 5)  Queue a work item onto the special power thread.
2863 6)  Attempt to acquire the state machine lock, with a zero-length timeout (*).
2864 7)  If successful, skip to step 9.
2865 8)  Queue a work item onto the special power thread.
2866 9)  Acquire the state machine lock.
2867 10) Acquire the Power policy queue lock.
2868 11) Attempt to dequeue an event.
2869 12) Drop the Power  policyqueue lock.
2870 13) If there was no event to dequeue, drop the state machine lock and exit.
2871 14) Execute the state handler.  This may involve taking one of the other state
2872     machine queue locks, briefly, to deliver an event.
2873 15) Go to Step 10.
2874 
2875 (*) zero length is different then NULL (infinite) being passed for the timeout
2876 
2877 Implementing this algorithm requires three functions.
2878 
2879 PowerPolicyProcessEvent         -- Implements steps 1-8.
2880 _PowerPolicyProcessEventInner   -- Implements step 9.
2881 PowerPolicyProcessEventInner    -- Implements steps 10-15.
2882 
2883 --*/
2884 
2885 VOID
PowerPolicyProcessEvent(__in FxPowerPolicyEvent Event,__in BOOLEAN ProcessOnDifferentThread)2886 FxPkgPnp::PowerPolicyProcessEvent(
2887     __in FxPowerPolicyEvent Event,
2888     __in BOOLEAN ProcessOnDifferentThread
2889     )
2890 /*++
2891 
2892 Routine Description:
2893     This function implements steps 1-8 of the algorithm described above.
2894 
2895 Arguments:
2896     Event - Current Power event
2897 
2898 Return Value:
2899 
2900     NTSTATUS
2901 
2902 --*/
2903 {
2904     NTSTATUS status;
2905     ULONG mask;
2906     KIRQL irql;
2907 
2908     //
2909     // Take the lock, raising to DISPATCH_LEVEL.
2910     //
2911     m_PowerPolicyMachine.Lock(&irql);
2912 
2913     //
2914     // If the input Event is any of the events described by PowerSingularEventMask,
2915     // then check whether it is already queued up. If so, then dont enqueue this
2916     // Event.
2917     //
2918     if (Event & PowerPolSingularEventMask) {
2919         if ((m_PowerPolicyMachine.m_SingularEventsPresent & Event) == 0x00) {
2920             m_PowerPolicyMachine.m_SingularEventsPresent |= Event;
2921         }
2922         else {
2923             DoTraceLevelMessage(
2924                 GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGPNP,
2925                 "WDFDEVICE 0x%p !devobj 0x%p current pwr pol state "
2926                 "%!WDF_DEVICE_POWER_POLICY_STATE! dropping event "
2927                 "%!FxPowerPolicyEvent! because the Event is already enqueued.",
2928                 m_Device->GetHandle(),
2929                 m_Device->GetDeviceObject(),
2930                 m_Device->GetDevicePowerPolicyState(), Event);
2931 
2932             m_PowerPolicyMachine.Unlock(irql);
2933             return;
2934         }
2935     }
2936 
2937     if (m_PowerPolicyMachine.IsFull()) {
2938         //
2939         // The queue is full.  Bail.
2940         //
2941         m_PowerPolicyMachine.Unlock(irql);
2942 
2943         ASSERT(!"The Power queue is full.  This shouldn't be able to happen.");
2944         return;
2945     }
2946 
2947     if (m_PowerPolicyMachine.IsClosedLocked()) {
2948         DoTraceLevelMessage(
2949             GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGPNP,
2950             "WDFDEVICE 0x%p !devobj 0x%p current pwr pol state "
2951             "%!WDF_DEVICE_POWER_POLICY_STATE! dropping event "
2952             "%!FxPowerPolicyEvent! because of a closed queue",
2953             m_Device->GetHandle(),
2954             m_Device->GetDeviceObject(),
2955             m_Device->GetDevicePowerPolicyState(), Event);
2956 
2957         //
2958         // The queue is closed.  Bail
2959         //
2960         m_PowerPolicyMachine.Unlock(irql);
2961 
2962         return;
2963     }
2964 
2965     //
2966     // Enqueue the event.  Whether the event goes on the front
2967     // or the end of the queue depends on which event it is and if we are the
2968     // PPO or not.
2969     //
2970     // Yes, mask could be a member variable of m_PowerPolicyMachine, but why
2971     // waste 4 bytes when it is very easy to figure out?
2972     //
2973     mask = IsPowerPolicyOwner() ? PwrPolPriorityEventsMask
2974                                 : PwrPolNotOwnerPriorityEventsMask;
2975 
2976     if (Event & mask) {
2977         //
2978         // Stick it on the front of the queue, making it the next event that
2979         // will be processed if, otherwise let these events go by.
2980         //
2981         m_PowerPolicyMachine.m_Queue[m_PowerPolicyMachine.InsertAtHead()] = Event;
2982     }
2983     else {
2984         //
2985         // Stick it on the end of the queue.
2986         //
2987         m_PowerPolicyMachine.m_Queue[m_PowerPolicyMachine.InsertAtTail()] = Event;
2988     }
2989 
2990     //
2991     // Drop the lock.
2992     //
2993     m_PowerPolicyMachine.Unlock(irql);
2994 
2995     //
2996     // Now, if we are running at PASSIVE_LEVEL, attempt to run the state
2997     // machine on this thread.  If we can't do that, then queue a work item.
2998     //
2999     if (FALSE == ShouldProcessPowerPolicyEventOnDifferentThread(
3000                     irql,
3001                     ProcessOnDifferentThread
3002                     )) {
3003 
3004         LONGLONG timeout = 0;
3005 
3006         status = m_PowerPolicyMachine.m_StateMachineLock.AcquireLock(
3007             GetDriverGlobals(), &timeout);
3008 
3009         if (FxWaitLockInternal::IsLockAcquired(status)) {
3010             FxPostProcessInfo info;
3011 
3012             //
3013             // We now hold the state machine lock.  So call the function that
3014             // dispatches the next state.
3015             //
3016             PowerPolicyProcessEventInner(&info);
3017 
3018             //
3019             // The pnp state machine should be the only one deleting the object
3020             //
3021             ASSERT(info.m_DeleteObject == FALSE);
3022 
3023             m_PowerPolicyMachine.m_StateMachineLock.ReleaseLock(
3024                 GetDriverGlobals());
3025 
3026             info.Evaluate(this);
3027 
3028             return;
3029         }
3030     }
3031 
3032     //
3033     // The tag added above will be released when the work item runs
3034     //
3035 
3036     //
3037     // For one reason or another, we couldn't run the state machine on this
3038     // thread.  So queue a work item to do it.  If m_PnPWorkItemEnqueuing
3039     // is non-zero, that means that the work item is already being enqueued
3040     // on another thread.  This is significant, since it means that we can't do
3041     // anything with the work item on this thread, but it's okay, since the
3042     // work item will pick up our work and do it.
3043     //
3044     m_PowerPolicyMachine.QueueToThread();
3045 }
3046 
3047 VOID
_PowerPolicyProcessEventInner(__inout FxPkgPnp * This,__inout FxPostProcessInfo * Info,__in PVOID Context)3048 FxPkgPnp::_PowerPolicyProcessEventInner(
3049     __inout FxPkgPnp* This,
3050     __inout FxPostProcessInfo* Info,
3051     __in    PVOID Context
3052     )
3053 {
3054 
3055     UNREFERENCED_PARAMETER(Context);
3056 
3057     //
3058     // Take the state machine lock.
3059     //
3060     This->m_PowerPolicyMachine.m_StateMachineLock.AcquireLock(
3061         This->GetDriverGlobals()
3062         );
3063 
3064     //
3065     // Call the function that will actually run the state machine.
3066     //
3067     This->PowerPolicyProcessEventInner(Info);
3068 
3069     //
3070     // We are being called from the work item and m_WorkItemRunning is > 0, so
3071     // we cannot be deleted yet.
3072     //
3073     ASSERT(Info->SomethingToDo() == FALSE);
3074 
3075     //
3076     // Now release the lock
3077     //
3078     This->m_PowerPolicyMachine.m_StateMachineLock.ReleaseLock(
3079         This->GetDriverGlobals()
3080         );
3081 }
3082 
3083 VOID
PowerPolicyProcessEventInner(__inout FxPostProcessInfo * Info)3084 FxPkgPnp::PowerPolicyProcessEventInner(
3085     __inout FxPostProcessInfo* Info
3086     )
3087 {
3088     WDF_DEVICE_POWER_POLICY_STATE newState;
3089     FxPowerPolicyEvent event;
3090     ULONG i;
3091     KIRQL irql;
3092 
3093     if (IsPowerPolicyOwner()) {
3094         CPPOWER_POLICY_STATE_TABLE entry;
3095 
3096         //
3097         // Process as many events as we can.
3098         //
3099         for ( ; ; ) {
3100             entry = GetPowerPolicyTableEntry(m_Device->GetDevicePowerPolicyState());
3101 
3102             //
3103             // Get an event from the queue.
3104             //
3105             m_PowerPolicyMachine.Lock(&irql);
3106 
3107             if (m_PowerPolicyMachine.IsEmpty()) {
3108                 m_PowerPolicyMachine.GetFinishedState(Info);
3109 
3110                 //
3111                 // The queue is empty.
3112                 //
3113                 m_PowerPolicyMachine.Unlock(irql);
3114                 return;
3115             }
3116 
3117             event = m_PowerPolicyMachine.m_Queue[m_PowerPolicyMachine.GetHead()];
3118 
3119             //
3120             // At this point, we need to determine whether we can process this
3121             // event.
3122             //
3123             if (event & PwrPolPriorityEventsMask) {
3124                 //
3125                 // These are always possible to handle.
3126                 //
3127                 DO_NOTHING();
3128             }
3129             else {
3130                 //
3131                 // Check to see if this state can handle new events, ie if this
3132                 // is a green dot (queue open) or red dot (queue *not* open) state.
3133                 //
3134                 if (entry->StateInfo.Bits.QueueOpen == FALSE) {
3135                     //
3136                     // This state can't handle new events.
3137                     //
3138                     m_PowerPolicyMachine.Unlock(irql);
3139                     return;
3140                 }
3141             }
3142 
3143             //
3144             // If the event obtained from the queue was a singular event, then
3145             // clear the flag to allow other similar events to be put into this
3146             // queue for processing.
3147             //
3148             if (m_PowerPolicyMachine.m_SingularEventsPresent & event) {
3149                m_PowerPolicyMachine.m_SingularEventsPresent &= ~event;
3150             }
3151 
3152             m_PowerPolicyMachine.IncrementHead();
3153             m_PowerPolicyMachine.Unlock(irql);
3154 
3155             //
3156             // Find the entry in the power policy state table that corresponds
3157             // to this event.
3158             //
3159             newState = WdfDevStatePwrPolNull;
3160 
3161             if (entry->FirstTargetState.PowerPolicyEvent == event) {
3162                 newState = entry->FirstTargetState.TargetState;
3163 
3164                 DO_EVENT_TRAP(&entry->FirstTargetState);
3165             }
3166             else if (entry->OtherTargetStates != NULL) {
3167                 for (i = 0;
3168                      entry->OtherTargetStates[i].PowerPolicyEvent != PwrPolNull;
3169                      i++) {
3170                     if (entry->OtherTargetStates[i].PowerPolicyEvent == event) {
3171                         newState = entry->OtherTargetStates[i].TargetState;
3172                         DO_EVENT_TRAP(&entry->OtherTargetStates[i]);
3173                         break;
3174                     }
3175                 }
3176             }
3177 
3178             if (newState == WdfDevStatePwrPolNull) {
3179                 //
3180                 // This state doesn't respond to the event.  Just throw the event
3181                 // away.
3182                 //
3183                 DoTraceLevelMessage(
3184                     GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGPNP,
3185                     "WDFDEVICE 0x%p !devobj 0x%p current pwr pol state "
3186                     "%!WDF_DEVICE_POWER_POLICY_STATE! dropping event "
3187                     "%!FxPowerPolicyEvent!", m_Device->GetHandle(),
3188                     m_Device->GetDeviceObject(),
3189                     m_Device->GetDevicePowerPolicyState(), event);
3190 
3191                 if ((entry->StateInfo.Bits.KnownDroppedEvents & event) == 0) {
3192                     COVERAGE_TRAP();
3193 
3194                     DoTraceLevelMessage(
3195                         GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
3196                         "WDFDEVICE 0x%p !devobj 0x%p current state "
3197                         "%!WDF_DEVICE_POWER_POLICY_STATE!, policy event "
3198                         "%!FxPowerPolicyEvent! is not a known dropped "
3199                         "event, known dropped events are %!FxPowerPolicyEvent!",
3200                         m_Device->GetHandle(), m_Device->GetDeviceObject(),
3201                         m_Device->GetDevicePowerPolicyState(),
3202                         event, entry->StateInfo.Bits.KnownDroppedEvents);
3203 
3204 
3205                 }
3206 
3207                 //
3208                 // Failsafes for events which have required processing in them.
3209                 //
3210                 switch (event) {
3211                 case PwrPolSx:
3212                     //
3213                     // The Sx handling code expects that the state machine
3214                     // complete the Sx irp.  (S0 irps are never pended).  Since
3215                     // we don't have a state to transition to that will complete
3216                     // the request, do so now.
3217                     //
3218                     // (This can legitimately happen if a PDO is disabled and
3219                     //  the machines moves into an Sx state.)
3220                     //
3221                     PowerPolicyCompleteSystemPowerIrp();
3222                     break;
3223 
3224                 case PwrPolUsbSelectiveSuspendCompleted:
3225                     //
3226                     // This state did not handle the event and event got
3227                     // dropped. However some state is definitely going to wait
3228                     // for this event. That's why we need m_EventDropped flag.
3229                     // If we didn't have this flag there will be no way to know
3230                     // if the event got dropped and some state will end up
3231                     // waiting for it indefinitely.
3232                     //
3233                     m_PowerPolicyMachine.m_Owner->m_UsbIdle->m_EventDropped = TRUE;
3234                     break;
3235 
3236                 case PwrPolUsbSelectiveSuspendCallback:
3237                     m_PowerPolicyMachine.UsbSSCallbackProcessingComplete();
3238                     break;
3239 
3240                 case PwrPolWakeSuccess:
3241                 case PwrPolWakeFailed:
3242                     //
3243                     // This state did not handle the event and event got
3244                     // dropped. However some state is definitely going to wait
3245                     // for this event. That's why we need
3246                     // m_WakeCompletionEventDropped flag. If we didn't have this
3247                     // flag there will be no way to know if the event got
3248                     // dropped and some state will end up waiting for it
3249                     // indefinitely.
3250                     //
3251                     m_PowerPolicyMachine.m_Owner->m_WakeCompletionEventDropped = TRUE;
3252                     break;
3253 
3254                 default:
3255                     DO_NOTHING();
3256                     break;
3257                 }
3258             }
3259             else {
3260                 //
3261                 // Now enter the new state.
3262                 //
3263                 PowerPolicyEnterNewState(newState);
3264             }
3265         }
3266     }
3267     else {
3268         //
3269         // Process as many events as we can.
3270         //
3271         for ( ; ; ) {
3272             CPNOT_POWER_POLICY_OWNER_STATE_TABLE entry;
3273 
3274 #pragma prefast(suppress:__WARNING_DEREF_NULL_PTR, "The current power policy state will always be in the table so entry will never be NULL")
3275             entry = GetNotPowerPolicyOwnerTableEntry(
3276                 m_Device->GetDevicePowerPolicyState()
3277                 );
3278 
3279             //
3280             // Get an event from the queue.
3281             //
3282             m_PowerPolicyMachine.Lock(&irql);
3283 
3284             if (m_PowerPolicyMachine.IsEmpty()) {
3285                 //
3286                 // The queue is empty.
3287                 //
3288                 m_PowerPolicyMachine.Unlock(irql);
3289                 return;
3290             }
3291 
3292             event = m_PowerPolicyMachine.m_Queue[m_PowerPolicyMachine.GetHead()];
3293 
3294             //
3295             // At this point, we need to determine whether we can process this
3296             // event.
3297             //
3298             if (event & PwrPolNotOwnerPriorityEventsMask) {
3299                 //
3300                 // These are always possible to handle.
3301                 //
3302                 DO_NOTHING();
3303             }
3304             else {
3305                 //
3306                 // Check to see if this state can handle new events, ie if this
3307                 // is a green dot (queue open) or red dot (queue *not* open) state.
3308                 //
3309                 if (entry->QueueOpen == FALSE) {
3310                     //
3311                     // This state can't handle new events.
3312                     //
3313                     m_PowerPolicyMachine.Unlock(irql);
3314                     return;
3315                 }
3316             }
3317 
3318             //
3319             // If the event obtained from the queue was a singular event, then
3320             // clear the flag to allow other similar events to be put into this
3321             // queue for processing.
3322             //
3323             if (m_PowerPolicyMachine.m_SingularEventsPresent & event) {
3324                m_PowerPolicyMachine.m_SingularEventsPresent &= ~event;
3325             }
3326 
3327             m_PowerPolicyMachine.IncrementHead();
3328             m_PowerPolicyMachine.Unlock(irql);
3329 
3330             if (entry != NULL && entry->TargetStatesCount > 0) {
3331                 for (i = 0; i < entry->TargetStatesCount; i++) {
3332                     if (event == entry->TargetStates[i].PowerPolicyEvent) {
3333                         DO_EVENT_TRAP(&entry->TargetStates[i]);
3334 
3335                         //
3336                         // Now enter the new state.
3337                         //
3338                         NotPowerPolicyOwnerEnterNewState(
3339                             entry->TargetStates[i].TargetState);
3340                         break;
3341                     }
3342                 }
3343             }
3344         }
3345     }
3346 }
3347 
3348 VOID
PowerPolicyEnterNewState(__in WDF_DEVICE_POWER_POLICY_STATE NewState)3349 FxPkgPnp::PowerPolicyEnterNewState(
3350     __in WDF_DEVICE_POWER_POLICY_STATE NewState
3351     )
3352 /*++
3353 
3354 Routine Description:
3355     This function looks up the handler for a state and then calls it.
3356 
3357 Arguments:
3358     Event - Current power plicy event
3359 
3360 Return Value:
3361 
3362     NTSTATUS
3363 
3364 --*/
3365 {
3366     CPPOWER_POLICY_STATE_TABLE entry;
3367     WDF_DEVICE_POWER_POLICY_STATE currentState, newState;
3368     WDF_DEVICE_POWER_POLICY_NOTIFICATION_DATA data;
3369     FxWatchdog watchdog(this);
3370 
3371     currentState = m_Device->GetDevicePowerPolicyState();
3372     newState = NewState;
3373 
3374     while (newState != WdfDevStatePwrPolNull) {
3375         DoTraceLevelMessage(
3376             GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGPNPPOWERSTATES,
3377             "WDFDEVICE 0x%p !devobj 0x%p entering power policy state "
3378             "%!WDF_DEVICE_POWER_POLICY_STATE! from "
3379             "%!WDF_DEVICE_POWER_POLICY_STATE!", m_Device->GetHandle(),
3380             m_Device->GetDeviceObject(), newState, currentState);
3381 
3382         if (m_PowerPolicyStateCallbacks != NULL) {
3383             //
3384             // Callback for leaving the old state
3385             //
3386             RtlZeroMemory(&data, sizeof(data));
3387 
3388             data.Type = StateNotificationLeaveState;
3389             data.Data.LeaveState.CurrentState = currentState;
3390             data.Data.LeaveState.NewState = newState;
3391 
3392             m_PowerPolicyStateCallbacks->Invoke(currentState,
3393                                                 StateNotificationLeaveState,
3394                                                 m_Device->GetHandle(),
3395                                                 &data);
3396         }
3397 
3398         m_PowerPolicyMachine.m_States.History[
3399             m_PowerPolicyMachine.IncrementHistoryIndex()] = (USHORT) newState;
3400 
3401         if (m_PowerPolicyStateCallbacks != NULL) {
3402             //
3403             // Callback for entering the new state
3404             //
3405             RtlZeroMemory(&data, sizeof(data));
3406 
3407             data.Type = StateNotificationEnterState;
3408             data.Data.EnterState.CurrentState = currentState;
3409             data.Data.EnterState.NewState = newState;
3410 
3411             m_PowerPolicyStateCallbacks->Invoke(newState,
3412                                                 StateNotificationEnterState,
3413                                                 m_Device->GetHandle(),
3414                                                 &data);
3415         }
3416 
3417         m_Device->SetDevicePowerPolicyState(newState);
3418         currentState = newState;
3419 
3420         entry = GetPowerPolicyTableEntry(currentState);
3421 
3422         //
3423         // And call the state handler, if there is one.
3424         //
3425         if (entry->StateFunc != NULL) {
3426             watchdog.StartTimer(currentState);
3427             newState = entry->StateFunc(this);
3428             watchdog.CancelTimer(currentState);
3429 
3430             //
3431             // Validate the return value if FX_STATE_MACHINE_VERIFY is enabled
3432             //
3433             VALIDATE_PWR_POL_STATE(currentState, newState);
3434 
3435         }
3436         else {
3437             newState = WdfDevStatePwrPolNull;
3438         }
3439 
3440         if (m_PowerPolicyStateCallbacks != NULL) {
3441             //
3442             // Callback for post processing the new state
3443             //
3444             RtlZeroMemory(&data, sizeof(data));
3445 
3446             data.Type = StateNotificationPostProcessState;
3447             data.Data.PostProcessState.CurrentState = currentState;
3448 
3449             m_PowerPolicyStateCallbacks->Invoke(currentState,
3450                                                 StateNotificationPostProcessState,
3451                                                 m_Device->GetHandle(),
3452                                                 &data);
3453         }
3454     }
3455 }
3456 
3457 
3458 /*++
3459 
3460 One of the goals of the Driver Framework is to make it really easy to write
3461 a driver for a device which keeps the device in the lowest useful power state
3462 at all times.  This could (and often does) mean that the device remains in the
3463 D0 state whenever the machine is running.  Or it could mean that the device is
3464 only in D0 when there are outstanding IRPs in its queues.  Or it could mean
3465 that the device is in D0 whenever the driver explicitly says that it has to be.
3466 
3467 Consequently, the Power Policy state machine has a bunch of states that relate
3468 only to managing the state of the device while the system is running, possibly
3469 allowing the device to "idle-out" to low power states while it isn't being
3470 heavily used.  Once that idle-out process has begun, there needs to be some
3471 way for the Framework I/O Package and the driver itself to tell the Power Policy
3472 engine that the device must, for some time at least, be in the D0 (high-power,
3473 working) state.  The problem is made much harder by the fact that the driver
3474 (or the Framework itself) probably has to stall some operation while the device
3475 is brought back into the D0 state.
3476 
3477 So we've created two operations, PowerReference and PowerDereference, which
3478 tell the Power Policy state machine when a device needs to be in the D0 state.
3479 The I/O Package uses these internally, and the driver may as well.  We want
3480 these operations to be as light-weight as possible, so that a driver never
3481 experiences meaningful degradation in performance simply because it chose to
3482 be a good electricity consumer and enabled idle-time power management.
3483 Fortunately, the Framework I/O package can significantly reduce the number of
3484 times that it needs to call these functions by only calling them when the
3485 queue state transitions from empty to non-empty or back again.  A caller within
3486 the driver itself will need to be aware that their usage can be somewhat
3487 expensive.
3488 
3489 Furthermore, these functions need to be callable at both PASSIVE_LEVEL and
3490 DISPATCH_LEVEL.  This really necessitates two versions, as a PASSIVE_LEVEL
3491 user within the driver probably would like us to block while the device is
3492 moved into D0, while a DISPATCH_LEVEL user (or the Framework I/O package) would
3493 prefer a much more asynchronous mode of use.
3494 
3495 Dealing with these multiple modes involves a fairly complex locking scheme. Here
3496 is a statement of algorithm.
3497 
3498 Locks:
3499 
3500 A)  Idle Transition Spinlock - DISPATCH_LEVEL
3501 B)  Device in D0 Notification Event - PASSIVE_LEVEL
3502 
3503 Device-wide variables:
3504 
3505   I) Power Reference Count - number of outstanding reasons to be in D0.
3506  II) Idle Timout -- value set by the driver which governs the idle timer
3507 III) Transitioning -- boolean indicating whether we're in the process of
3508      moving the device from Dx to D0.
3509 
3510 PowerDecrement:
3511 
3512 1)  Take Idle Transition lock.
3513 3)  Decrement of the device-wide power reference count.
3514 3)  If that's not zero, drop the lock and exit.
3515 4)  Set the driver's Idle Timer.
3516 5)  Drop the Idle Transition lock.
3517 
3518 PowerIncrement:
3519 
3520  1) Take Idle Transition lock.
3521  2) Increment of the device-wide power reference count.
3522  3) If that's 1, then we're transitioning out of idle.  Goto Step 6.
3523  4) If Transitioning == TRUE, we need to wait, Goto Step 13.
3524  5) Drop the Idle Transition lock.  Exit.
3525  6) Cancel the Idle Timer.  If that was unsuccessful, then the timer was not
3526     set, which means that the device has either moved out of D0 or it is moving
3527     out of D0.  Goto Step 8.
3528  7) Drop the Idle Transition lock.  Exit.
3529  8) The timer was not succefully cancelled.  This means that we have timed out
3530     in the past and we need to put the device back in D0.
3531     Set Transitioning = TRUE.
3532  9) Drop Idle Transition lock.
3533 10) Reset the D0 Notification Event.
3534 11) Send IoPresent event to the Power Policy state machine.
3535 12) If IRQL == DISPATCH_LEVEL goto Step 15.
3536 13) Wait for the D0 Notification Event.
3537 14) Exit.
3538 15) Note that I/O needs to be restarted later.
3539 16) Exit STATUS_PENDING.
3540 
3541 --*/
3542 WDF_DEVICE_POWER_POLICY_STATE
PowerPolStarting(__inout FxPkgPnp * This)3543 FxPkgPnp::PowerPolStarting(
3544     __inout FxPkgPnp* This
3545     )
3546 {
3547     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolStarting);
3548 
3549     This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.Start();
3550 
3551     This->PowerProcessEvent(PowerImplicitD0);
3552 
3553     //
3554     // Wait for the successful power up before starting any idle timers.  If
3555     // the power up fails, we will not send a power policy stop from the pnp
3556     // engine.
3557     //
3558     return WdfDevStatePwrPolNull;
3559 }
3560 
3561 WDF_DEVICE_POWER_POLICY_STATE
PowerPolStartingPoweredUp(__inout FxPkgPnp * This)3562 FxPkgPnp::PowerPolStartingPoweredUp(
3563     __inout FxPkgPnp* This
3564     )
3565 /*++
3566 
3567 Routine Description:
3568     The power state policy state machine has powered up. Tell the active/idle
3569     state machine to initialize.
3570 
3571     The device needs to be in D0 before the active/idle state machine registers
3572     with the power framework. Therefore, we wait until the power state machine
3573     has brought the device into D0 before we tell the active/idle state machine
3574     to start. Moving the device into D0 allows us to touch hardware if needed
3575     (for example, to determine the number of components in the device) before
3576     registering with the power framework.
3577 
3578 Arguments:
3579     This - instance of the state machine
3580 
3581 Return Value:
3582     WdfDevStatePwrPolNull
3583 
3584 --*/
3585 {
3586     NTSTATUS status;
3587     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolStartingPoweredUp);
3588 
3589     //
3590     // The decision regarding whether or not the power framework determines the
3591     // idle timeout is now "frozen" and cannot be changed unless the device is
3592     // stopped and restarted.
3593     //
3594     This->m_PowerPolicyMachine.m_Owner->
3595             m_IdleSettings.m_TimeoutMgmt.FreezeIdleTimeoutManagementStatus(
3596                                                 This->GetDriverGlobals()
3597                                                 );
3598 
3599     status = This->m_PowerPolicyMachine.m_Owner->
3600                         m_PoxInterface.InitializeComponents();
3601     if (FALSE == NT_SUCCESS(status)) {
3602         return WdfDevStatePwrPolStartingPoweredUpFailed;
3603     }
3604 
3605     return WdfDevStatePwrPolStartingSucceeded;
3606 }
3607 
3608 WDF_DEVICE_POWER_POLICY_STATE
PowerPolStartingPoweredUpFailed(__inout FxPkgPnp * This)3609 FxPkgPnp::PowerPolStartingPoweredUpFailed(
3610     __inout FxPkgPnp* This
3611     )
3612 /*++
3613 
3614 Routine Description:
3615     We failed to initialize the device's components. We have already started the
3616     power state machine, so ask it to run down before we tell the PNP state
3617     machine to fail device start.
3618 
3619 Arguments:
3620     This - instance of the state machine
3621 
3622 Return Value:
3623     WdfDevStatePwrPolNull
3624 
3625 --*/
3626 {
3627     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolStartingPoweredUpFailed);
3628 
3629     This->PowerProcessEvent(PowerImplicitD3);
3630 
3631     return WdfDevStatePwrPolNull;
3632 }
3633 
3634 WDF_DEVICE_POWER_POLICY_STATE
PowerPolStartingSucceeded(__inout FxPkgPnp * This)3635 FxPkgPnp::PowerPolStartingSucceeded(
3636     __inout FxPkgPnp* This
3637     )
3638 /*++
3639 
3640 Routine Description:
3641     The power policy state machine has successfully started.  Notify the pnp
3642     state machine that this has occurred and then tell the active/idle state
3643     machine to move to an active state.
3644 
3645 Arguments:
3646     This - instance of the state machine
3647 
3648 Return Value:
3649     WdfDevStatePwrPolStartingDecideS0Wake
3650 
3651   --*/
3652 {
3653     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolStartingSucceeded);
3654 
3655     This->PnpProcessEvent(PnpEventPwrPolStarted);
3656 
3657     return WdfDevStatePwrPolStartingDecideS0Wake;
3658 }
3659 
3660 WDF_DEVICE_POWER_POLICY_STATE
PowerPolStartingFailed(__inout FxPkgPnp * This)3661 FxPkgPnp::PowerPolStartingFailed(
3662     __inout FxPkgPnp* This
3663     )
3664 /*++
3665 
3666 Routine Description:
3667     Attempting to bring the device into the D0 state failed.  Report the status
3668     to pnp.
3669 
3670 Arguments:
3671     This - instance of the state machine
3672 
3673 Return Value
3674     WdfDevStatePwrPolNull
3675 
3676   --*/
3677 {
3678     KIRQL irql;
3679 
3680     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolStartingFailed);
3681 
3682     This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.Stop();
3683 
3684     //
3685     // We raise IRQL to dispatch level so that pnp is forced onto its own thread
3686     // to process the PwrPolStartFailed event.  If pnp is on the power thread when
3687     // it processes the event and it tries to delete the dedicated thread, it
3688     // will deadlock waiting for the thread its on to exit.
3689     //
3690     Mx::MxRaiseIrql(DISPATCH_LEVEL, &irql);
3691     This->PnpProcessEvent(PnpEventPwrPolStartFailed);
3692     Mx::MxLowerIrql(irql);
3693 
3694     return WdfDevStatePwrPolNull;
3695 }
3696 
3697 WDF_DEVICE_POWER_POLICY_STATE
PowerPolStartingDecideS0Wake(__inout FxPkgPnp * This)3698 FxPkgPnp::PowerPolStartingDecideS0Wake(
3699     __inout FxPkgPnp* This
3700     )
3701 {
3702     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolStartingDecideS0Wake);
3703 
3704     This->PowerPolicyChildrenCanPowerUp();
3705 
3706     //
3707     // Save idle state if it is dirty.  We check when deciding the S0 state
3708     // because any change in the S0 idle settings will go through this state.
3709     //
3710     This->SaveState(TRUE);
3711 
3712     //
3713     // If necessary update the idle timeout hint to the power framework
3714     //
3715     This->m_PowerPolicyMachine.m_Owner->m_PoxInterface.UpdateIdleTimeoutHint();
3716 
3717     if (This->m_PowerPolicyMachine.m_Owner->m_IdleSettings.Enabled) {
3718         if (This->m_PowerPolicyMachine.m_Owner->m_IdleSettings.WakeFromS0Capable) {
3719             //
3720             // We can idle out and wake from S0
3721             //
3722             return WdfDevStatePwrPolStartedWakeCapable;
3723         }
3724         else {
3725             //
3726             // We can idle out, but not wake from the idle state
3727             //
3728             return WdfDevStatePwrPolStartedIdleCapable;
3729         }
3730     }
3731 
3732     return WdfDevStatePwrPolStarted;
3733 }
3734 
3735 WDF_DEVICE_POWER_POLICY_STATE
PowerPolStartedIdleCapable(__inout FxPkgPnp * This)3736 FxPkgPnp::PowerPolStartedIdleCapable(
3737     __inout FxPkgPnp* This
3738     )
3739 {
3740     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolStartedIdleCapable);
3741 
3742     //
3743     // Enable the idle state machine.  This will release any threads who are
3744     // waiting for the device to return to D0.
3745     //
3746     This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.EnableTimer();
3747 
3748     return WdfDevStatePwrPolNull;
3749 }
3750 
3751 WDF_DEVICE_POWER_POLICY_STATE
PowerPolIdleCapableDeviceIdle(__inout FxPkgPnp * This)3752 FxPkgPnp::PowerPolIdleCapableDeviceIdle(
3753     __inout FxPkgPnp* This
3754     )
3755 /*++
3756 
3757 Routine Description:
3758     We are now idle. Tell the active/idle state machine to move us to an idle
3759     state.
3760 
3761 Arguments:
3762     This - instance of the state machine
3763 
3764 Return Value:
3765     WdfDevStatePwrPolNull
3766 
3767   --*/
3768 {
3769     BOOLEAN canPowerDown;
3770     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolIdleCapableDeviceIdle);
3771 
3772     canPowerDown = This->m_PowerPolicyMachine.m_Owner->
3773                         m_PoxInterface.DeclareComponentIdle();
3774 
3775     //
3776     // If we are using driver-managed idle timeout we can power down immediately
3777     // and so we jump to the next state (that initiates power down) immediately.
3778     // If we are using system-managed idle timeout, we wait in the current state
3779     // for device-power-not-required notification.
3780     //
3781     return (canPowerDown ?
3782                 WdfDevStatePwrPolTimerExpiredNoWake :
3783                 WdfDevStatePwrPolNull);
3784 }
3785 
3786 WDF_DEVICE_POWER_POLICY_STATE
PowerPolDeviceIdleReturnToActive(__inout FxPkgPnp * This)3787 FxPkgPnp::PowerPolDeviceIdleReturnToActive(
3788     __inout FxPkgPnp* This
3789     )
3790 /*++
3791 
3792 Routine Description:
3793     We are idle, but still in D0. We need to return to an active state.
3794 
3795 Arguments:
3796     This - instance of the state machine
3797 
3798 Return Value:
3799     WdfDevStatePwrPolNull
3800 
3801   --*/
3802 {
3803     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolDeviceIdleReturnToActive);
3804 
3805     This->m_PowerPolicyMachine.m_Owner->
3806             m_PoxInterface.RequestComponentActive();
3807 
3808     return WdfDevStatePwrPolStartedCancelTimer;
3809 }
3810 
3811 WDF_DEVICE_POWER_POLICY_STATE
PowerPolDeviceIdleSleeping(__inout FxPkgPnp * This)3812 FxPkgPnp::PowerPolDeviceIdleSleeping(
3813     __inout FxPkgPnp* This
3814     )
3815 /*++
3816 
3817 Routine Description:
3818     We are idle, but still in D0. System is going to a low power state.
3819 
3820 Arguments:
3821     This - instance of the state machine
3822 
3823 Return Value:
3824     WdfDevStatePwrPolNull
3825 
3826   --*/
3827 {
3828     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolDeviceIdleSleeping);
3829 
3830     //
3831     // Normally we'd make the component active when we get the device-power-
3832     // required notification. But we've not yet processed the device-power-not-
3833     // required notification, so we will not be processing the device-power-
3834     // required notification either. So let's activate the component before we
3835     // process the Sx IRP.
3836     //
3837     This->m_PowerPolicyMachine.m_Owner->
3838             m_PoxInterface.RequestComponentActive();
3839 
3840     return WdfDevStatePwrPolStartedIdleCapableCancelTimerForSleep;
3841 }
3842 
3843 WDF_DEVICE_POWER_POLICY_STATE
PowerPolDeviceIdleStopping(__inout FxPkgPnp * This)3844 FxPkgPnp::PowerPolDeviceIdleStopping(
3845     __inout FxPkgPnp* This
3846     )
3847 /*++
3848 
3849 Routine Description:
3850     We are idle, but still in D0. Power policy state machine is being stopped.
3851 
3852 Arguments:
3853     This - instance of the state machine
3854 
3855 Return Value:
3856     WdfDevStatePwrPolNull
3857 
3858   --*/
3859 {
3860     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolDeviceIdleStopping);
3861 
3862     //
3863     // Normally we'd make the component active when we get the device-power-
3864     // required notification. But we've not yet processed the device-power-not-
3865     // required notification, so we will not be processing the device-power-
3866     // required notification either. So let's activate the component before we
3867     // process the stop/remove request.
3868     //
3869     This->m_PowerPolicyMachine.m_Owner->
3870             m_PoxInterface.RequestComponentActive();
3871 
3872     return WdfDevStatePwrPolStoppingCancelTimer;
3873 }
3874 
3875 WDF_DEVICE_POWER_POLICY_STATE
PowerPolTimerExpiredNoWake(__inout FxPkgPnp * This)3876 FxPkgPnp::PowerPolTimerExpiredNoWake(
3877     __inout FxPkgPnp* This
3878     )
3879 {
3880     BOOLEAN poweredDown;
3881     NTSTATUS notifyPowerDownStatus;
3882 
3883     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolTimerExpiredNoWake);
3884 
3885     //
3886     // Notify the device power requirement state machine that we are about to
3887     // power down.
3888     //
3889     notifyPowerDownStatus = This->m_PowerPolicyMachine.m_Owner->
3890                               m_PoxInterface.NotifyDevicePowerDown();
3891     if (FALSE == NT_SUCCESS(notifyPowerDownStatus)) {
3892         //
3893         // We couldn't notify the device power requirement state machine that
3894         // we are about to power down, because the "device-power-required"
3895         // notification has already arrived. So we should not power down at this
3896         // time. Revert back to the started state.
3897         //
3898         return WdfDevStatePwrPolTimerExpiredNoWakeReturnToActive;
3899     }
3900 
3901     poweredDown = This->PowerPolicyCanIdlePowerDown(
3902         This->m_PowerPolicyMachine.m_Owner->m_IdleSettings.DxState
3903         );
3904 
3905     if (poweredDown == FALSE) {
3906         //
3907         // Upon failure, revert back to the started state.
3908         //
3909         return WdfDevStatePwrPolTimerExpiredNoWakeUndoPowerDown;
3910     }
3911 
3912     return WdfDevStatePwrPolNull;
3913 }
3914 
3915 WDF_DEVICE_POWER_POLICY_STATE
PowerPolTimerExpiredNoWakeCompletePowerDown(__inout FxPkgPnp * This)3916 FxPkgPnp::PowerPolTimerExpiredNoWakeCompletePowerDown(
3917     __inout FxPkgPnp* This
3918     )
3919 /*++
3920 
3921 Routine Description:
3922     The device idled out and we sent the Dx request. The power state machine has
3923     gone as far as stopping I/O is waiting to be notified to complete the Dx
3924     process.  Send the PowerCompleteDx event to move the device fully into Dx.
3925 
3926 Arguments:
3927     This - instance of the state machine
3928 
3929 Return Value:
3930     WdfDevStatePwrPolNull
3931 
3932   --*/
3933 {
3934     ASSERT_PWR_POL_STATE(This,
3935                          WdfDevStatePwrPolTimerExpiredNoWakeCompletePowerDown);
3936 
3937     This->PowerProcessEvent(PowerCompleteDx);
3938 
3939     return WdfDevStatePwrPolNull;
3940 }
3941 
3942 WDF_DEVICE_POWER_POLICY_STATE
PowerPolWaitingUnarmedQueryIdle(__inout FxPkgPnp * This)3943 FxPkgPnp::PowerPolWaitingUnarmedQueryIdle(
3944     __inout FxPkgPnp* This
3945     )
3946 /*++
3947 
3948 Routine Description:
3949     The device was in the WaitingUnarmed state and received a PwrPolIoPresent
3950     event.  Before committing the device to move back to D0, check to see if
3951     the device has returned to an idle state.  This can easily happen if the
3952     driver causes a power reference in D0Exit accidentally and the power
3953     reference is removed before exiting the function.
3954 
3955 Arguments:
3956     This - instance of the state machine
3957 
3958 Return Value:
3959     new state
3960 
3961   --*/
3962 {
3963     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolWaitingUnarmedQueryIdle);
3964 
3965     //
3966     // If QueryReturnToIdle returns TRUE, return to the waiting state
3967     //
3968     if (This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.QueryReturnToIdle()) {
3969         return WdfDevStatePwrPolWaitingUnarmed;
3970     }
3971     else {
3972         return WdfDevStatePwrPolS0NoWakePowerUp;
3973     }
3974 }
3975 
3976 WDF_DEVICE_POWER_POLICY_STATE
PowerPolS0NoWakePowerUp(__inout FxPkgPnp * This)3977 FxPkgPnp::PowerPolS0NoWakePowerUp(
3978     __inout FxPkgPnp* This
3979     )
3980 {
3981     NTSTATUS status;
3982 
3983     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolS0NoWakePowerUp);
3984 
3985     //
3986     // Attempt to get back to the D0 state
3987     //
3988     This->m_PowerPolicyMachine.m_Owner->
3989             m_PoxInterface.RequestComponentActive();
3990     status = This->PowerPolicySendDevicePowerRequest(PowerDeviceD0, Retry);
3991 
3992     if (!NT_SUCCESS(status)) {
3993         COVERAGE_TRAP();
3994         return WdfDevStatePwrPolDeviceD0PowerRequestFailed;
3995     }
3996 
3997     return WdfDevStatePwrPolNull;
3998 }
3999 
4000 WDF_DEVICE_POWER_POLICY_STATE
PowerPolS0NoWakeCompletePowerUp(__inout FxPkgPnp * This)4001 FxPkgPnp::PowerPolS0NoWakeCompletePowerUp(
4002     __inout FxPkgPnp* This
4003     )
4004 /*++
4005 
4006 Routine Description:
4007     The device was in a Dx unarmed for wake while in S0 and is now being brought
4008     into the  D0 state.  The device is currently in a partial D0 state (HW
4009     started), move it into the full D0 state by sending PowerCompleteD0 to the
4010     power state machine.
4011 
4012 Arguments:
4013     This - instance of the state machine
4014 
4015 Return Value:
4016     WdfDevStatePwrPolNull
4017 
4018   --*/
4019 {
4020     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolS0NoWakeCompletePowerUp);
4021 
4022     This->m_PowerPolicyMachine.m_Owner->
4023                 m_PoxInterface.DeviceIsPoweredOn();
4024 
4025     This->PowerProcessEvent(PowerCompleteD0);
4026 
4027     return WdfDevStatePwrPolNull;
4028 }
4029 
4030 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSystemSleepFromDeviceWaitingUnarmed(__inout FxPkgPnp * This)4031 FxPkgPnp::PowerPolSystemSleepFromDeviceWaitingUnarmed(
4032     __inout FxPkgPnp* This
4033     )
4034 {
4035     SYSTEM_POWER_STATE systemState;
4036 
4037     ASSERT_PWR_POL_STATE(
4038         This, WdfDevStatePwrPolSystemSleepFromDeviceWaitingUnarmed);
4039 
4040     systemState = This->PowerPolicyGetPendingSystemState();
4041 
4042     if (This->PowerPolicyIsWakeEnabled() &&
4043         This->PowerPolicyCanWakeFromSystemState(systemState)) {
4044         return WdfDevStatePwrPolSystemSleepNeedWake;
4045     }
4046     else {
4047         return WdfDevStatePwrPolSystemAsleepNoWake;
4048     }
4049 }
4050 
4051 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSystemSleepNeedWake(__inout FxPkgPnp * This)4052 FxPkgPnp::PowerPolSystemSleepNeedWake(
4053     __inout FxPkgPnp* This
4054     )
4055 {
4056     NTSTATUS status;
4057     BOOLEAN result;
4058 
4059     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolSystemSleepNeedWake);
4060 
4061     result = This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.DisableTimer();
4062     ASSERT(result);
4063     UNREFERENCED_PARAMETER(result);
4064 
4065     status = This->PowerPolicySendDevicePowerRequest(PowerDeviceD0, Retry);
4066 
4067     //
4068     // We are currently in Dx and not armed for wake.  While the current Dx
4069     // state may not be the same Dx state we would be for Sx, we can't get to
4070     // D0 to arm ourselves for Sx wake so just leave ourselves as is.
4071     //
4072     if (!NT_SUCCESS(status)) {
4073         DoTraceLevelMessage(
4074             This->GetDriverGlobals(), TRACE_LEVEL_WARNING, TRACINGPNP,
4075             "Failed to allocate D0 request to disarm from wake from S0 to allow "
4076             "arm for wake from Sx, %!STATUS!", status);
4077 
4078         COVERAGE_TRAP();
4079 
4080         //
4081         // If D0 IRP allocation fails, we don't treat that as an error. Instead,
4082         // we just let the device remain in Dx without arming it for
4083         // wake-from-Sx, even though the driver had enabled wake-from-Sx.
4084         //
4085         return WdfDevStatePwrPolSystemAsleepNoWake;
4086     }
4087 
4088     return WdfDevStatePwrPolNull;
4089 }
4090 
4091 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSystemSleepNeedWakeCompletePowerUp(__inout FxPkgPnp * This)4092 FxPkgPnp::PowerPolSystemSleepNeedWakeCompletePowerUp(
4093     __inout FxPkgPnp* This
4094     )
4095 /*++
4096 
4097 Routine Description:
4098     The machine is going into Sx while the device was in Dx.  We have started
4099     the D0 process.  The power state machine has moved the device into the HW
4100     working state and is waiting to be notified to complete the D0 process.
4101     Send the PowerCompleteD0 event to complete it.
4102 
4103 Arguments:
4104     This - instance of the state machine
4105 
4106 Return Value:
4107     WdfDevStatePwrPolNull
4108 
4109   --*/
4110 {
4111     ASSERT_PWR_POL_STATE(This,
4112                          WdfDevStatePwrPolSystemSleepNeedWakeCompletePowerUp);
4113 
4114     This->PowerProcessEvent(PowerCompleteD0);
4115 
4116     return WdfDevStatePwrPolNull;
4117 }
4118 
4119 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSystemSleepPowerRequestFailed(__inout FxPkgPnp * This)4120 FxPkgPnp::PowerPolSystemSleepPowerRequestFailed(
4121     __inout FxPkgPnp* This
4122     )
4123 /*++
4124 
4125 Routine Description:
4126     Power up failed in the power state machine.  Complete the pending system
4127     power irp with success (system ignores the results) even if the Dx irp
4128     failed.
4129 
4130 Arguments:
4131     This - instance of the state machine
4132 
4133 Return Value:
4134     new state WdfDevStatePwrPolDevicePowerRequestFailed
4135 
4136   --*/
4137 {
4138     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolSystemSleepPowerRequestFailed);
4139 
4140     This->PowerPolicyCompleteSystemPowerIrp();
4141 
4142     return WdfDevStatePwrPolDevicePowerRequestFailed;
4143 }
4144 
4145 WDF_DEVICE_POWER_POLICY_STATE
PowerPolCheckPowerPageable(__inout FxPkgPnp * This)4146 FxPkgPnp::PowerPolCheckPowerPageable(
4147     __inout FxPkgPnp* This
4148     )
4149 /*++
4150 
4151 Routine Description:
4152     Checks to see if the device should move down the power pagable wake path
4153     or the NP path.
4154 
4155 Arguments:
4156     This - instance of the state machine
4157 
4158 Return Value:
4159     new state
4160 
4161   --*/
4162 {
4163     ULONG flags;
4164     MxDeviceObject deviceObject;
4165 
4166     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolCheckPowerPageable);
4167 
4168     deviceObject.SetObject(This->m_Device->GetDeviceObject());
4169     flags = deviceObject.GetFlags();
4170 
4171     if (flags & DO_POWER_PAGABLE) {
4172         ASSERT((flags & DO_POWER_INRUSH) == 0);
4173 
4174         return WdfDevStatePwrPolSleepingWakeWakeArrived;
4175     }
4176     else {
4177         //
4178         // DO_POWER_INRUSH also gets us to this state, but since it is mutually
4179         // exclusive with DO_POWER_PAGABLE, we don't need to check for it
4180         //
4181         return WdfDevStatePwrPolSleepingWakeWakeArrivedNP;
4182     }
4183 }
4184 
4185 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSleepingWakeWakeArrived(__inout FxPkgPnp * This)4186 FxPkgPnp::PowerPolSleepingWakeWakeArrived(
4187     __inout FxPkgPnp* This
4188     )
4189 /*++
4190 
4191 Routine Description:
4192     The device is in partial Dx (I/O has stopped) and will now be armed for wake.
4193     Complete the going Dx transition by sending a PowerCompleteDx irp to the
4194 
4195 Arguments:
4196     This - instance of the state machine
4197 
4198 Return Value:
4199     new state
4200 
4201   --*/
4202 {
4203     NTSTATUS status;
4204     ULONG wakeReason;
4205 
4206     ASSERT_PWR_POL_STATE(
4207         This, WdfDevStatePwrPolSleepingWakeWakeArrived);
4208 
4209     ASSERT(This->PowerPolicyCanWakeFromSystemState(
4210                 This->PowerPolicyGetPendingSystemState()
4211                 ));
4212 
4213     wakeReason = This->PowerPolicyGetCurrentWakeReason();
4214 
4215     status = This->m_PowerPolicyMachine.m_Owner->m_DeviceArmWakeFromSx.Invoke(
4216         This->m_Device->GetHandle(),
4217         FLAG_TO_BOOL(wakeReason, FxPowerPolicySxWakeDeviceEnabledFlag),
4218         FLAG_TO_BOOL(wakeReason, FxPowerPolicySxWakeChildrenArmedFlag)
4219         );
4220 
4221     if (!NT_SUCCESS(status)) {
4222         DoTraceLevelMessage(
4223             This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
4224             "WDFDEVICE %p Failed to arm for wake from Sx, %!STATUS!",
4225             This->m_Device->GetHandle(), status);
4226 
4227         return WdfDevStatePwrPolSleepingWakeRevertArmWake;
4228     }
4229 
4230     //
4231     // If the PDO is the Power Policy owner, then enable wake at bus, otherwise
4232     // the power state machine will enable wake at bus.
4233     //
4234     if (This->m_Device->IsPdo()) {
4235         status = This->PowerEnableWakeAtBusOverload();
4236         if (!NT_SUCCESS(status)) {
4237             DoTraceLevelMessage(
4238                 This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
4239                 "WDFDEVICE %p Failed to Enable Wake at Bus, %!STATUS!",
4240                 This->m_Device->GetHandle(), status);
4241             return WdfDevStatePwrPolSleepingWakeRevertArmWake;
4242         }
4243     }
4244 
4245     This->PowerProcessEvent(PowerCompleteDx);
4246 
4247     return WdfDevStatePwrPolNull;
4248 }
4249 
4250 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSleepingWakeRevertArmWake(__inout FxPkgPnp * This)4251 FxPkgPnp::PowerPolSleepingWakeRevertArmWake(
4252     __inout FxPkgPnp* This
4253     )
4254 {
4255     ASSERT_PWR_POL_STATE(
4256         This, WdfDevStatePwrPolSleepingWakeRevertArmWake);
4257 
4258     DoTraceLevelMessage(
4259         This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
4260         "reverting arm for wake from Sx due to failure to allocate wait wake "
4261         "request or wait wake request completed immeidately.  Device will *NOT* "
4262         "be armed for wake from Sx");
4263 
4264     //
4265     // Enable calls should be matched with Disable calls even in the failure
4266     // cases. However, for the Enable wake at bus failure, we do not call the
4267     // disable wake at bus method as we try to keep the failure behavior
4268     // consistent with the Power State machine. Only the Device Disarm wake
4269     // callback will be invoked here.
4270     //
4271     This->PowerPolicyDisarmWakeFromSx();
4272 
4273     //
4274     // attempt to cancel ww
4275     //
4276     if (This->PowerPolicyCancelWaitWake() == FALSE &&
4277         This->m_PowerPolicyMachine.m_Owner->m_WakeCompletionEventDropped) {
4278         return WdfDevStatePwrPolSleepingNoWakeCompletePowerDown;
4279     }
4280 
4281     return WdfDevStatePwrPolNull;
4282 }
4283 
4284 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSystemAsleepWakeArmed(__inout FxPkgPnp * This)4285 FxPkgPnp::PowerPolSystemAsleepWakeArmed(
4286     __inout FxPkgPnp* This
4287     )
4288 {
4289     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolSystemAsleepWakeArmed);
4290     This->PowerPolicyCompleteSystemPowerIrp();
4291 
4292     return WdfDevStatePwrPolNull;
4293 }
4294 
4295 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSystemWakeDeviceWakeEnabled(__inout FxPkgPnp * This)4296 FxPkgPnp::PowerPolSystemWakeDeviceWakeEnabled(
4297     __inout FxPkgPnp* This
4298     )
4299 {
4300     ASSERT_PWR_POL_STATE(
4301         This, WdfDevStatePwrPolSystemWakeDeviceWakeEnabled);
4302 
4303     if (This->PowerPolicyCancelWaitWake() == FALSE &&
4304         This->m_PowerPolicyMachine.m_Owner->m_WakeCompletionEventDropped) {
4305         return WdfDevStatePwrPolSystemWakeDeviceWakeEnabledWakeCanceled;
4306     }
4307 
4308     return WdfDevStatePwrPolNull;
4309 }
4310 
4311 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSystemWakeDeviceWakeInterruptFired(__inout FxPkgPnp * This)4312 FxPkgPnp::PowerPolSystemWakeDeviceWakeInterruptFired(
4313     __inout FxPkgPnp* This
4314     )
4315 {
4316     ASSERT_PWR_POL_STATE(
4317         This, WdfDevStatePwrPolSystemWakeDeviceWakeInterruptFired);
4318 
4319     //
4320     // Make a note of the fact that system was woken by
4321     // a wake interrupt of this device
4322     //
4323     This->m_SystemWokenByWakeInterrupt = TRUE;
4324 
4325     if (This->PowerPolicyCancelWaitWake() == FALSE &&
4326         This->m_PowerPolicyMachine.m_Owner->m_WakeCompletionEventDropped) {
4327 
4328         return WdfDevStatePwrPolSystemWakeDeviceWakeTriggered;
4329     }
4330 
4331     return WdfDevStatePwrPolNull;
4332 }
4333 
4334 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSystemWakeDeviceWakeEnabledWakeCanceled(__inout FxPkgPnp * This)4335 FxPkgPnp::PowerPolSystemWakeDeviceWakeEnabledWakeCanceled(
4336     __inout FxPkgPnp* This
4337     )
4338 {
4339     NTSTATUS status;
4340 
4341     ASSERT_PWR_POL_STATE(
4342         This, WdfDevStatePwrPolSystemWakeDeviceWakeEnabledWakeCanceled);
4343 
4344     status = This->PowerPolicySendDevicePowerRequest(PowerDeviceD0, Retry);
4345 
4346     if (!NT_SUCCESS(status)) {
4347         COVERAGE_TRAP();
4348         return WdfDevStatePwrPolDeviceD0PowerRequestFailed;
4349     }
4350 
4351     return WdfDevStatePwrPolNull;
4352 }
4353 
4354 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSystemWakeDeviceWakeDisarm(__inout FxPkgPnp * This)4355 FxPkgPnp::PowerPolSystemWakeDeviceWakeDisarm(
4356     __inout FxPkgPnp* This
4357     )
4358 {
4359     ASSERT_PWR_POL_STATE(
4360         This, WdfDevStatePwrPolSystemWakeDeviceWakeDisarm);
4361 
4362     //
4363     // If the PDO is the Power Policy owner, then disable wake at bus, otherwise
4364     // the power state machine will disable wake at bus.
4365     //
4366     if (This->m_Device->IsPdo()) {
4367         This->PowerDisableWakeAtBusOverload();
4368     }
4369 
4370     This->PowerPolicyDisarmWakeFromSx();
4371 
4372     return WdfDevStatePwrPolSystemWakeDeviceWakeCompletePowerUp;
4373 }
4374 
4375 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSystemWakeDeviceWakeTriggeredS0(__inout FxPkgPnp * This)4376 FxPkgPnp::PowerPolSystemWakeDeviceWakeTriggeredS0(
4377     __inout FxPkgPnp* This
4378     )
4379 {
4380     NTSTATUS status;
4381 
4382     ASSERT_PWR_POL_STATE(
4383         This, WdfDevStatePwrPolSystemWakeDeviceWakeTriggeredS0);
4384 
4385     status = This->PowerPolicySendDevicePowerRequest(PowerDeviceD0, Retry);
4386 
4387     if (!NT_SUCCESS(status)) {
4388         COVERAGE_TRAP();
4389         return WdfDevStatePwrPolDeviceD0PowerRequestFailed;
4390     }
4391 
4392     return WdfDevStatePwrPolNull;
4393 }
4394 
4395 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSystemWakeDeviceWokeDisarm(__inout FxPkgPnp * This)4396 FxPkgPnp::PowerPolSystemWakeDeviceWokeDisarm(
4397     __inout FxPkgPnp* This
4398     )
4399 {
4400     ASSERT_PWR_POL_STATE(
4401         This, WdfDevStatePwrPolSystemWakeDeviceWokeDisarm);
4402 
4403     //
4404     // If the PDO is the Power Policy owner, then disable wake at bus, otherwise
4405     // the power state machine will enable wake at bus.
4406     //
4407     if (This->m_Device->IsPdo()) {
4408         This->PowerDisableWakeAtBusOverload();
4409     }
4410 
4411     This->m_PowerPolicyMachine.m_Owner->m_DeviceWakeFromSxTriggered.Invoke(
4412         This->m_Device->GetHandle()
4413         );
4414 
4415     This->PowerPolicyDisarmWakeFromSx();
4416 
4417     return WdfDevStatePwrPolSystemWakeDeviceWakeCompletePowerUp;
4418 }
4419 
4420 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSleepingWakeWakeArrivedNP(__inout FxPkgPnp * This)4421 FxPkgPnp::PowerPolSleepingWakeWakeArrivedNP(
4422     __inout FxPkgPnp* This
4423     )
4424 /*++
4425 
4426 Routine Description:
4427     The device is in partial Dx (I/O has stopped) and will now be armed for wake.
4428     Complete the going Dx transition by sending a PowerCompleteDx irp to the
4429     power state machine.
4430 
4431 Arguments:
4432     This - instance of the state machine
4433 
4434 Return Value:
4435     new state
4436 
4437   --*/
4438 {
4439     NTSTATUS status;
4440     ULONG wakeReason;
4441 
4442     ASSERT_PWR_POL_STATE(
4443         This, WdfDevStatePwrPolSleepingWakeWakeArrivedNP);
4444 
4445     ASSERT(This->PowerPolicyCanWakeFromSystemState(
4446                 This->PowerPolicyGetPendingSystemState()
4447                 ));
4448 
4449     wakeReason = This->PowerPolicyGetCurrentWakeReason();
4450 
4451     status = This->m_PowerPolicyMachine.m_Owner->m_DeviceArmWakeFromSx.Invoke(
4452         This->m_Device->GetHandle(),
4453         FLAG_TO_BOOL(wakeReason, FxPowerPolicySxWakeDeviceEnabledFlag),
4454         FLAG_TO_BOOL(wakeReason, FxPowerPolicySxWakeChildrenArmedFlag)
4455         );
4456 
4457     if (!NT_SUCCESS(status)) {
4458         DoTraceLevelMessage(
4459             This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
4460             "WDFDEVICE %p Failed to arm for wake from Sx, %!STATUS!",
4461             This->m_Device->GetHandle(), status);
4462 
4463         return WdfDevStatePwrPolSleepingWakeRevertArmWakeNP;
4464     }
4465 
4466     //
4467     // If the PDO is the Power Policy owner, then enable wake at bus, otherwise
4468     // the power state machine will enable wake at bus.
4469     //
4470     if (This->m_Device->IsPdo()) {
4471         status = This->PowerEnableWakeAtBusOverload();
4472         if (!NT_SUCCESS(status)) {
4473             DoTraceLevelMessage(
4474                 This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
4475                 "WDFDEVICE %p Failed to Enable Wake at Bus, %!STATUS!",
4476                 This->m_Device->GetHandle(), status);
4477             return WdfDevStatePwrPolSleepingWakeRevertArmWakeNP;
4478         }
4479     }
4480 
4481     This->PowerProcessEvent(PowerCompleteDx);
4482 
4483     return WdfDevStatePwrPolNull;
4484 }
4485 
4486 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSleepingWakeRevertArmWakeNP(__inout FxPkgPnp * This)4487 FxPkgPnp::PowerPolSleepingWakeRevertArmWakeNP(
4488     __inout FxPkgPnp* This
4489     )
4490 {
4491     ASSERT_PWR_POL_STATE(
4492         This, WdfDevStatePwrPolSleepingWakeRevertArmWakeNP);
4493 
4494     DoTraceLevelMessage(
4495         This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
4496         "reverting arm for wake from Sx due to failure to allocate wait wake "
4497         "request or wait wake request completed immeidately.  Device will *NOT* "
4498         "be armed for wake from Sx");
4499 
4500     //
4501     // Enable calls should be matched with Disable calls even in the failure
4502     // cases. However, for the Enable wake at bus failure, we do not call the
4503     // disable wake at bus method as we try to keep the failure behavior
4504     // consistent with the Power State machine. Only the Device Disarm wake
4505     // callback will be invoked here.
4506     //
4507     This->PowerPolicyDisarmWakeFromSx();
4508 
4509     //
4510     // attempt to cancel ww
4511     //
4512     if (This->PowerPolicyCancelWaitWake() == FALSE &&
4513         This->m_PowerPolicyMachine.m_Owner->m_WakeCompletionEventDropped) {
4514         return WdfDevStatePwrPolSleepingNoWakeCompletePowerDown;
4515     }
4516 
4517     return WdfDevStatePwrPolNull;
4518 }
4519 
4520 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSleepingWakePowerDownFailed(__inout FxPkgPnp * This)4521 FxPkgPnp::PowerPolSleepingWakePowerDownFailed(
4522     __inout FxPkgPnp* This
4523     )
4524 /*++
4525 
4526 Routine Description:
4527     Power down failed in the power state machine.  Cancel the wait wake irp
4528     that was just sent down and revert the arming before moving to the failed
4529     state.
4530 
4531 Arguments:
4532     This - instance of the state machine.
4533 
4534 Return Value:
4535     new state
4536 
4537   --*/
4538 {
4539     ASSERT_PWR_POL_STATE(
4540         This, WdfDevStatePwrPolSleepingWakePowerDownFailed);
4541 
4542     if (This->PowerPolicyCancelWaitWake() == FALSE &&
4543         This->m_PowerPolicyMachine.m_Owner->m_WakeCompletionEventDropped) {
4544         return WdfDevStatePwrPolSleepingWakePowerDownFailedWakeCanceled;
4545     }
4546 
4547     return WdfDevStatePwrPolNull;
4548 }
4549 
4550 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSleepingWakePowerDownFailedWakeCanceled(__inout FxPkgPnp * This)4551 FxPkgPnp::PowerPolSleepingWakePowerDownFailedWakeCanceled(
4552     __inout FxPkgPnp* This
4553     )
4554 /*++
4555 
4556 Routine Description:
4557     Wait wake irp has been cancelled.  Complete the Sx irp and goto the failed
4558     state.
4559 
4560 Arguments:
4561     This - instance of the state machine
4562 
4563 Return Value:
4564     new state
4565 
4566   --*/
4567 {
4568     ASSERT_PWR_POL_STATE(
4569         This, WdfDevStatePwrPolSleepingWakePowerDownFailedWakeCanceled);
4570 
4571     This->PowerPolicyCompleteSystemPowerIrp();
4572 
4573     return WdfDevStatePwrPolDevicePowerRequestFailed;
4574 }
4575 
4576 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSystemAsleepWakeArmedNP(__inout FxPkgPnp * This)4577 FxPkgPnp::PowerPolSystemAsleepWakeArmedNP(
4578     __inout FxPkgPnp* This
4579     )
4580 {
4581     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolSystemAsleepWakeArmedNP);
4582 
4583     This->PowerPolicyCompleteSystemPowerIrp();
4584 
4585     return WdfDevStatePwrPolNull;
4586 }
4587 
4588 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSystemWakeDeviceWakeEnabledNP(__inout FxPkgPnp * This)4589 FxPkgPnp::PowerPolSystemWakeDeviceWakeEnabledNP(
4590     __inout FxPkgPnp* This
4591     )
4592 {
4593     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolSystemWakeDeviceWakeEnabledNP);
4594 
4595     if (This->PowerPolicyCancelWaitWake() == FALSE &&
4596         This->m_PowerPolicyMachine.m_Owner->m_WakeCompletionEventDropped) {
4597         return WdfDevStatePwrPolSystemWakeDeviceWakeEnabledWakeCanceledNP;
4598     }
4599 
4600     return WdfDevStatePwrPolNull;
4601 }
4602 
4603 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSystemWakeDeviceWakeInterruptFiredNP(__inout FxPkgPnp * This)4604 FxPkgPnp::PowerPolSystemWakeDeviceWakeInterruptFiredNP(
4605     __inout FxPkgPnp* This
4606     )
4607 {
4608     ASSERT_PWR_POL_STATE(
4609         This, WdfDevStatePwrPolSystemWakeDeviceWakeInterruptFiredNP);
4610 
4611     //
4612     // Make a notee of the fact that system was woken by
4613     // a wake interrupt of this device
4614     //
4615     This->m_SystemWokenByWakeInterrupt = TRUE;
4616 
4617     if (This->PowerPolicyCancelWaitWake() == FALSE &&
4618         This->m_PowerPolicyMachine.m_Owner->m_WakeCompletionEventDropped) {
4619         return WdfDevStatePwrPolSystemWakeDeviceWakeTriggeredNP;
4620     }
4621 
4622     return WdfDevStatePwrPolNull;
4623 }
4624 
4625 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSystemWakeDeviceWakeEnabledWakeCanceledNP(__inout FxPkgPnp * This)4626 FxPkgPnp::PowerPolSystemWakeDeviceWakeEnabledWakeCanceledNP(
4627     __inout FxPkgPnp* This
4628     )
4629 {
4630     NTSTATUS status;
4631 
4632     ASSERT_PWR_POL_STATE(
4633         This, WdfDevStatePwrPolSystemWakeDeviceWakeEnabledWakeCanceledNP);
4634 
4635     status = This->PowerPolicySendDevicePowerRequest(PowerDeviceD0, Retry);
4636 
4637     if (!NT_SUCCESS(status)) {
4638         COVERAGE_TRAP();
4639         return WdfDevStatePwrPolDeviceD0PowerRequestFailed;
4640     }
4641 
4642     return WdfDevStatePwrPolNull;
4643 }
4644 
4645 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSystemWakeDeviceWakeDisarmNP(__inout FxPkgPnp * This)4646 FxPkgPnp::PowerPolSystemWakeDeviceWakeDisarmNP(
4647     __inout FxPkgPnp* This
4648     )
4649 {
4650     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolSystemWakeDeviceWakeDisarmNP);
4651 
4652     //
4653     // If the PDO is the Power Policy owner, then disable wake at bus, otherwise
4654     // the power state machine will disable wake at bus.
4655     //
4656     if (This->m_Device->IsPdo()) {
4657         This->PowerDisableWakeAtBusOverload();
4658     }
4659 
4660     This->PowerPolicyDisarmWakeFromSx();
4661 
4662     return WdfDevStatePwrPolSystemWakeDeviceWakeCompletePowerUp;
4663 }
4664 
4665 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSystemWakeDeviceWakeTriggeredS0NP(__inout FxPkgPnp * This)4666 FxPkgPnp::PowerPolSystemWakeDeviceWakeTriggeredS0NP(
4667     __inout FxPkgPnp* This
4668     )
4669 {
4670     NTSTATUS status;
4671 
4672     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolSystemWakeDeviceWakeTriggeredS0NP);
4673 
4674     status = This->PowerPolicySendDevicePowerRequest(PowerDeviceD0, Retry);
4675 
4676     if (!NT_SUCCESS(status)) {
4677         COVERAGE_TRAP();
4678         return WdfDevStatePwrPolDeviceD0PowerRequestFailed;
4679     }
4680 
4681     return WdfDevStatePwrPolNull;
4682 }
4683 
4684 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSystemWakeDeviceWokeDisarmNP(__inout FxPkgPnp * This)4685 FxPkgPnp::PowerPolSystemWakeDeviceWokeDisarmNP(
4686     __inout FxPkgPnp* This
4687     )
4688 {
4689     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolSystemWakeDeviceWokeDisarmNP);
4690 
4691     //
4692     // If the PDO is the Power Policy owner, then disable wake at bus, otherwise
4693     // the power state machine will disable wake at bus.
4694     //
4695     if (This->m_Device->IsPdo()) {
4696         This->PowerDisableWakeAtBusOverload();
4697     }
4698 
4699     This->m_PowerPolicyMachine.m_Owner->m_DeviceWakeFromSxTriggered.Invoke(
4700         This->m_Device->GetHandle()
4701         );
4702 
4703     This->PowerPolicyDisarmWakeFromSx();
4704 
4705     return WdfDevStatePwrPolSystemWakeDeviceWakeCompletePowerUp;
4706 }
4707 
4708 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSystemWakeDeviceWakeCompletePowerUp(__inout FxPkgPnp * This)4709 FxPkgPnp::PowerPolSystemWakeDeviceWakeCompletePowerUp(
4710     __inout FxPkgPnp* This
4711     )
4712 /*++
4713 
4714 Routine Description:
4715     The system went into Sx and the device was armed for wake.  The system has
4716     now returned to S0, the device has started the D0 transition, and the device
4717     has been disarmed for wake.  We must now complete the D0 transition by sending
4718     PowerCompleteD0 to the power state machine.
4719 
4720 Arguments:
4721     This - instance of the state machine
4722 
4723 Return Value:
4724     WdfDevStatePwrPolNull
4725 
4726   --*/
4727 {
4728     ASSERT_PWR_POL_STATE(This,
4729                          WdfDevStatePwrPolSystemWakeDeviceWakeCompletePowerUp);
4730 
4731     //
4732     // Simulate a device-power-required notification from the power framework.
4733     // An S0-IRP is essentially equivalent to a device-power-required
4734     // notification.
4735     //
4736     This->m_PowerPolicyMachine.m_Owner->
4737         m_PoxInterface.SimulateDevicePowerRequired();
4738 
4739     //
4740     // Notify the device-power-requirement state machine that we are powered on
4741     //
4742     This->m_PowerPolicyMachine.m_Owner->
4743                 m_PoxInterface.DeviceIsPoweredOn();
4744 
4745     This->PowerProcessEvent(PowerCompleteD0);
4746 
4747     return WdfDevStatePwrPolNull;
4748 }
4749 
4750 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSleeping(__inout FxPkgPnp * This)4751 FxPkgPnp::PowerPolSleeping(
4752     __inout FxPkgPnp* This
4753     )
4754 /*++
4755 
4756 Routine Description:
4757     The machine is going into Sx.  Send a Dx irp to the stack.  The "x" depends
4758     on if the target system state is one which we can wake the system and
4759     the device is enabled to wake from Sx.
4760 
4761 Arguments:
4762     This - instance of the state machine
4763 
4764 Return Value:
4765     new state
4766 
4767   --*/
4768 {
4769     NTSTATUS notifyPowerDownStatus;
4770     SYSTEM_POWER_STATE systemState;
4771 
4772     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolSleeping);
4773 
4774     //
4775     // If the bus/PDO is not in the hibernate path, then verify that all the
4776     // children have powered down by now.
4777     //
4778     if (This->GetUsageCount(WdfSpecialFileHibernation) == 0 &&
4779         This->m_PowerPolicyMachine.m_Owner->m_ChildrenPoweredOnCount > 0) {
4780         DoTraceLevelMessage(
4781             This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
4782             "WDFDEVICE %p powering down before child devices have powered down. "
4783             "This usually indicates a faulty child device that completed the Sx "
4784             "irp before sending the Dx irp",
4785             This->m_Device->GetHandle());
4786 
4787         FxVerifierBreakOnDeviceStateError(
4788             This->m_Device->GetDriverGlobals());
4789     }
4790 
4791     //
4792     // Simulate a device-power-not-required notification from the power
4793     // framework. An Sx-IRP is essentially equivalent to a device-power-not-
4794     // required notification.
4795     //
4796     This->m_PowerPolicyMachine.m_Owner->
4797         m_PoxInterface.SimulateDevicePowerNotRequired();
4798 
4799     //
4800     // Notify the device-power-requirement state machine that we are about to
4801     // power down
4802     //
4803     notifyPowerDownStatus = This->m_PowerPolicyMachine.m_Owner->
4804                               m_PoxInterface.NotifyDevicePowerDown();
4805 
4806     //
4807     // We simulated a device-power-not-required notification before we notified
4808     // the device-power-requirement state machine that we are powering down.
4809     // Therefore, our notification should have succeeded.
4810     //
4811     ASSERT(NT_SUCCESS(notifyPowerDownStatus));
4812     UNREFERENCED_PARAMETER(notifyPowerDownStatus);
4813 
4814     systemState = This->PowerPolicyGetPendingSystemState();
4815 
4816     if (This->PowerPolicyIsWakeEnabled() &&
4817         This->PowerPolicyCanWakeFromSystemState(systemState)) {
4818         return WdfDevStatePwrPolSleepingWakePowerDown;
4819     }
4820     else {
4821         return WdfDevStatePwrPolSleepingNoWakePowerDown;
4822     }
4823 }
4824 
4825 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSleepingNoWakePowerDown(__inout FxPkgPnp * This)4826 FxPkgPnp::PowerPolSleepingNoWakePowerDown(
4827     __inout FxPkgPnp* This
4828     )
4829 /*++
4830 
4831 Routine Description:
4832     Machine is going into Sx and the device is not enabled to wake from Sx.
4833     Request a D3 irp to put the device into a low power state.
4834 
4835 Arguments:
4836     This - instance of the state machine
4837 
4838 Return Value:
4839     new state
4840 
4841   --*/
4842 {
4843     NTSTATUS status;
4844     DEVICE_POWER_STATE dxState;
4845 
4846     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolSleepingNoWakePowerDown);
4847 
4848     dxState = (DEVICE_POWER_STATE)
4849         This->m_PowerPolicyMachine.m_Owner->m_IdealDxStateForSx;
4850 
4851     if (dxState != PowerDeviceD3) {
4852         DEVICE_POWER_STATE dxMappedState;
4853 
4854         //
4855         // Get the lightest Dx state for this Sx state as reported by the
4856         // device capabilities of the stack.
4857         //
4858         dxMappedState = _GetPowerCapState(
4859             This->PowerPolicyGetPendingSystemState(),
4860             This->m_PowerPolicyMachine.m_Owner->m_SystemToDeviceStateMap
4861             );
4862 
4863         //
4864         // If the ideal desired state is lighter than what the S->D mapping says
4865         // is the lightest supported D state, use the mapping value instead.
4866         //
4867         if (dxState < dxMappedState) {
4868             dxState = dxMappedState;
4869         }
4870     }
4871 
4872     ASSERT(dxState >= PowerDeviceD1 && dxState <= PowerDeviceD3);
4873 
4874     status = This->PowerPolicyPowerDownForSx(dxState, Retry);
4875 
4876     if (!NT_SUCCESS(status)) {
4877         COVERAGE_TRAP();
4878         return WdfDevStatePwrPolSleepingNoWakeDxRequestFailed;
4879     }
4880 
4881     return WdfDevStatePwrPolNull;
4882 }
4883 
4884 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSleepingNoWakeCompletePowerDown(__inout FxPkgPnp * This)4885 FxPkgPnp::PowerPolSleepingNoWakeCompletePowerDown(
4886     __inout FxPkgPnp* This
4887     )
4888 /*++
4889 
4890 Routine Description:
4891     The system has moved into Sx and the device is not armed for wake.  The
4892     device in partial Dx (I/O has stopped), transition the device into full
4893     Dx by sending the PowerCompleteDx event to the power state machine.
4894 
4895 Arguments:
4896     This - instance of the state machine
4897 
4898 Return Value:
4899     WdfDevStatePwrPolNull
4900 
4901   --*/
4902 {
4903     ASSERT_PWR_POL_STATE(This,
4904                          WdfDevStatePwrPolSleepingNoWakeCompletePowerDown);
4905 
4906     This->PowerProcessEvent(PowerCompleteDx);
4907 
4908     return WdfDevStatePwrPolNull;
4909 }
4910 
4911 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSleepingNoWakeDxRequestFailed(__inout FxPkgPnp * This)4912 FxPkgPnp::PowerPolSleepingNoWakeDxRequestFailed(
4913     __inout FxPkgPnp* This
4914     )
4915 {
4916     COVERAGE_TRAP();
4917 
4918     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolSleepingNoWakeDxRequestFailed);
4919 
4920     This->SetInternalFailure();
4921     This->PowerPolicyCompleteSystemPowerIrp();
4922 
4923     if (FALSE == This->m_ReleaseHardwareAfterDescendantsOnFailure) {
4924         This->PnpProcessEvent(PnpEventPowerDownFailed);
4925     }
4926 
4927     return WdfDevStatePwrPolDevicePowerRequestFailed;
4928 }
4929 
4930 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSleepingWakePowerDown(__inout FxPkgPnp * This)4931 FxPkgPnp::PowerPolSleepingWakePowerDown(
4932     __inout FxPkgPnp* This
4933     )
4934 /*++
4935 
4936 Routine Description:
4937     The system is going into Sx and the device is set to arm itself for wake from
4938     Sx. Start the power down process by requesting the Dx irp to stop I/O in
4939     the power state machine.
4940 
4941 Arguments:
4942     This - instance of the state machine
4943 
4944 Return Value:
4945     new state
4946 
4947   --*/
4948 {
4949     NTSTATUS status;
4950 
4951     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolSleepingWakePowerDown);
4952 
4953     status = This->PowerPolicyPowerDownForSx(
4954         This->m_PowerPolicyMachine.m_Owner->m_WakeSettings.DxState, NoRetry
4955         );
4956 
4957     if (!NT_SUCCESS(status)) {
4958         COVERAGE_TRAP();
4959         return WdfDevStatePwrPolSleepingNoWakePowerDown;
4960     }
4961 
4962     return WdfDevStatePwrPolNull;
4963 }
4964 
4965 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSleepingSendWake(__inout FxPkgPnp * This)4966 FxPkgPnp::PowerPolSleepingSendWake(
4967     __inout FxPkgPnp* This
4968     )
4969 /*++
4970 
4971 Routine Description:
4972     Machine is moving into an Sx state and the device is in a partial Dx (I/O
4973     stopped) state.  Send a wait wake request so that the device can be armed
4974     for wake from Sx.
4975 
4976 Arguments:
4977     This - instance of the state machine
4978 
4979 Return Value:
4980     new state
4981 
4982   --*/
4983 {
4984     SYSTEM_POWER_STATE systemState;
4985     NTSTATUS status;
4986 
4987     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolSleepingSendWake);
4988 
4989     //
4990     // We are in a wake-enabled path, keep wake interrupts connected.
4991     //
4992     This->m_WakeInterruptsKeepConnected = TRUE;
4993 
4994     //
4995     // We use the deepest possible Sx state instead of the current Sx state so
4996     // that we can handle the FastS4 case where PowerPolicyGetPendingSystemState
4997     // would return, but we could possible goto S4.  By using the deepest
4998     // possible state, we can arm for any possible Sx state that we are capable
4999     // of waking from.
5000     //
5001     systemState = This->PowerPolicyGetDeviceDeepestSystemWakeState();
5002 
5003     status = This->PowerPolicySendWaitWakeRequest(systemState);
5004 
5005     if (!NT_SUCCESS(status)) {
5006         DoTraceLevelMessage(
5007             This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
5008             "Attempting to send wait wake request for EvtDeviceArmWakeFromSx() "
5009             "failed, %!STATUS!", status);
5010 
5011         COVERAGE_TRAP();
5012 
5013         return WdfDevStatePwrPolSleepingNoWakeCompletePowerDown;
5014     }
5015 
5016     return WdfDevStatePwrPolNull;
5017 }
5018 
5019 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSystemAsleepNoWake(__inout FxPkgPnp * This)5020 FxPkgPnp::PowerPolSystemAsleepNoWake(
5021     __inout FxPkgPnp* This
5022     )
5023 {
5024     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolSystemAsleepNoWake);
5025 
5026     This->PowerPolicyCompleteSystemPowerIrp();
5027 
5028     return WdfDevStatePwrPolNull;
5029 }
5030 
5031 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSystemWakeDeviceWakeDisabled(__inout FxPkgPnp * This)5032 FxPkgPnp::PowerPolSystemWakeDeviceWakeDisabled(
5033     __inout FxPkgPnp* This
5034     )
5035 /*++
5036 
5037 Routine Description:
5038     The machine is moving from Sx->S0 and the device was in Dx and not armed for
5039     wake from Sx.  Determine if the device should remain in Dx after the machine
5040     has moved into S0.
5041 
5042 Arguments:
5043     This - instance of the state machine
5044 
5045 Return Value:
5046     new state
5047 
5048   --*/
5049 {
5050     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolSystemWakeDeviceWakeDisabled);
5051 
5052     //
5053     // We do not attempt to let the device remain in Dx if we are using system-
5054     // managed idle timeout. This is because an S0 IRP is equivalent to a
5055     // device-power-required notification from the power framework. In response
5056     // to it, we need to power up the device and notify the power framework that
5057     // the device is powered on.
5058     //
5059     if ((This->m_PowerPolicyMachine.m_Owner->
5060           m_IdleSettings.m_TimeoutMgmt.UsingSystemManagedIdleTimeout() == FALSE)
5061             &&
5062         (This->m_PowerPolicyMachine.m_Owner->m_IdleSettings.Enabled)
5063             &&
5064         (This->m_PowerPolicyMachine.m_Owner->
5065           m_IdleSettings.WakeFromS0Capable == FALSE)
5066             &&
5067         (This->m_PowerPolicyMachine.m_Owner->
5068           m_IdleSettings.PowerUpIdleDeviceOnSystemWake == FALSE)) {
5069 
5070         return WdfDevStatePwrPolSystemWakeQueryIdle;
5071     }
5072     else {
5073         return WdfDevStatePwrPolSystemWakeDeviceToD0;
5074     }
5075 }
5076 
5077 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSystemWakeDeviceToD0(__inout FxPkgPnp * This)5078 FxPkgPnp::PowerPolSystemWakeDeviceToD0(
5079     __inout FxPkgPnp* This
5080     )
5081 {
5082     NTSTATUS status;
5083 
5084     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolSystemWakeDeviceToD0);
5085 
5086     status = This->PowerPolicySendDevicePowerRequest(PowerDeviceD0, Retry);
5087     if (!NT_SUCCESS(status)) {
5088         COVERAGE_TRAP();
5089         return WdfDevStatePwrPolDeviceD0PowerRequestFailed;
5090     }
5091 
5092     return WdfDevStatePwrPolNull;
5093 }
5094 
5095 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSystemWakeDeviceToD0CompletePowerUp(__inout FxPkgPnp * This)5096 FxPkgPnp::PowerPolSystemWakeDeviceToD0CompletePowerUp(
5097     __inout FxPkgPnp* This
5098     )
5099 /*++
5100 
5101 Routine Description:
5102     The machine was in Sx and the device was not armed for wake from Sx.  The
5103     machine is moving back into S0 and the device is in partial D0 (HW has
5104     started).  Move the device into full D0 by sending the PowerCompleteD0
5105     event to the power state machine.
5106 
5107 Arguments:
5108     This - instance of the state machine
5109 
5110 Return Value:
5111     WdfDevStatePwrPolNull
5112 
5113   --*/
5114 {
5115     ASSERT_PWR_POL_STATE(
5116         This, WdfDevStatePwrPolSystemWakeDeviceToD0CompletePowerUp);
5117 
5118     //
5119     // Simulate a device-power-not-required notification from the power
5120     // framework. An S0-IRP is essentially equivalent to a device-power-required
5121     // notification.
5122     //
5123     This->m_PowerPolicyMachine.m_Owner->
5124         m_PoxInterface.SimulateDevicePowerRequired();
5125 
5126     //
5127     // Notify the device-power-requirement state machine that we are powered on
5128     //
5129     This->m_PowerPolicyMachine.m_Owner->
5130                 m_PoxInterface.DeviceIsPoweredOn();
5131 
5132     This->PowerProcessEvent(PowerCompleteD0);
5133 
5134     return WdfDevStatePwrPolNull;
5135 }
5136 
5137 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSystemWakeQueryIdle(__inout FxPkgPnp * This)5138 FxPkgPnp::PowerPolSystemWakeQueryIdle(
5139     __inout FxPkgPnp* This
5140     )
5141 {
5142     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolSystemWakeQueryIdle);
5143 
5144     //
5145     // This state can be reached only if we are using driver-managed idle
5146     // timeout.
5147     //
5148     ASSERT(
5149       This->m_PowerPolicyMachine.m_Owner->
5150           m_IdleSettings.m_TimeoutMgmt.UsingSystemManagedIdleTimeout() == FALSE
5151       );
5152 
5153     if (This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.QueryReturnToIdle()) {
5154         return WdfDevStatePwrPolWaitingUnarmed;
5155     }
5156     else {
5157         return WdfDevStatePwrPolSystemWakeDeviceToD0;
5158     }
5159 }
5160 
5161 
5162 WDF_DEVICE_POWER_POLICY_STATE
PowerPolStartedWakeCapable(__inout FxPkgPnp * This)5163 FxPkgPnp::PowerPolStartedWakeCapable(
5164     __inout FxPkgPnp* This
5165     )
5166 {
5167     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolStartedWakeCapable);
5168 
5169     //
5170     // Enable the idle state machine.  This will release any threads who are
5171     // waiting for the device to return to D0.
5172     //
5173     This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.EnableTimer();
5174 
5175     return WdfDevStatePwrPolNull;
5176 }
5177 
5178 WDF_DEVICE_POWER_POLICY_STATE
PowerPolWakeCapableDeviceIdle(__inout FxPkgPnp * This)5179 FxPkgPnp::PowerPolWakeCapableDeviceIdle(
5180     __inout FxPkgPnp* This
5181     )
5182 /*++
5183 
5184 Routine Description:
5185     We are now idle. Tell the active/idle state machine to move us to an idle
5186     state.
5187 
5188 Arguments:
5189     This - instance of the state machine
5190 
5191 Return Value:
5192     WdfDevStatePwrPolNull
5193 
5194   --*/
5195 {
5196     BOOLEAN canPowerDown;
5197 
5198     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolWakeCapableDeviceIdle);
5199 
5200     canPowerDown = This->m_PowerPolicyMachine.m_Owner->
5201                             m_PoxInterface.DeclareComponentIdle();
5202 
5203     //
5204     // If we are using driver-managed idle timeout we can power down immediately
5205     // and so we jump to the next state (that initiates power down) immediately.
5206     // If we are using system-managed idle timeout, we wait in the current state
5207     // for device-power-not-required notification.
5208     //
5209     return (canPowerDown ?
5210                 WdfDevStatePwrPolTimerExpiredDecideUsbSS :
5211                 WdfDevStatePwrPolNull);
5212 }
5213 
5214 WDF_DEVICE_POWER_POLICY_STATE
PowerPolTimerExpiredDecideUsbSS(__inout FxPkgPnp * This)5215 FxPkgPnp::PowerPolTimerExpiredDecideUsbSS(
5216     __inout FxPkgPnp* This
5217     )
5218 /*++
5219 
5220 Routine Description:
5221     Decides how to handle the idle timer firing.  If the device is capable of
5222     USB selective suspend, it will move the machine into that path.  Otherwise,
5223     the machine will be moved into the normal arm for wake while in D0 path.
5224 
5225 Arguments:
5226     This - instance of the state machine
5227 
5228 Return Value:
5229     WdfDevStatePwrPolTimerExpiredWakeCapableUsbSS
5230     or
5231     WdfDevStatePwrPolTimerExpiredWakeCapable
5232 
5233   --*/
5234 {
5235     NTSTATUS notifyPowerDownStatus;
5236 
5237     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolTimerExpiredDecideUsbSS);
5238 
5239     //
5240     // Notify the device power requirement state machine that we are about to
5241     // power down.
5242     //
5243     notifyPowerDownStatus = This->m_PowerPolicyMachine.m_Owner->
5244                               m_PoxInterface.NotifyDevicePowerDown();
5245     if (FALSE == NT_SUCCESS(notifyPowerDownStatus)) {
5246         //
5247         // We couldn't notify the device power requirement state machine that
5248         // we are about to power down, because the "device-power-required"
5249         // notification has already arrived. So we should not power down at this
5250         // time. Revert back to the started state.
5251         //
5252         return WdfDevStatePwrPolDeviceIdleReturnToActive;
5253     }
5254 
5255     if (This->m_PowerPolicyMachine.m_Owner->m_IdleSettings.UsbSSCapable) {
5256         return WdfDevStatePwrPolTimerExpiredWakeCapableUsbSS;
5257     }
5258     else {
5259         return WdfDevStatePwrPolTimerExpiredWakeCapablePowerDown;
5260     }
5261 }
5262 
5263 WDF_DEVICE_POWER_POLICY_STATE
PowerPolTimerExpiredWakeCapablePowerDown(__inout FxPkgPnp * This)5264 FxPkgPnp::PowerPolTimerExpiredWakeCapablePowerDown(
5265     __inout FxPkgPnp* This
5266     )
5267 /*++
5268 
5269 Routine Description:
5270     The device is enabled to be armed for wake from S0.  The device just idled
5271     out and is now about to transition into this state. The first step is to
5272     move into a partial Dx state (I/O stopped), send the wake request, arm the
5273     device, and then move into full Dx.  This function starts the transition
5274     by requesting a Dx irp.
5275 
5276 Arguments:
5277     This - instance of the state machine
5278 
5279 Return Value:
5280     new state
5281 
5282   --*/
5283 
5284 {
5285     BOOLEAN poweredDown;
5286 
5287     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolTimerExpiredWakeCapablePowerDown);
5288 
5289     poweredDown = This->PowerPolicyCanIdlePowerDown(
5290         This->m_PowerPolicyMachine.m_Owner->m_IdleSettings.DxState
5291         );
5292 
5293     if (poweredDown == FALSE) {
5294         //
5295         // Upon failure, revert back to the started state.
5296         //
5297         return WdfDevStatePwrPolTimerExpiredWakeCapableDxAllocFailed;
5298     }
5299 
5300     return WdfDevStatePwrPolNull;
5301 }
5302 
5303 WDF_DEVICE_POWER_POLICY_STATE
PowerPolTimerExpiredWakeCapableSendWake(__inout FxPkgPnp * This)5304 FxPkgPnp::PowerPolTimerExpiredWakeCapableSendWake(
5305     __inout FxPkgPnp* This
5306     )
5307 {
5308     NTSTATUS status;
5309 
5310     ASSERT_PWR_POL_STATE(
5311         This, WdfDevStatePwrPolTimerExpiredWakeCapableSendWake);
5312 
5313     //
5314     // We are in a wake-enabled path, keep wake interrupts connected.
5315     //
5316     This->m_WakeInterruptsKeepConnected = TRUE;
5317 
5318     status = This->PowerPolicySendWaitWakeRequest(PowerSystemWorking);
5319 
5320     if (!NT_SUCCESS(status)) {
5321         DoTraceLevelMessage(
5322             This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
5323             "Could not allocate wake request for wake from S0, revert arming,"
5324             " %!STATUS!", status);
5325 
5326         COVERAGE_TRAP();
5327 
5328         return WdfDevStatePwrPolTimerExpiredWakeCapableCleanup;
5329     }
5330 
5331     return WdfDevStatePwrPolNull;
5332 }
5333 
5334 WDF_DEVICE_POWER_POLICY_STATE
PowerPolTimerExpiredWakeCapableUsbSS(__inout FxPkgPnp * This)5335 FxPkgPnp::PowerPolTimerExpiredWakeCapableUsbSS(
5336     __inout FxPkgPnp* This
5337     )
5338 /*++
5339 
5340 Routine Description:
5341     Sends the selective suspend ready irp down to the USB parent
5342 
5343 Arguments:
5344     This - instance of the state machine
5345 
5346 Return Value:
5347     WdfDevStatePwrPolNull
5348 
5349   --*/
5350 {
5351     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolTimerExpiredWakeCapableUsbSS);
5352 
5353     This->PowerPolicySubmitUsbIdleNotification();
5354 
5355     return WdfDevStatePwrPolNull;
5356 }
5357 
5358 WDF_DEVICE_POWER_POLICY_STATE
PowerPolWakeCapableUsbSSCompleted(__inout FxPkgPnp * This)5359 FxPkgPnp::PowerPolWakeCapableUsbSSCompleted(
5360     __inout FxPkgPnp* This
5361     )
5362 /*++
5363 
5364 Routine Description:
5365     We've sent the USB idle notification, but the bus driver completed it even
5366     before sending the USB idle callback.
5367 
5368 Arguments:
5369     This - instance of the state machine
5370 
5371 Return Value:
5372     WdfDevStatePwrPolNull
5373 
5374   --*/
5375 {
5376     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolWakeCapableUsbSSCompleted);
5377 
5378     //
5379     // We notified the device power requirement state machine that we are about
5380     // to power down, but eventually we didn't power down. So notify the device
5381     // power requirement state machine that the device should be considered
5382     // powered on.
5383     //
5384     This->m_PowerPolicyMachine.m_Owner->
5385                 m_PoxInterface.DeviceIsPoweredOn();
5386 
5387     This->m_PowerPolicyMachine.m_Owner->
5388             m_PoxInterface.RequestComponentActive();
5389 
5390     return WdfDevStatePwrPolStartedWakeCapable;
5391 }
5392 
5393 WDF_DEVICE_POWER_POLICY_STATE
PowerPolTimerExpiredWakeCapableWakeArrived(__inout FxPkgPnp * This)5394 FxPkgPnp::PowerPolTimerExpiredWakeCapableWakeArrived(
5395     __inout FxPkgPnp* This
5396     )
5397 /*++
5398 
5399 Routine Description:
5400     The device is has been armed for wake from S0.  It is in a partial Dx state
5401     (I/O stopped) and needs to transition to the total Dx state by sending
5402     a PowerCompleteDx event to the power state machine.
5403 
5404 Arguments:
5405     This - instance of the state machine
5406 
5407 Return Value:
5408     WdfDevStatePwrPolNull
5409 
5410   --*/
5411 {
5412     NTSTATUS status;
5413 
5414     ASSERT_PWR_POL_STATE(
5415         This, WdfDevStatePwrPolTimerExpiredWakeCapableWakeArrived);
5416 
5417     status = This->m_PowerPolicyMachine.m_Owner->m_DeviceArmWakeFromS0.Invoke(
5418         This->m_Device->GetHandle()
5419         );
5420 
5421     if (!NT_SUCCESS(status)) {
5422         return WdfDevStatePwrPolTimerExpiredWakeCapableCancelWake;
5423     }
5424 
5425     //
5426     // If the PDO is the Power Policy owner, then enable wake at bus, otherwise
5427     // the power state machine will enable wake at bus.
5428     //
5429     if (This->m_Device->IsPdo()) {
5430         status = This->PowerEnableWakeAtBusOverload();
5431         if (!NT_SUCCESS(status)) {
5432             DoTraceLevelMessage(
5433                 This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
5434                 "WDFDEVICE %p Failed to Enable Wake at Bus, %!STATUS!",
5435                 This->m_Device->GetHandle(), status);
5436 
5437             return WdfDevStatePwrPolTimerExpiredWakeCapableCancelWake;
5438         }
5439     }
5440 
5441     This->PowerProcessEvent(PowerCompleteDx);
5442 
5443     return WdfDevStatePwrPolNull;
5444 }
5445 
5446 WDF_DEVICE_POWER_POLICY_STATE
PowerPolTimerExpiredWakeCapableCancelWake(__inout FxPkgPnp * This)5447 FxPkgPnp::PowerPolTimerExpiredWakeCapableCancelWake(
5448     __inout FxPkgPnp* This
5449     )
5450 /*++
5451 
5452 Routine Description:
5453     Device was attempting to enter Dx armed for wake from S0, but
5454     EvtDeviceArmForWakeFromS0 returned failure.  Cancel the wait wake irp and
5455     move into Dx.
5456 
5457 Arguments:
5458     This - instance of the state machine
5459 
5460 Return Value:
5461     new state
5462 
5463   --*/
5464 {
5465     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolTimerExpiredWakeCapableCancelWake);
5466 
5467     if (This->PowerPolicyCancelWaitWake() == FALSE) {
5468         return WdfDevStatePwrPolTimerExpiredWakeCapableWakeCanceled;
5469     }
5470 
5471     return WdfDevStatePwrPolNull;
5472 }
5473 
5474 WDF_DEVICE_POWER_POLICY_STATE
PowerPolTimerExpiredWakeCapableWakeCanceled(__inout FxPkgPnp * This)5475 FxPkgPnp::PowerPolTimerExpiredWakeCapableWakeCanceled(
5476     __inout FxPkgPnp* This
5477     )
5478 /*++
5479 
5480 Routine Description:
5481     The device was put into a wake from S0 state and the arm failed.  The wait
5482     wake irp has been canceled, now complete the power down.
5483 
5484 Arguments:
5485     This - instance of the state machine
5486 
5487 Return Value:
5488     WdfDevStatePwrPolTimerExpiredWakeCapableCleanup
5489 
5490   --*/
5491 {
5492     UNREFERENCED_PARAMETER(This);
5493 
5494     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolTimerExpiredWakeCapableWakeCanceled);
5495 
5496     return WdfDevStatePwrPolTimerExpiredWakeCapableCleanup;
5497 }
5498 
5499 WDF_DEVICE_POWER_POLICY_STATE
PowerPolTimerExpiredWakeCapableCleanup(__inout FxPkgPnp * This)5500 FxPkgPnp::PowerPolTimerExpiredWakeCapableCleanup(
5501     __inout FxPkgPnp* This
5502     )
5503 /*++
5504 
5505 Routine Description:
5506     An attempt to arm the device for wake from S0 has failed.  Decide if we need
5507     to complete the USB SS callback or not before completely powering down so
5508     that we can power back up again.
5509 
5510 Arguments:
5511     This - instance of the state machine
5512 
5513 Return Value:
5514     new state
5515 
5516   --*/
5517 {
5518     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolTimerExpiredWakeCapableCleanup);
5519 
5520     if (This->m_PowerPolicyMachine.m_Owner->m_IdleSettings.UsbSSCapable) {
5521         COVERAGE_TRAP();
5522         This->m_PowerPolicyMachine.UsbSSCallbackProcessingComplete();
5523     }
5524 
5525     //
5526     // Cancel UsbSS if present
5527     //
5528     if (This->PowerPolicyCancelUsbSSIfCapable()) {
5529         //
5530         // wait for Usbss completion event to move us from this state.
5531         //
5532         return WdfDevStatePwrPolNull;
5533     }
5534 
5535     return WdfDevStatePwrPolTimerExpiredWakeCompletedPowerDown;
5536 }
5537 
5538 WDF_DEVICE_POWER_POLICY_STATE
PowerPolTimerExpiredWakeCapableDxAllocFailed(__inout FxPkgPnp * This)5539 FxPkgPnp::PowerPolTimerExpiredWakeCapableDxAllocFailed(
5540     __inout FxPkgPnp* This
5541     )
5542 /*++
5543 
5544 Routine Description:
5545     The device idled out and we attempted to allocate a Dx irp so that we could
5546     be armed for wake from S0.  The Dx irp allocation failed.  Complete the
5547     USB SS callback and move back into the working state.
5548 
5549 Arguments:
5550     This - instance of the state machine
5551 
5552 Return Value:
5553     WdfDevStatePwrPolTimerExpiredWakeCapableUndoPowerDown
5554 
5555   --*/
5556 {
5557     ASSERT_PWR_POL_STATE(
5558         This, WdfDevStatePwrPolTimerExpiredWakeCapableDxAllocFailed);
5559 
5560     if (This->m_PowerPolicyMachine.m_Owner->m_IdleSettings.UsbSSCapable) {
5561         COVERAGE_TRAP();
5562         This->m_PowerPolicyMachine.UsbSSCallbackProcessingComplete();
5563     }
5564 
5565     //
5566     // cancel USB SS irp if capable
5567     //
5568     if (This->PowerPolicyCancelUsbSSIfCapable()) {
5569         //
5570         // wait for Usbss completion event to move us from this state.
5571         //
5572         return WdfDevStatePwrPolNull;
5573     }
5574 
5575     return WdfDevStatePwrPolTimerExpiredWakeCapableUndoPowerDown;
5576 }
5577 
5578 WDF_DEVICE_POWER_POLICY_STATE
PowerPolTimerExpiredWakeCapableUndoPowerDown(__inout FxPkgPnp * This)5579 FxPkgPnp::PowerPolTimerExpiredWakeCapableUndoPowerDown(
5580     __inout FxPkgPnp* This
5581     )
5582 /*++
5583 
5584 Routine Description:
5585     The device idled out, but a failure occurred when we attempted to power
5586     down. So we need to return to the active state now.
5587 
5588 Arguments:
5589     This - instance of the state machine
5590 
5591 Return Value:
5592     WdfDevStatePwrPolDeviceIdleReturnToActive
5593 
5594   --*/
5595 {
5596     ASSERT_PWR_POL_STATE(
5597         This, WdfDevStatePwrPolTimerExpiredWakeCapableUndoPowerDown);
5598 
5599     //
5600     // We notified the device power requirement state machine that we are about
5601     // to power down, but eventually we didn't power down. So notify the device
5602     // power requirement state machine that the device should be considered
5603     // powered on.
5604     //
5605     This->m_PowerPolicyMachine.m_Owner->
5606                 m_PoxInterface.DeviceIsPoweredOn();
5607     return WdfDevStatePwrPolDeviceIdleReturnToActive;
5608 }
5609 
5610 WDF_DEVICE_POWER_POLICY_STATE
PowerPolTimerExpiredWakeCompletedPowerDown(__inout FxPkgPnp * This)5611 FxPkgPnp::PowerPolTimerExpiredWakeCompletedPowerDown(
5612     __inout FxPkgPnp* This
5613     )
5614 /*++
5615 
5616 Routine Description:
5617     Complete the Dx transition from Dx armed for S0 wake.  Upon going into Dx,
5618     we will move back into D0 since the wake completed already (or there was
5619     an error in arming).
5620 
5621 Arguments:
5622     This - instance of the state machine
5623 
5624 Return Value:
5625     WdfDevStatePwrPolNull
5626 
5627   --*/
5628 {
5629     ASSERT_PWR_POL_STATE(
5630         This, WdfDevStatePwrPolTimerExpiredWakeCompletedPowerDown);
5631 
5632     This->PowerProcessEvent(PowerCompleteDx);
5633 
5634     return WdfDevStatePwrPolNull;
5635 }
5636 
5637 WDF_DEVICE_POWER_POLICY_STATE
PowerPolTimerExpiredWakeCompletedPowerUp(__inout FxPkgPnp * This)5638 FxPkgPnp::PowerPolTimerExpiredWakeCompletedPowerUp(
5639     __inout FxPkgPnp* This
5640     )
5641 /*++
5642 
5643 Routine Description:
5644     The device was armed for wake from S0 and the wake completed immediately
5645     (or there was a problem).  We put the device into Dx and we are now trying
5646     to bring it back into D0.
5647 
5648 Arguments:
5649     This - instance of the state machine
5650 
5651 Return Value:
5652     new state
5653 
5654   --*/
5655 {
5656     NTSTATUS status;
5657     BOOLEAN result;
5658 
5659     ASSERT_PWR_POL_STATE(
5660         This, WdfDevStatePwrPolTimerExpiredWakeCompletedPowerUp);
5661 
5662     This->m_PowerPolicyMachine.m_Owner->
5663             m_PoxInterface.RequestComponentActive();
5664 
5665     //
5666     // Disable the timer so that when we move back into D0, the timer is not
5667     // automatically started.  Since the timer has already fired, we should never
5668     // get FALSE back (which indicates we should wait for the timer to fire).
5669     //
5670     result = This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.DisableTimer();
5671     ASSERT(result);
5672     UNREFERENCED_PARAMETER(result);
5673 
5674     status = This->PowerPolicySendDevicePowerRequest(PowerDeviceD0, Retry);
5675 
5676     if (!NT_SUCCESS(status)) {
5677         //
5678         // Couldn't allocate power irp, goto the failed state
5679         //
5680         COVERAGE_TRAP();
5681         return WdfDevStatePwrPolDeviceD0PowerRequestFailed;
5682     }
5683 
5684     return WdfDevStatePwrPolNull;
5685 }
5686 
5687 WDF_DEVICE_POWER_POLICY_STATE
PowerPolTimerExpiredWakeCompletedHardwareStarted(__inout FxPkgPnp * This)5688 FxPkgPnp::PowerPolTimerExpiredWakeCompletedHardwareStarted(
5689     __inout FxPkgPnp* This
5690     )
5691 /*++
5692 
5693 Routine Description:
5694     We went idle and were in the process of powering down, but the wait-wake IRP
5695     completed even before we could arm the device for wake. We finished powering
5696     down the device and we're now powering it back up due to the wait-wake
5697     completion.
5698 
5699 Arguments:
5700     This - instance of the state machine
5701 
5702 Return Value:
5703     WdfDevStatePwrPolNull
5704 
5705   --*/
5706 {
5707     ASSERT_PWR_POL_STATE(This,
5708         WdfDevStatePwrPolTimerExpiredWakeCompletedHardwareStarted);
5709 
5710     This->m_PowerPolicyMachine.m_Owner->
5711                 m_PoxInterface.DeviceIsPoweredOn();
5712 
5713     return WdfDevStatePwrPolS0WakeCompletePowerUp;
5714 }
5715 
5716 WDF_DEVICE_POWER_POLICY_STATE
PowerPolWaitingArmedUsbSS(__inout FxPkgPnp * This)5717 FxPkgPnp::PowerPolWaitingArmedUsbSS(
5718     __inout FxPkgPnp* This
5719     )
5720 /*++
5721 
5722 Routine Description:
5723     Complete the USB SS callback now tha the device is armed and in Dx
5724 
5725 Arguments:
5726     This - instance of the state machine
5727 
5728 Return Value:
5729     WdfDevStatePwrPolWaitingArmed
5730 
5731   --*/
5732 {
5733     BOOLEAN result;
5734 
5735     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolWaitingArmedUsbSS);
5736 
5737     if (This->m_PowerPolicyMachine.m_Owner->m_IdleSettings.UsbSSCapable) {
5738         This->m_PowerPolicyMachine.UsbSSCallbackProcessingComplete();
5739     }
5740 
5741     //
5742     // Disable the timer so that when we move back into D0, the timer is not
5743     // automatically started.  Since the timer has already fired, we should never
5744     // get FALSE back (which indicates we should wait for the timer to fire).
5745     //
5746     result = This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.DisableTimer();
5747     ASSERT(result);
5748     UNREFERENCED_PARAMETER(result);
5749 
5750     //
5751     // PwrPolIoPresent can be sent before PwrPolPowerTimeoutExpired in the idle
5752     // state machine if the idle s.m. attempts to cancel the timer after it has
5753     // started running.  That means the PwrPolIoPresent meant to wake up the
5754     // device and resume from idle is lost.  By first querying the idle s.m.
5755     // after moving into Dx we can recover from the lost event.
5756     //
5757     return WdfDevStatePwrPolWaitingArmedQueryIdle;
5758 }
5759 
5760 WDF_DEVICE_POWER_POLICY_STATE
PowerPolWaitingArmedQueryIdle(__inout FxPkgPnp * This)5761 FxPkgPnp::PowerPolWaitingArmedQueryIdle(
5762     __inout FxPkgPnp* This
5763     )
5764 /*++
5765 
5766 Routine Description:
5767     The device was in the WaitingArmed state and received a PwrPolIoPresent
5768     event.  Before committing the device to move back to D0, check to see if
5769     the device has returned to an idle state.  This can easily happen if the
5770     driver causes a power reference in D0Exit accidentally and the power
5771     reference is removed before exitting the function.
5772 
5773 Arguments:
5774     This - instance of the state machine
5775 
5776 Return Value:
5777     new state
5778 
5779   --*/
5780 
5781 {
5782     //
5783     // If QueryReturnToIdle returns TRUE, return to the waiting state
5784     //
5785     if (This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.QueryReturnToIdle()) {
5786         return WdfDevStatePwrPolWaitingArmed;
5787     }
5788     else {
5789         return WdfDevStatePwrPolWaitingArmedIoPresentCancelUsbSS;
5790     }
5791 }
5792 
5793 WDF_DEVICE_POWER_POLICY_STATE
PowerPolIoPresentArmed(__inout FxPkgPnp * This)5794 FxPkgPnp::PowerPolIoPresentArmed(
5795     __inout FxPkgPnp* This
5796     )
5797 {
5798     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolIoPresentArmed);
5799 
5800     if (This->PowerPolicyCancelWaitWake() == FALSE &&
5801         This->m_PowerPolicyMachine.m_Owner->m_WakeCompletionEventDropped) {
5802         COVERAGE_TRAP();
5803         return WdfDevStatePwrPolIoPresentArmedWakeCanceled;
5804     }
5805 
5806     return WdfDevStatePwrPolNull;
5807 }
5808 
5809 WDF_DEVICE_POWER_POLICY_STATE
PowerPolWaitingArmedWakeInterruptFired(__inout FxPkgPnp * This)5810 FxPkgPnp::PowerPolWaitingArmedWakeInterruptFired(
5811     __inout FxPkgPnp* This
5812     )
5813 {
5814     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolWaitingArmedWakeInterruptFired);
5815 
5816     if (This->PowerPolicyCancelWaitWake() == FALSE &&
5817         This->m_PowerPolicyMachine.m_Owner->m_WakeCompletionEventDropped) {
5818         return WdfDevStatePwrPolWaitingArmedWakeSucceededCancelUsbSS;
5819     }
5820 
5821     return WdfDevStatePwrPolNull;
5822 }
5823 
5824 WDF_DEVICE_POWER_POLICY_STATE
PowerPolIoPresentArmedWakeCanceled(__inout FxPkgPnp * This)5825 FxPkgPnp::PowerPolIoPresentArmedWakeCanceled(
5826     __inout FxPkgPnp* This
5827     )
5828 {
5829     NTSTATUS status;
5830 
5831     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolIoPresentArmedWakeCanceled);
5832 
5833     This->m_PowerPolicyMachine.m_Owner->
5834             m_PoxInterface.RequestComponentActive();
5835 
5836     status = This->PowerPolicySendDevicePowerRequest(PowerDeviceD0, Retry);
5837 
5838     if (!NT_SUCCESS(status)) {
5839         COVERAGE_TRAP();
5840         return WdfDevStatePwrPolDeviceD0PowerRequestFailed;
5841     }
5842 
5843     return WdfDevStatePwrPolNull;
5844 }
5845 
5846 WDF_DEVICE_POWER_POLICY_STATE
PowerPolS0WakeDisarm(__inout FxPkgPnp * This)5847 FxPkgPnp::PowerPolS0WakeDisarm(
5848     __inout FxPkgPnp* This
5849     )
5850 {
5851     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolS0WakeDisarm);
5852 
5853     This->m_PowerPolicyMachine.m_Owner->
5854                 m_PoxInterface.DeviceIsPoweredOn();
5855 
5856     //
5857     // If the PDO is the Power Policy owner, then disable wake at bus, otherwise
5858     // the power state machine will disable wake at bus.
5859     //
5860     if (This->m_Device->IsPdo()) {
5861         This->PowerDisableWakeAtBusOverload();
5862     }
5863 
5864     This->m_PowerPolicyMachine.m_Owner->m_DeviceDisarmWakeFromS0.Invoke(
5865         This->m_Device->GetHandle()
5866         );
5867 
5868     return WdfDevStatePwrPolS0WakeCompletePowerUp;
5869 }
5870 
5871 WDF_DEVICE_POWER_POLICY_STATE
PowerPolS0WakeCompletePowerUp(__inout FxPkgPnp * This)5872 FxPkgPnp::PowerPolS0WakeCompletePowerUp(
5873     __inout FxPkgPnp* This
5874     )
5875 /*++
5876 
5877 Routine Description:
5878     We are moving back into D0 from being armed for wake from S0.  The device
5879     is in partial D0 (hw started) already, so complete the transition to D0
5880     by posting the PowerCompleteD0 event to the power state machine.
5881 
5882 Arguments:
5883     This - instance of the state machine
5884 
5885 Return Value:
5886     WdfDevStatePwrPolNull
5887 
5888   --*/
5889 {
5890     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolS0WakeCompletePowerUp);
5891 
5892     This->PowerProcessEvent(PowerCompleteD0);
5893 
5894     return WdfDevStatePwrPolNull;
5895 }
5896 
5897 WDF_DEVICE_POWER_POLICY_STATE
PowerPolTimerExpiredWakeSucceeded(__inout FxPkgPnp * This)5898 FxPkgPnp::PowerPolTimerExpiredWakeSucceeded(
5899     __inout FxPkgPnp* This
5900     )
5901 /*++
5902 
5903 Routine Description:
5904     The wake irp succeeded synchronously when we sent it down the stack.  Notify
5905     the driver and move immediately back into the working state.
5906 
5907 Arguments:
5908     This - instance of the state machine
5909 
5910 Return Value:
5911     WdfDevStatePwrPolStartingDecideS0Wake
5912 
5913   --*/
5914 {
5915     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolTimerExpiredWakeSucceeded);
5916 
5917     This->m_PowerPolicyMachine.m_Owner->m_DeviceWakeFromS0Triggered.Invoke(
5918         This->m_Device->GetHandle()
5919         );
5920 
5921     return WdfDevStatePwrPolTimerExpiredWakeCompletedDisarm;
5922 }
5923 
5924 WDF_DEVICE_POWER_POLICY_STATE
PowerPolTimerExpiredWakeCompletedDisarm(__inout FxPkgPnp * This)5925 FxPkgPnp::PowerPolTimerExpiredWakeCompletedDisarm(
5926     __inout FxPkgPnp* This
5927     )
5928 /*++
5929 
5930 Routine Description:
5931     The device was armed for wake from Dx in S0.  The wake irp completed
5932     before the PwrPolPowerDown was processed.  Disarm the device, move to Dx,
5933     and then immediately back to D0.
5934 
5935 Arguments:
5936     This - instance of the state machine
5937 
5938 Return Value:
5939     WdfDevStatePwrPolTimerExpiredWakeCapableCleanup
5940 
5941   --*/
5942 {
5943     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolTimerExpiredWakeCompletedDisarm);
5944 
5945     //
5946     // If the PDO is the Power Policy owner, then disable wake at bus, otherwise
5947     // the power state machine will disable wake at bus.
5948     //
5949     if (This->m_Device->IsPdo()) {
5950         This->PowerDisableWakeAtBusOverload();
5951     }
5952 
5953     This->m_PowerPolicyMachine.m_Owner->m_DeviceDisarmWakeFromS0.Invoke(
5954         This->m_Device->GetHandle()
5955         );
5956 
5957     return WdfDevStatePwrPolTimerExpiredWakeCapableCleanup;
5958 
5959 }
5960 
5961 WDF_DEVICE_POWER_POLICY_STATE
PowerPolWakeFailedUsbSS(__inout FxPkgPnp * This)5962 FxPkgPnp::PowerPolWakeFailedUsbSS(
5963     __inout FxPkgPnp* This
5964     )
5965 /*++
5966 
5967 Routine Description:
5968     Wake failed before we got the Dx irp.  Complete the SS calback and then
5969     move to the WakeFailed state.
5970 
5971 Arguments:
5972     This - instance of the state machine
5973 
5974 Return Value:
5975     WdfDevStatePwrPolIoPresentArmedWakeCanceled
5976 
5977   --*/
5978 {
5979     BOOLEAN result;
5980 
5981     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolWakeFailedUsbSS);
5982 
5983     if (This->m_PowerPolicyMachine.m_Owner->m_IdleSettings.UsbSSCapable) {
5984         This->m_PowerPolicyMachine.UsbSSCallbackProcessingComplete();
5985     }
5986 
5987     //
5988     // Disable the timer so that when we move back into D0, the timer is not
5989     // automatically started.  Since the timer has already fired, we should never
5990     // get FALSE back (which indicates we should wait for the timer to fire).
5991     //
5992     result = This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.DisableTimer();
5993     ASSERT(result);
5994     UNREFERENCED_PARAMETER(result);
5995 
5996     //
5997     // cancel USB SS irp if capable
5998     //
5999     if (This->PowerPolicyCancelUsbSSIfCapable()) {
6000         //
6001         // wait for Usbss completion event to move us from this state.
6002         //
6003         return WdfDevStatePwrPolNull;
6004     }
6005 
6006     return WdfDevStatePwrPolIoPresentArmedWakeCanceled;
6007 }
6008 
6009 WDF_DEVICE_POWER_POLICY_STATE
PowerPolTimerExpiredWakeCapablePowerDownFailedCancelWake(__inout FxPkgPnp * This)6010 FxPkgPnp::PowerPolTimerExpiredWakeCapablePowerDownFailedCancelWake(
6011     __inout FxPkgPnp* This
6012     )
6013 /*++
6014 
6015 Routine Description:
6016     We sent the wake request, but the power state machine failed.  Cancel the
6017     wake request and then move to the failed state.
6018 
6019 Arguments:
6020     This - instance of the state machine
6021 
6022 Return Value:
6023     new state
6024 
6025   --*/
6026 {
6027     ASSERT_PWR_POL_STATE(
6028         This,
6029         WdfDevStatePwrPolTimerExpiredWakeCapablePowerDownFailedCancelWake);
6030 
6031     if (This->PowerPolicyCancelWaitWake() == FALSE) {
6032         return WdfDevStatePwrPolTimerExpiredWakeCapablePowerDownFailedWakeCanceled;
6033     }
6034 
6035     return WdfDevStatePwrPolNull;
6036 }
6037 
6038 WDF_DEVICE_POWER_POLICY_STATE
PowerPolTimerExpiredWakeCapablePowerDownFailedWakeCanceled(__inout FxPkgPnp * This)6039 FxPkgPnp::PowerPolTimerExpiredWakeCapablePowerDownFailedWakeCanceled(
6040     __inout FxPkgPnp* This
6041     )
6042 /*++
6043 
6044 Routine Description:
6045     The wake request has been canceled. Move to the state where we will decide
6046     if we need to complete the USB SS callback.
6047 
6048     There is no need to disarm for wake from S0 because the failure here is for
6049     the device to power down.  We must assume the device is now in Dx and we
6050     cannot touch hw in this state.
6051 
6052 Arguments:
6053     This - instance of the state machine
6054 
6055 Return Value:
6056     new state, WdfDevStatePwrPolTimerExpiredWakeCapablePowerDownFailedDecideUsbSS
6057 
6058   --*/
6059 {
6060     UNREFERENCED_PARAMETER(This);
6061 
6062     ASSERT_PWR_POL_STATE(
6063         This,
6064         WdfDevStatePwrPolTimerExpiredWakeCapablePowerDownFailedWakeCanceled);
6065 
6066     return WdfDevStatePwrPolTimerExpiredWakeCapablePowerDownFailedUsbSS;
6067 }
6068 
6069 WDF_DEVICE_POWER_POLICY_STATE
PowerPolTimerExpiredWakeCapablePowerDownFailedUsbSS(__inout FxPkgPnp * This)6070 FxPkgPnp::PowerPolTimerExpiredWakeCapablePowerDownFailedUsbSS(
6071     __inout FxPkgPnp* This
6072     )
6073 /*++
6074 
6075 Routine Description:
6076     Complete the USB SS callback if enabled and the move to the failed state
6077 
6078 Arguments:
6079     This - instance of the state machine
6080 
6081 Return Value:
6082     new state, WdfDevStatePwrPolDevicePowerRequestFailed
6083 
6084   --*/
6085 {
6086     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolTimerExpiredWakeCapablePowerDownFailedUsbSS);
6087 
6088     if (This->m_PowerPolicyMachine.m_Owner->m_IdleSettings.UsbSSCapable) {
6089         This->m_PowerPolicyMachine.UsbSSCallbackProcessingComplete();
6090     }
6091 
6092     if (This->PowerPolicyCancelUsbSSIfCapable()) {
6093         //
6094         // wait for Usbss completion event to move us from this state.
6095         //
6096         return WdfDevStatePwrPolNull;
6097     }
6098 
6099     return WdfDevStatePwrPolDevicePowerRequestFailed;
6100 }
6101 
6102 WDF_DEVICE_POWER_POLICY_STATE
PowerPolCancelingWakeForSystemSleep(__inout FxPkgPnp * This)6103 FxPkgPnp::PowerPolCancelingWakeForSystemSleep(
6104     __inout FxPkgPnp* This
6105     )
6106 {
6107     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolCancelingWakeForSystemSleep);
6108 
6109     if (This->PowerPolicyCancelWaitWake() == FALSE &&
6110         This->m_PowerPolicyMachine.m_Owner->m_WakeCompletionEventDropped) {
6111         return WdfDevStatePwrPolCancelingWakeForSystemSleepWakeCanceled;
6112     }
6113 
6114     return WdfDevStatePwrPolNull;
6115 }
6116 
6117 WDF_DEVICE_POWER_POLICY_STATE
PowerPolCancelingWakeForSystemSleepWakeCanceled(__inout FxPkgPnp * This)6118 FxPkgPnp::PowerPolCancelingWakeForSystemSleepWakeCanceled(
6119     __inout FxPkgPnp* This
6120     )
6121 {
6122     NTSTATUS status;
6123 
6124     ASSERT_PWR_POL_STATE(
6125         This, WdfDevStatePwrPolCancelingWakeForSystemSleepWakeCanceled);
6126 
6127     status = This->PowerPolicySendDevicePowerRequest(PowerDeviceD0, NoRetry);
6128 
6129     if (!NT_SUCCESS(status)) {
6130         COVERAGE_TRAP();
6131         return WdfDevStatePwrPolPowerUpForSystemSleepNotSeen;
6132     }
6133 
6134     return WdfDevStatePwrPolNull;
6135 }
6136 
6137 WDF_DEVICE_POWER_POLICY_STATE
PowerPolDisarmingWakeForSystemSleepCompletePowerUp(__inout FxPkgPnp * This)6138 FxPkgPnp::PowerPolDisarmingWakeForSystemSleepCompletePowerUp(
6139     __inout FxPkgPnp* This
6140     )
6141 /*++
6142 
6143 Routine Description:
6144     The device was armed for wake from S0 and in Dx.  The machine is now moving
6145     into Sx.  The device is currently in partial D0 (HW started).  Disarm wake
6146     from S0 and then move the device fully into D0 (I/0 started).
6147 
6148 Arguments:
6149     This - instance of the state machine
6150 
6151 Return Value:
6152     WdfDevStatePwrPolNull
6153 
6154   --*/
6155 {
6156     ASSERT_PWR_POL_STATE(
6157         This, WdfDevStatePwrPolDisarmingWakeForSystemSleepCompletePowerUp);
6158 
6159     //
6160     // If the PDO is the Power Policy owner, then disable wake at bus, otherwise
6161     // the power state machine will disable wake at bus.
6162     //
6163     if (This->m_Device->IsPdo()) {
6164         This->PowerDisableWakeAtBusOverload();
6165     }
6166 
6167     This->m_PowerPolicyMachine.m_Owner->m_DeviceDisarmWakeFromS0.Invoke(
6168         This->m_Device->GetHandle()
6169         );
6170 
6171     This->PowerProcessEvent(PowerCompleteD0);
6172 
6173     return WdfDevStatePwrPolNull;
6174 }
6175 
6176 WDF_DEVICE_POWER_POLICY_STATE
PowerPolPowerUpForSystemSleepFailed(__inout FxPkgPnp * This)6177 FxPkgPnp::PowerPolPowerUpForSystemSleepFailed(
6178     __inout FxPkgPnp* This
6179     )
6180 /*++
6181 
6182 Routine Description:
6183     The system is moving into an Sx state and the device was in a Dx armed for
6184     wake from S0 state.  Power up has failed (could not allocate the request,
6185     actual power up path failed, etc).  Complete the Sx irp and move into a
6186     state where we can be removed when we return to S0.
6187 
6188 Arguments:
6189     This - instance of the state machine
6190 
6191 Return Value:
6192     WdfDevStatePwrPolDevicePowerRequestFailed
6193 
6194   --*/
6195 {
6196     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolPowerUpForSystemSleepFailed);
6197 
6198     This->PowerPolicyCompleteSystemPowerIrp();
6199 
6200     return WdfDevStatePwrPolDevicePowerRequestFailed;
6201 }
6202 
6203 WDF_DEVICE_POWER_POLICY_STATE
PowerPolWokeFromS0UsbSS(__inout FxPkgPnp * This)6204 FxPkgPnp::PowerPolWokeFromS0UsbSS(
6205     __inout FxPkgPnp* This
6206     )
6207 /*++
6208 
6209 Routine Description:
6210     The device successfully woke up before we got to the WaitingArmed state.
6211     Complete the USB SS callback while we are in Dx.
6212 
6213 Arguments:
6214     This - instance of the state machine
6215 
6216 Return Value:
6217     WdfDevStatePwrPolWokeFromS0
6218 
6219   --*/
6220 {
6221     BOOLEAN result;
6222 
6223     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolWokeFromS0UsbSS);
6224 
6225     if (This->m_PowerPolicyMachine.m_Owner->m_IdleSettings.UsbSSCapable) {
6226         This->m_PowerPolicyMachine.UsbSSCallbackProcessingComplete();
6227     }
6228 
6229     //
6230     // Disable the timer so that when we move back into D0, the timer is not
6231     // automatically started.  Since the timer has already fired, we should never
6232     // get FALSE back (which indicates we should wait for the timer to fire).
6233     //
6234     result = This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.DisableTimer();
6235     ASSERT(result);
6236     UNREFERENCED_PARAMETER(result);
6237 
6238     //
6239     // Cancel USBSS irp if capable
6240     //
6241     if (This->PowerPolicyCancelUsbSSIfCapable()) {
6242         //
6243         // Usbss completion event will move us from this state.
6244         //
6245         return WdfDevStatePwrPolNull;
6246     }
6247 
6248     return WdfDevStatePwrPolWokeFromS0;
6249 }
6250 
6251 WDF_DEVICE_POWER_POLICY_STATE
PowerPolWokeFromS0(__inout FxPkgPnp * This)6252 FxPkgPnp::PowerPolWokeFromS0(
6253     __inout FxPkgPnp* This
6254     )
6255 {
6256     NTSTATUS status;
6257 
6258     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolWokeFromS0);
6259 
6260     This->m_PowerPolicyMachine.m_Owner->
6261             m_PoxInterface.RequestComponentActive();
6262 
6263     status = This->PowerPolicySendDevicePowerRequest(PowerDeviceD0, Retry);
6264     if (!NT_SUCCESS(status)) {
6265         COVERAGE_TRAP();
6266         return WdfDevStatePwrPolDeviceD0PowerRequestFailed;
6267     }
6268 
6269     return WdfDevStatePwrPolNull;
6270 }
6271 
6272 WDF_DEVICE_POWER_POLICY_STATE
PowerPolWokeFromS0NotifyDriver(__inout FxPkgPnp * This)6273 FxPkgPnp::PowerPolWokeFromS0NotifyDriver(
6274     __inout FxPkgPnp* This
6275     )
6276 /*++
6277 
6278 Routine Description:
6279     The device was armed for wake from S0 and it successfully woke up and triggered
6280     wake.  Notify the driver of this on the way back up to D0.
6281 
6282 Arguments:
6283     This - instance of the state machine
6284 
6285 Return Value:
6286     WdfDevStatePwrPolS0WakeDisarm
6287 
6288   --*/
6289 {
6290     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolWokeFromS0NotifyDriver);
6291 
6292     This->m_PowerPolicyMachine.m_Owner->m_DeviceWakeFromS0Triggered.Invoke(
6293         This->m_Device->GetHandle()
6294         );
6295 
6296     return WdfDevStatePwrPolS0WakeDisarm;
6297 }
6298 
6299 WDF_DEVICE_POWER_POLICY_STATE
PowerPolStoppingResetDevice(__inout FxPkgPnp * This)6300 FxPkgPnp::PowerPolStoppingResetDevice(
6301     __inout FxPkgPnp* This
6302     )
6303 /*++
6304 
6305 Routine Description:
6306     The device was in a Dx state, unarmed for wake.  The device is not being
6307     removed, so we must disable the idle timer and power up the device so that
6308     we can implicitly power it down.
6309 
6310 Arguments:
6311     This - instance of the state machine
6312 
6313 Return Value:
6314     new state
6315 
6316   --*/
6317 {
6318     NTSTATUS status;
6319     BOOLEAN result;
6320 
6321     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolStoppingResetDevice);
6322 
6323     This->m_PowerPolicyMachine.m_Owner->
6324             m_PoxInterface.RequestComponentActive();
6325 
6326     result = This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.DisableTimer();
6327     ASSERT(result);
6328     UNREFERENCED_PARAMETER(result);
6329 
6330     status = This->PowerPolicySendDevicePowerRequest(PowerDeviceD0, Retry);
6331 
6332     if (!NT_SUCCESS(status)) {
6333         COVERAGE_TRAP();
6334         return WdfDevStatePwrPolDeviceD0PowerRequestFailed;
6335     }
6336 
6337     return WdfDevStatePwrPolNull;
6338 }
6339 
6340 WDF_DEVICE_POWER_POLICY_STATE
PowerPolStoppingResetDeviceCompletePowerUp(__inout FxPkgPnp * This)6341 FxPkgPnp::PowerPolStoppingResetDeviceCompletePowerUp(
6342     __inout FxPkgPnp* This
6343     )
6344 /*++
6345 
6346 Routine Description:
6347    The device was idled out and in Dx (not armed for wake from S0).  The power
6348    policy state machine is being stopped and the device has been brought into
6349    partial D0 (HW started).  Complete the D0 transition by sending PowerCompleteD0
6350    to the power state machine.
6351 
6352 Arguments:
6353     This - Instance of the state machine
6354 
6355 Return Value:
6356     WdfDevStatePwrPolNull
6357 
6358   --*/
6359 {
6360     ASSERT_PWR_POL_STATE(
6361         This, WdfDevStatePwrPolStoppingResetDeviceCompletePowerUp);
6362 
6363     This->m_PowerPolicyMachine.m_Owner->
6364                 m_PoxInterface.DeviceIsPoweredOn();
6365 
6366     This->PowerProcessEvent(PowerCompleteD0);
6367 
6368     return WdfDevStatePwrPolNull;
6369 }
6370 
6371 WDF_DEVICE_POWER_POLICY_STATE
PowerPolStoppingResetDeviceFailed(__inout FxPkgPnp * This)6372 FxPkgPnp::PowerPolStoppingResetDeviceFailed(
6373     __inout FxPkgPnp* This
6374     )
6375 /*++
6376 
6377 Routine Description:
6378     The attempt to power on a device in the idled out state so that we can stop
6379     the power policy state machine failed.  Record the error and continue down
6380     the stop path.
6381 
6382 Arguments:
6383     This - instance of the state machine
6384 
6385 Return Value:
6386     WdfDevStatePwrPolStopping
6387 
6388   --*/
6389 
6390 {
6391     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolStoppingResetDeviceFailed);
6392 
6393     This->m_PowerPolicyMachine.m_Owner->m_PowerFailed = TRUE;
6394 
6395     //
6396     // Notify the device power requirement state machine that the device should
6397     // be considered powered on, although it is not. Doing this will ensure that
6398     // component activation before device removal will succeed.
6399     //
6400     This->m_PowerPolicyMachine.m_Owner->
6401                 m_PoxInterface.DeviceIsPoweredOn();
6402 
6403     return WdfDevStatePwrPolStopping;
6404 }
6405 
6406 WDF_DEVICE_POWER_POLICY_STATE
PowerPolStoppingD0(__inout FxPkgPnp * This)6407 FxPkgPnp::PowerPolStoppingD0(
6408     __inout FxPkgPnp* This
6409     )
6410 {
6411     NTSTATUS status;
6412 
6413     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolStoppingD0);
6414 
6415     This->m_PowerPolicyMachine.m_Owner->
6416             m_PoxInterface.RequestComponentActive();
6417 
6418     This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.DisableTimer();
6419 
6420     status = This->PowerPolicySendDevicePowerRequest(PowerDeviceD0, Retry);
6421     if (!NT_SUCCESS(status)) {
6422         COVERAGE_TRAP();
6423         return WdfDevStatePwrPolDeviceD0PowerRequestFailed;
6424     }
6425 
6426     return WdfDevStatePwrPolNull;
6427 }
6428 
6429 WDF_DEVICE_POWER_POLICY_STATE
PowerPolStoppingD0Failed(__inout FxPkgPnp * This)6430 FxPkgPnp::PowerPolStoppingD0Failed(
6431     __inout FxPkgPnp* This
6432     )
6433 /*++
6434 
6435 Routine Description:
6436     While attempting to stop the device and bring it into D0, power up failed.
6437     Record the error and continue.
6438 
6439 Arguments:
6440     This - instance of the state machine
6441 
6442 Return Value:
6443     WdfDevStatePwrPolStoppingDisarmWakeCancelWake
6444 
6445   --*/
6446 
6447 {
6448     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolStoppingD0Failed);
6449 
6450     This->m_PowerPolicyMachine.m_Owner->m_PowerFailed = TRUE;
6451 
6452     //
6453     // Notify the device power requirement state machine that the device should
6454     // be considered powered on, although it is not. Doing this will ensure that
6455     // component activation before device removal will succeed.
6456     //
6457     This->m_PowerPolicyMachine.m_Owner->
6458                 m_PoxInterface.DeviceIsPoweredOn();
6459 
6460     return WdfDevStatePwrPolStoppingDisarmWakeCancelWake;
6461 }
6462 
6463 WDF_DEVICE_POWER_POLICY_STATE
PowerPolStoppingDisarmWake(__inout FxPkgPnp * This)6464 FxPkgPnp::PowerPolStoppingDisarmWake(
6465     __inout FxPkgPnp* This
6466     )
6467 {
6468     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolStoppingDisarmWake);
6469 
6470     This->m_PowerPolicyMachine.m_Owner->
6471                 m_PoxInterface.DeviceIsPoweredOn();
6472 
6473     //
6474     // If the PDO is the Power Policy owner, then disable wake at bus, otherwise
6475     // the power state machine will disable wake at bus.
6476     //
6477     if (This->m_Device->IsPdo()) {
6478         This->PowerDisableWakeAtBusOverload();
6479     }
6480 
6481     This->m_PowerPolicyMachine.m_Owner->m_DeviceDisarmWakeFromS0.Invoke(
6482         This->m_Device->GetHandle()
6483         );
6484 
6485     This->PowerProcessEvent(PowerCompleteD0);
6486 
6487     return WdfDevStatePwrPolNull;
6488 
6489 }
6490 
6491 WDF_DEVICE_POWER_POLICY_STATE
PowerPolStoppingDisarmWakeCancelWake(__inout FxPkgPnp * This)6492 FxPkgPnp::PowerPolStoppingDisarmWakeCancelWake(
6493     __inout FxPkgPnp* This
6494     )
6495 {
6496     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolStoppingDisarmWakeCancelWake);
6497 
6498     if (This->PowerPolicyCancelWaitWake() == FALSE &&
6499         This->m_PowerPolicyMachine.m_Owner->m_WakeCompletionEventDropped) {
6500         return WdfDevStatePwrPolStoppingDisarmWakeWakeCanceled;
6501     }
6502 
6503     return WdfDevStatePwrPolNull;
6504 }
6505 
6506 WDF_DEVICE_POWER_POLICY_STATE
PowerPolStoppingDisarmWakeWakeCanceled(__inout FxPkgPnp * This)6507 FxPkgPnp::PowerPolStoppingDisarmWakeWakeCanceled(
6508     __inout FxPkgPnp* This
6509     )
6510 {
6511     UNREFERENCED_PARAMETER(This);
6512 
6513     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolStoppingDisarmWakeWakeCanceled);
6514 
6515     return WdfDevStatePwrPolStopping;
6516 }
6517 
6518 WDF_DEVICE_POWER_POLICY_STATE
PowerPolStopping(__inout FxPkgPnp * This)6519 FxPkgPnp::PowerPolStopping(
6520     __inout FxPkgPnp* This
6521     )
6522 {
6523     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolStopping);
6524 
6525     //
6526     // Prevent any children from powering up.  Technically this is not necessary
6527     // because if we are getting to this point, all of our children have already
6528     // been implicitly stopped as well, but this keeps the child power up state
6529     // consistent with the power policy state.
6530     //
6531     This->PowerPolicyBlockChildrenPowerUp();
6532 
6533     //
6534     // This power change event does not need to be synchronous
6535     //
6536     This->PowerProcessEvent(PowerImplicitD3);
6537 
6538     return WdfDevStatePwrPolNull;
6539 }
6540 
6541 WDF_DEVICE_POWER_POLICY_STATE
PowerPolStoppingFailed(__inout FxPkgPnp * This)6542 FxPkgPnp::PowerPolStoppingFailed(
6543     __inout FxPkgPnp* This
6544     )
6545 /*++
6546 
6547 Routine Description:
6548     The attempt to move the power state machine into a Dx state failed.  Report
6549     the failure to pnp and move to the stopped state.
6550 
6551 Arguments:
6552     This - instance of the state machine
6553 
6554 Return Value:
6555     WdfDevStatePwrPolStopped
6556 
6557   --*/
6558 {
6559     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolStoppingFailed);
6560 
6561     This->m_PowerPolicyMachine.m_Owner->m_PowerFailed = TRUE;
6562 
6563     return WdfDevStatePwrPolStoppingSendStatus;
6564 }
6565 
6566 WDF_DEVICE_POWER_POLICY_STATE
PowerPolStoppingSendStatus(__inout FxPkgPnp * This)6567 FxPkgPnp::PowerPolStoppingSendStatus(
6568     __inout FxPkgPnp* This
6569     )
6570 /*++
6571 
6572 Routine Description:
6573     The power policy machine is about to finish stopping.  The final act of
6574     stopping is notify the Pnp state machine of the final outcome.  Do so, reset
6575     state, and move to the stopped state.
6576 
6577 Arguments:
6578     This - instance of the state machine
6579 
6580 Return Value:
6581     WdfDevStatePwrPolStopped
6582 
6583   --*/
6584 {
6585     KIRQL irql;
6586 
6587     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolStoppingSendStatus);
6588 
6589     This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.Stop();
6590 
6591     //
6592     // We raise IRQL to dispatch level so that pnp is forced onto its own thread
6593     // to process the PwrPolStopped event.  If pnp is on the power thread when
6594     // it processes the event and it tries to delete the dedicated thread, it
6595     // will deadlock waiting for the thread its on to exit.
6596     //
6597     Mx::MxRaiseIrql(DISPATCH_LEVEL, &irql);
6598     This->PnpProcessEvent(
6599         This->m_PowerPolicyMachine.m_Owner->m_PowerFailed
6600                           ? PnpEventPwrPolStopFailed
6601                           : PnpEventPwrPolStopped
6602         );
6603     Mx::MxLowerIrql(irql);
6604 
6605     //
6606     // Reset back to a non failed state
6607     //
6608     This->m_PowerPolicyMachine.m_Owner->m_PowerFailed = FALSE;
6609 
6610     return WdfDevStatePwrPolStopped;
6611 }
6612 
6613 WDF_DEVICE_POWER_POLICY_STATE
PowerPolStoppedRemoving(__inout FxPkgPnp * This)6614 FxPkgPnp::PowerPolStoppedRemoving(
6615     __inout FxPkgPnp* This
6616     )
6617 /*++
6618 
6619 Routine Description:
6620     The device is being removed. Tell the active/idle state machine to
6621     unregister with the power framework.
6622 
6623 Arguments:
6624     This - instance of the state machine
6625 
6626 Return Value:
6627     WdfDevStatePwrPolNull
6628 
6629   --*/
6630 {
6631     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolStoppedRemoving);
6632 
6633     This->m_PowerPolicyMachine.m_Owner->
6634             m_PoxInterface.UninitializeComponents();
6635 
6636     return WdfDevStatePwrPolRemoved;
6637 }
6638 
6639 WDF_DEVICE_POWER_POLICY_STATE
PowerPolRemoved(__inout FxPkgPnp * This)6640 FxPkgPnp::PowerPolRemoved(
6641     __inout FxPkgPnp* This
6642     )
6643 /*++
6644 
6645 Routine Description:
6646     The active/idle state machine has unregistered with the power framework.
6647     Tell the PNP state machine that device removal can proceed.
6648 
6649 Arguments:
6650     This - instance of the state machine
6651 
6652 Return Value:
6653     WdfDevStatePwrPolNull
6654 
6655   --*/
6656 {
6657     KIRQL irql;
6658 
6659     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolRemoved);
6660 
6661     //
6662     // We raise IRQL to dispatch level so that pnp is forced onto its own thread
6663     // to process the PwrPolRemoved event.  If pnp is on the power thread when
6664     // it processes the event and it tries to delete the dedicated thread, it
6665     // will deadlock waiting for the thread it is on to exit.
6666     //
6667     Mx::MxRaiseIrql(DISPATCH_LEVEL, &irql);
6668     This->PnpProcessEvent(PnpEventPwrPolRemoved);
6669     Mx::MxLowerIrql(irql);
6670 
6671     return WdfDevStatePwrPolNull;
6672 }
6673 
6674 WDF_DEVICE_POWER_POLICY_STATE
PowerPolRestarting(__inout FxPkgPnp * This)6675 FxPkgPnp::PowerPolRestarting(
6676     __inout FxPkgPnp* This
6677     )
6678 /*++
6679 
6680 Routine Description:
6681     The device is restarting after being stopped
6682 
6683 Arguments:
6684     This - instance of the state machine
6685 
6686 Return Value:
6687     WdfDevStatePwrPolNull
6688 
6689   --*/
6690 {
6691     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolRestarting);
6692 
6693     This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.Start();
6694 
6695     This->PowerProcessEvent(PowerImplicitD0);
6696 
6697     //
6698     // Wait for the successful power up before starting any idle timers.  If
6699     // the power up fails, we will not send a power policy stop from the pnp
6700     // engine.
6701     //
6702     return WdfDevStatePwrPolNull;
6703 }
6704 
6705 WDF_DEVICE_POWER_POLICY_STATE
PowerPolRestartingFailed(__inout FxPkgPnp * This)6706 FxPkgPnp::PowerPolRestartingFailed(
6707     __inout FxPkgPnp* This
6708     )
6709 /*++
6710 
6711 Routine Description:
6712     Power up failed when restarting the device
6713 
6714 Arguments:
6715     This - instance of the state machine
6716 
6717 Return Value:
6718     WdfDevStatePwrPolStopped
6719 
6720   --*/
6721 {
6722     KIRQL irql;
6723 
6724     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolRestartingFailed);
6725 
6726     This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.Stop();
6727 
6728     //
6729     // We raise IRQL to dispatch level so that pnp is forced onto its own thread
6730     // to process the PwrPolStartFailed event.  If pnp is on the power thread
6731     // when it processes the event and it tries to delete the dedicated thread,
6732     // it will deadlock waiting for the thread it is on to exit.
6733     //
6734     Mx::MxRaiseIrql(DISPATCH_LEVEL, &irql);
6735     This->PnpProcessEvent(PnpEventPwrPolStartFailed);
6736     Mx::MxLowerIrql(irql);
6737 
6738     return WdfDevStatePwrPolStopped;
6739 }
6740 
6741 WDF_DEVICE_POWER_POLICY_STATE
PowerPolStoppingCancelTimer(__inout FxPkgPnp * This)6742 FxPkgPnp::PowerPolStoppingCancelTimer(
6743     __inout FxPkgPnp* This
6744     )
6745 /*++
6746 
6747 Routine Description:
6748     Moving to the stopping state.  Need to cancel the idle timeout timer.
6749 
6750 Arguments:
6751     This - instance of the state machine
6752 
6753 Return Value:
6754     new power policy state
6755 
6756   --*/
6757 {
6758     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolStoppingCancelTimer);
6759 
6760     if (This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.DisableTimer()) {
6761         return WdfDevStatePwrPolStopping;
6762     }
6763     else {
6764         //
6765         // Timer was not canceled, move to the state where we wait for the
6766         // timeout event to be posted.
6767         //
6768         return WdfDevStatePwrPolStoppingWaitForIdleTimeout;
6769     }
6770 }
6771 
6772 WDF_DEVICE_POWER_POLICY_STATE
PowerPolStoppingCancelUsbSS(__inout FxPkgPnp * This)6773 FxPkgPnp::PowerPolStoppingCancelUsbSS(
6774     __inout FxPkgPnp* This
6775     )
6776 /*++
6777 
6778 Routine Description:
6779     Cancel the USB SS request because we are being stopped or surprise removed
6780 
6781 Arguments:
6782     This - instance of the state machine
6783 
6784 Return Value:
6785     WdfDevStatePwrPolStoppingWaitForUsbSSCompletion
6786 
6787   --*/
6788 {
6789     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolStoppingCancelUsbSS);
6790 
6791     //
6792     // We notified the device power requirement state machine that we are about
6793     // to power down, but eventually we didn't power down. So notify the device
6794     // power requirement state machine that the device should be considered
6795     // powered on.
6796     //
6797     This->m_PowerPolicyMachine.m_Owner->
6798                 m_PoxInterface.DeviceIsPoweredOn();
6799 
6800     This->m_PowerPolicyMachine.m_Owner->
6801             m_PoxInterface.RequestComponentActive();
6802 
6803     if (This->PowerPolicyCancelUsbSSIfCapable() == FALSE) {
6804         //
6805         // UsbSS already canceled/completed
6806         //
6807         return WdfDevStatePwrPolStoppingCancelTimer;
6808     }
6809 
6810     return WdfDevStatePwrPolStoppingWaitForUsbSSCompletion;
6811 }
6812 
6813 WDF_DEVICE_POWER_POLICY_STATE
PowerPolStoppingCancelWake(__inout FxPkgPnp * This)6814 FxPkgPnp::PowerPolStoppingCancelWake(
6815     __inout FxPkgPnp* This
6816     )
6817 /*++
6818 
6819 Routine Description:
6820     Cancels the pended wait wake in the case where we are surprise removed and
6821     in a Dx state and armed for wake.
6822 
6823 Arguments:
6824     This - instance of the state machine
6825 
6826 Return Value:
6827     If there was no request to cancel, WdfDevStatePwrPolStopping. If there was,
6828     wait for the wait completion event to be posted before transitioning.
6829 
6830   --*/
6831 {
6832     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolStoppingCancelWake);
6833 
6834     if (This->PowerPolicyCancelWaitWake() == FALSE &&
6835         This->m_PowerPolicyMachine.m_Owner->m_WakeCompletionEventDropped) {
6836         COVERAGE_TRAP();
6837         return WdfDevStatePwrPolStopping;
6838     }
6839     else {
6840         return WdfDevStatePwrPolNull;
6841     }
6842 }
6843 
6844 WDF_DEVICE_POWER_POLICY_STATE
PowerPolCancelUsbSS(__inout FxPkgPnp * This)6845 FxPkgPnp::PowerPolCancelUsbSS(
6846     __inout FxPkgPnp* This
6847     )
6848 /*++
6849 
6850 Routine Description:
6851     The S0 idle policy has changed.  Cancel the idle notification so we can move
6852     to another S0 started state
6853 
6854 Arguments:
6855     This - instance of the state machine
6856 
6857 Return Value:
6858     WdfDevStatePwrPolNull
6859 
6860   --*/
6861 {
6862     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolCancelUsbSS);
6863 
6864     //
6865     // We notified the device power requirement state machine that we are about
6866     // to power down, but eventually we didn't power down. So notify the device
6867     // power requirement state machine that the device should be considered
6868     // powered on.
6869     //
6870     This->m_PowerPolicyMachine.m_Owner->
6871                 m_PoxInterface.DeviceIsPoweredOn();
6872 
6873     This->m_PowerPolicyMachine.m_Owner->
6874             m_PoxInterface.RequestComponentActive();
6875 
6876     if (This->PowerPolicyCancelUsbSSIfCapable() == FALSE) {
6877         //
6878         // UsbSS has already been canceled/completed
6879         //
6880         return WdfDevStatePwrPolStartedCancelTimer;
6881     }
6882 
6883     return WdfDevStatePwrPolNull;
6884 }
6885 
6886 WDF_DEVICE_POWER_POLICY_STATE
PowerPolStarted(__inout FxPkgPnp * This)6887 FxPkgPnp::PowerPolStarted(
6888     __inout FxPkgPnp* This
6889     )
6890 /*++
6891 
6892 Routine Description:
6893     The device is now in the started state (w/regard to power policy).
6894 
6895 Arguments:
6896     This - instance of the state machine
6897 
6898 Return Value:
6899     WdfDevStatePwrPolNull
6900 
6901   --*/
6902 {
6903     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolStarted);
6904 
6905     //
6906     // We signal we are in D0 even though there is idling out in this state
6907     // because we could have just come from a state which *was* idled out.
6908     // For instance
6909     // 1) We are in WaitingArmed and an io present event moved us out of this state
6910     // 2) Immediately afterward, the s0 idle policy was changed
6911     // 3) When we enter StartingDecideS0Wake, we will move into this state without
6912     //    first entering StartedWakeCapable.
6913     // 4) The source of the io present event, if waiting synchronously needs to
6914     //    be unblocked.
6915     //
6916     This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.DisableTimer();
6917 
6918     return WdfDevStatePwrPolNull;
6919 }
6920 
6921 WDF_DEVICE_POWER_POLICY_STATE
PowerPolStartedCancelTimer(__inout FxPkgPnp * This)6922 FxPkgPnp::PowerPolStartedCancelTimer(
6923     __inout FxPkgPnp* This
6924     )
6925 /*++
6926 
6927 Routine Description:
6928     Device is started and we need to cancel the idle timer
6929 
6930 Arguments:
6931     This - instance of the state machine
6932 
6933 Return Value:
6934     new power policy state
6935 
6936   --*/
6937 {
6938     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolStartedCancelTimer);
6939 
6940     if (This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.DisableTimer()) {
6941         return WdfDevStatePwrPolStartingDecideS0Wake;
6942     }
6943     else {
6944         COVERAGE_TRAP();
6945         return WdfDevStatePwrPolStartedWaitForIdleTimeout;
6946     }
6947 }
6948 
6949 WDF_DEVICE_POWER_POLICY_STATE
PowerPolStartedWakeCapableCancelTimerForSleep(__inout FxPkgPnp * This)6950 FxPkgPnp::PowerPolStartedWakeCapableCancelTimerForSleep(
6951     __inout FxPkgPnp* This
6952     )
6953 /*++
6954 
6955 Routine Description:
6956     Device is wake capable and enabled for idling out.  Try to disable the
6957     power idle state machine.
6958 
6959 Arguments:
6960     This - instance of the state machine
6961 
6962 Return Value:
6963     new power policy state
6964 
6965   --*/
6966 {
6967     ASSERT_PWR_POL_STATE(
6968         This, WdfDevStatePwrPolStartedWakeCapableCancelTimerForSleep);
6969 
6970     if (This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.DisableTimer()) {
6971         return WdfDevStatePwrPolSleeping;
6972     }
6973     else {
6974         COVERAGE_TRAP();
6975         return WdfDevStatePwrPolStartedWakeCapableWaitForIdleTimeout;
6976     }
6977 }
6978 
6979 WDF_DEVICE_POWER_POLICY_STATE
PowerPolStartedWakeCapableSleepingUsbSS(__inout FxPkgPnp * This)6980 FxPkgPnp::PowerPolStartedWakeCapableSleepingUsbSS(
6981     __inout FxPkgPnp* This
6982     )
6983 /*++
6984 
6985 Routine Description:
6986     The machine is going to sleep after we have submitted the USB SS request
6987     but before USB has called us back on the go to idle callback.  Cancel the
6988     request and wait for its completion
6989 
6990 Arguments:
6991     This - instance of the state machine
6992 
6993 Return Value:
6994     WdfDevStatePwrPol
6995 
6996   --*/
6997 {
6998     BOOLEAN result;
6999 
7000     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolStartedWakeCapableSleepingUsbSS);
7001 
7002     result = This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.DisableTimer();
7003 
7004     //
7005     // Since the power timeout expired, the disable should not return FALSE
7006     //
7007     ASSERT(result);
7008     UNREFERENCED_PARAMETER(result);
7009 
7010     //
7011     // Cancel USBSS irp
7012     //
7013     This->PowerPolicyCancelUsbSS();
7014 
7015     return WdfDevStatePwrPolNull;
7016 }
7017 
7018 WDF_DEVICE_POWER_POLICY_STATE
PowerPolStartedIdleCapableCancelTimerForSleep(__inout FxPkgPnp * This)7019 FxPkgPnp::PowerPolStartedIdleCapableCancelTimerForSleep(
7020     __inout FxPkgPnp* This
7021     )
7022 /*++
7023 
7024 Routine Description:
7025     Device is idle capable and enabled for idling out.  Try to disable the
7026     power idle state machine.
7027 
7028 Arguments:
7029     This - instance of the state machine
7030 
7031 Return Value:
7032     new power policy state
7033 
7034   --*/
7035 {
7036     ASSERT_PWR_POL_STATE(
7037         This, WdfDevStatePwrPolStartedIdleCapableCancelTimerForSleep);
7038 
7039     if (This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.DisableTimer()) {
7040         return WdfDevStatePwrPolSleeping;
7041     }
7042     else {
7043         COVERAGE_TRAP();
7044         return WdfDevStatePwrPolStartedIdleCapableWaitForIdleTimeout;
7045     }
7046 }
7047 
7048 WDF_DEVICE_POWER_POLICY_STATE
PowerPolDeviceD0PowerRequestFailed(__inout FxPkgPnp * This)7049 FxPkgPnp::PowerPolDeviceD0PowerRequestFailed(
7050     __inout FxPkgPnp* This
7051     )
7052 /*++
7053 
7054 Routine Description:
7055     A D0 request failed, notify pnp.
7056 
7057 Arguments:
7058     This - instance of the state machine
7059 
7060 Return Value:
7061     WdfDevStatePwrPolDevicePowerRequestFailed
7062 
7063   --*/
7064 {
7065     COVERAGE_TRAP();
7066 
7067     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolDeviceD0PowerRequestFailed);
7068 
7069     This->SetInternalFailure();
7070 
7071     if (FALSE == This->m_ReleaseHardwareAfterDescendantsOnFailure) {
7072         This->PnpProcessEvent(PnpEventPowerUpFailed);
7073     }
7074 
7075     return WdfDevStatePwrPolDevicePowerRequestFailed;
7076 }
7077 
7078 WDF_DEVICE_POWER_POLICY_STATE
PowerPolDevicePowerRequestFailed(__inout FxPkgPnp * This)7079 FxPkgPnp::PowerPolDevicePowerRequestFailed(
7080     __inout FxPkgPnp* This
7081     )
7082 /*++
7083 
7084 Routine Description:
7085     Either we could not allocate a device power irp or the power state machine
7086     reported failure.  Mark the failure and then wait for pnp to send a stop
7087     event.
7088 
7089 Arguments:
7090     This - instance of the state machine
7091 
7092 Return Value:
7093     WdfDevStatePwrPolNull
7094 
7095   --*/
7096 {
7097     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolDevicePowerRequestFailed);
7098 
7099     //
7100     // In the failure path we still need to notify the children that they can
7101     // power up so that they will unblock.
7102     //
7103     This->PowerPolicyChildrenCanPowerUp();
7104 
7105     This->m_PowerPolicyMachine.m_Owner->m_PowerFailed = TRUE;
7106 
7107     //
7108     // Notify the device power requirement state machine that the device should
7109     // be considered powered on, although it may not be in reality. Doing this
7110     // will ensure that component activation before device removal will succeed.
7111     //
7112     This->m_PowerPolicyMachine.m_Owner->
7113                 m_PoxInterface.DeviceIsPoweredOn();
7114 
7115     return WdfDevStatePwrPolNull;
7116 }
7117 
7118 WDF_DEVICE_POWER_POLICY_STATE
PowerPolSleepingPowerDownNotProcessed(__inout FxPkgPnp * This)7119 FxPkgPnp::PowerPolSleepingPowerDownNotProcessed(
7120     __inout FxPkgPnp* This
7121     )
7122 /*++
7123 
7124 Routine Description:
7125     We requested a Dx irp but a driver layered above our device failed the
7126     request without sending it down the stack.  Queue a Tear down the stack and
7127     then move into a state where we will complete the Sx irp.
7128 
7129 Arguments:
7130     This - instance of the state machine
7131 
7132 Return Value:
7133     WdfDevStatePwrPolSystemSleepPowerRequestFailed
7134 
7135   --*/
7136 {
7137     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolSleepingPowerDownNotProcessed);
7138 
7139     This->SetInternalFailure();
7140 
7141     return WdfDevStatePwrPolSystemSleepPowerRequestFailed;
7142 }
7143 
7144 WDF_DEVICE_POWER_POLICY_STATE
PowerPolTimerExpiredWakeCapablePowerDownNotProcessed(__inout FxPkgPnp * This)7145 FxPkgPnp::PowerPolTimerExpiredWakeCapablePowerDownNotProcessed(
7146     __inout FxPkgPnp* This
7147     )
7148 /*++
7149 
7150 Routine Description:
7151     We requested a Dx irp after idling out, but a driver layered above our device
7152     failed the request without sending it down the stack.  Queue a tear down the
7153     stack and then move into a state where we can handle tear down.
7154 
7155 Arguments:
7156     This - instance of the state machine
7157 
7158 Return Value:
7159     WdfDevStatePwrPolTimerExpiredWakeCapableDxAllocFailed
7160 
7161   --*/
7162 {
7163     ASSERT_PWR_POL_STATE(
7164         This, WdfDevStatePwrPolTimerExpiredWakeCapablePowerDownNotProcessed);
7165 
7166     This->SetInternalFailure();
7167 
7168     return WdfDevStatePwrPolTimerExpiredWakeCapableDxAllocFailed;
7169 }
7170 
7171 WDF_DEVICE_POWER_POLICY_STATE
PowerPolTimerExpiredNoWakePowerDownNotProcessed(__inout FxPkgPnp * This)7172 FxPkgPnp::PowerPolTimerExpiredNoWakePowerDownNotProcessed(
7173     __inout FxPkgPnp* This
7174     )
7175 /*++
7176 
7177 Routine Description:
7178     We requested a Dx irp after idling out, but a driver layered above our device
7179     failed the request without sending it down the stack.  Queue a tear down the
7180     stack and then move into a state where we can handle tear down.
7181 
7182 Arguments:
7183     This - instance of the state machine
7184 
7185 Return Value:
7186     WdfDevStatePwrPolStartedIdleCapable
7187 
7188   --*/
7189 {
7190     ASSERT_PWR_POL_STATE(
7191         This, WdfDevStatePwrPolTimerExpiredNoWakePowerDownNotProcessed);
7192 
7193     This->SetInternalFailure();
7194 
7195     return WdfDevStatePwrPolTimerExpiredNoWakeUndoPowerDown;
7196 }
7197 
7198 WDF_DEVICE_POWER_POLICY_STATE
PowerPolTimerExpiredNoWakeUndoPowerDown(__inout FxPkgPnp * This)7199 FxPkgPnp::PowerPolTimerExpiredNoWakeUndoPowerDown(
7200     __inout FxPkgPnp* This
7201     )
7202 /*++
7203 
7204 Routine Description:
7205     The device was idle and attempting to go to Dx (without wake-from-S0), but
7206     a power down failure occurred.
7207 
7208 Arguments:
7209     This - instance of the state machine
7210 
7211 Return Value:
7212     WdfDevStatePwrPolNull
7213 
7214   --*/
7215 {
7216     ASSERT_PWR_POL_STATE(
7217         This, WdfDevStatePwrPolTimerExpiredNoWakeUndoPowerDown);
7218 
7219     //
7220     // We notified the device power requirement state machine that we are about
7221     // to power down, but eventually we didn't power down. So notify the device
7222     // power requirement state machine that the device should be considered
7223     // powered on.
7224     //
7225     This->m_PowerPolicyMachine.m_Owner->
7226                 m_PoxInterface.DeviceIsPoweredOn();
7227 
7228     return WdfDevStatePwrPolTimerExpiredNoWakeReturnToActive;
7229 }
7230 
7231 WDF_DEVICE_POWER_POLICY_STATE
PowerPolTimerExpiredNoWakeReturnToActive(__inout FxPkgPnp * This)7232 FxPkgPnp::PowerPolTimerExpiredNoWakeReturnToActive(
7233     __inout FxPkgPnp* This
7234     )
7235 /*++
7236 
7237 Routine Description:
7238     The device was idle and attempting to go to Dx (without wake-from-S0), but
7239     eventually it did not go to Dx. This might have been because a power down
7240     failure occurred or because we received the device power required
7241     notification from the power framework before we could go to Dx.
7242 
7243 Arguments:
7244     This - instance of the state machine
7245 
7246 Return Value:
7247     WdfDevStatePwrPolNull
7248 
7249   --*/
7250 {
7251     ASSERT_PWR_POL_STATE(
7252         This, WdfDevStatePwrPolTimerExpiredNoWakeReturnToActive);
7253 
7254     This->m_PowerPolicyMachine.m_Owner->
7255             m_PoxInterface.RequestComponentActive();
7256 
7257     return WdfDevStatePwrPolStartedIdleCapable;
7258 }
7259 
7260 WDF_DEVICE_POWER_POLICY_STATE
PowerPolTimerExpiredNoWakePoweredDownDisableIdleTimer(__inout FxPkgPnp * This)7261 FxPkgPnp::PowerPolTimerExpiredNoWakePoweredDownDisableIdleTimer(
7262     __inout FxPkgPnp* This
7263     )
7264 /*++
7265 
7266 Routine Description:
7267     The device has fully powered down.  Disable the idle timer so that when we
7268     we power up the idle timer will not start running immediately.  Rather,
7269     we should power up and only start the idle timer after being explicitly
7270     enabled again.
7271 
7272 Arguments:
7273     This - instance of the state machine
7274 
7275 Return Value:
7276     WdfDevStatePwrPolWaitingUnarmedQueryIdle
7277 
7278   --*/
7279 {
7280     BOOLEAN result;
7281 
7282     ASSERT_PWR_POL_STATE(
7283         This, WdfDevStatePwrPolTimerExpiredNoWakePoweredDownDisableIdleTimer);
7284 
7285     //
7286     // Disable the timer so that when we move back into D0, the timer is not
7287     // automatically started.  Since the timer has already fired, we should never
7288     // get FALSE back (which indicates we should wait for the timer to fire).
7289     //
7290     result = This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.DisableTimer();
7291     ASSERT(result);
7292     UNREFERENCED_PARAMETER(result);
7293 
7294     //
7295     // Check to see if we should immediately power up
7296     //
7297     return WdfDevStatePwrPolWaitingUnarmedQueryIdle;
7298 }
7299 
7300 WDF_DEVICE_POWER_POLICY_STATE
PowerPolPowerUpForSystemSleepNotSeen(__inout FxPkgPnp * This)7301 FxPkgPnp::PowerPolPowerUpForSystemSleepNotSeen(
7302     __inout FxPkgPnp* This
7303     )
7304 /*++
7305 
7306 Routine Description:
7307     PowerDeviceD0 request was not forwarded to this driver by upper driver even
7308     though this driver requested it. Power completion routine detects this
7309     condition, and causes transition to this state. Ensure that any pending
7310     S-IRP is completed.
7311 
7312 Arguments:
7313     This - instance of the state machine
7314 
7315 Return Value:
7316     WdfDevStatePwrPolDeviceD0PowerRequestFailed
7317 
7318   --*/
7319 {
7320     if (This->m_PendingSystemPowerIrp != NULL) {
7321         This->PowerPolicyCompleteSystemPowerIrp();
7322     }
7323 
7324     return WdfDevStatePwrPolDeviceD0PowerRequestFailed;
7325 }
7326 
7327 __drv_sameIRQL
7328 VOID
_PowerPolDeviceWaitWakeComplete(__in MdDeviceObject DeviceObject,__in UCHAR MinorFunction,__in POWER_STATE PowerState,__in_opt PVOID Context,__in PIO_STATUS_BLOCK IoStatus)7329 FxPkgPnp::_PowerPolDeviceWaitWakeComplete(
7330     __in MdDeviceObject DeviceObject,
7331     __in UCHAR MinorFunction,
7332     __in POWER_STATE PowerState,
7333     __in_opt PVOID Context,
7334     __in PIO_STATUS_BLOCK IoStatus
7335     )
7336 /*++
7337 
7338 Routine Description:
7339     Completion routine for a requested wait wake irp.  Called once the wait wake
7340     irp has traveled through the entire stack or when some driver in the stack
7341     completes the wait wake irp.  We feed the result of the wait wake operation
7342     back into the power policy state machine through an event.
7343 
7344 Arguments:
7345     Context - instance of the state machine
7346     IoStatus - pointer to the IO_STATUS_BLOCK structure for the completed IRP
7347     All others ignored
7348 
7349 Return Value:
7350     None
7351 
7352   --*/
7353 {
7354     FxPkgPnp* pThis;
7355 
7356     UNREFERENCED_PARAMETER(DeviceObject);
7357     UNREFERENCED_PARAMETER(MinorFunction);
7358     UNREFERENCED_PARAMETER(PowerState);
7359 
7360     pThis = (FxPkgPnp*) Context;
7361     pThis->m_PowerPolicyMachine.m_Owner->m_WaitWakeStatus = IoStatus->Status;
7362 
7363     if (NT_SUCCESS(IoStatus->Status)) {
7364         pThis->PowerPolicyProcessEvent(PwrPolWakeSuccess);
7365     }
7366     else {
7367         pThis->PowerPolicyProcessEvent(PwrPolWakeFailed);
7368     }
7369 }
7370 
7371 __drv_sameIRQL
7372 VOID
_PowerPolDevicePowerDownComplete(__in MdDeviceObject DeviceObject,__in UCHAR MinorFunction,__in POWER_STATE PowerState,__in_opt PVOID Context,__in PIO_STATUS_BLOCK IoStatus)7373 FxPkgPnp::_PowerPolDevicePowerDownComplete(
7374     __in MdDeviceObject DeviceObject,
7375     __in UCHAR MinorFunction,
7376     __in POWER_STATE PowerState,
7377     __in_opt PVOID Context,
7378     __in PIO_STATUS_BLOCK IoStatus
7379     )
7380 /*++
7381 
7382 Routine Description:
7383     Completion routine for a requested power irp.  Called once the power irp
7384     has traveled through the entire stack.  We feed the result of the power
7385     operation back into the power policy state machine through an event.
7386 
7387 Arguments:
7388     Context - instance of the state machine
7389     All others ignored
7390 
7391 Return Value:
7392     None
7393 
7394   --*/
7395 
7396 {
7397     FxPkgPnp* pThis;
7398 
7399     UNREFERENCED_PARAMETER(DeviceObject);
7400     UNREFERENCED_PARAMETER(MinorFunction);
7401     UNREFERENCED_PARAMETER(PowerState);
7402     UNREFERENCED_PARAMETER(IoStatus);
7403 
7404     pThis = (FxPkgPnp*) Context;
7405 
7406     //
7407     // Note that we are ignoring IoStatus.Status intentionally.  If we failed
7408     // power down in this device, we have tracked that state via
7409     // m_PowerDownFailure.  If some other device failed power down, we are still
7410     // in the state where we succeeded power down and we don't want to alter
7411     // that yet.
7412     //
7413     // Note that the state machine also handles an upper filter completing the
7414     // Dx irp before our device gets to process it (which would be a bug in the
7415     // filter driver) by handling the PwrPolPowerDown from the appropriate
7416     // state, as an example...
7417     //
7418     // a successful power down state transition looks like this
7419     // 1)  power policy state where we request a power irp
7420     // 2)  power sends a partial power down message (PwrPolPowerDownIoStopped)
7421     //      to power policy, moves to the partial power down state
7422     // 3)  power policy tells power to complete the power down
7423     // 4)  power completes the irp and we send the power down complete message
7424     //      (PwrPolPowerDown) moving from the partial power down state to the
7425     //      final power down state
7426     //
7427     // In the case where the top filter driver completes the PIRP without our
7428     // driver seeing it, we will be in the state where we requested a power irp
7429     // and process a power down complete event instead of the partial power down
7430     // event and in this transition, we detect the error.
7431     //
7432     if (pThis->m_PowerMachine.m_PowerDownFailure) {
7433         //
7434         // Clear the faliure condition if we ever attempt to power off this
7435         // device again (highly possible if it is a PDO).
7436         //
7437         pThis->m_PowerMachine.m_PowerDownFailure = FALSE;
7438 
7439         //
7440         // Power down failed, send ourself an even indicating that.
7441         //
7442         pThis->PowerPolicyProcessEvent(PwrPolPowerDownFailed);
7443 
7444         //
7445         // Inform pnp last so that all the other state machines are in the failed
7446         // state by the time we transition the pnp state of the device.
7447         //
7448         if (FALSE == pThis->m_ReleaseHardwareAfterDescendantsOnFailure) {
7449             pThis->PnpProcessEvent(PnpEventPowerDownFailed);
7450         }
7451     }
7452     else {
7453         //
7454         // Power down succeeded, send ourself an even indicating that.
7455         //
7456         pThis->PowerPolicyProcessEvent(PwrPolPowerDown);
7457     }
7458 }
7459 
7460 __drv_sameIRQL
7461 VOID
_PowerPolDevicePowerUpComplete(__in MdDeviceObject DeviceObject,__in UCHAR MinorFunction,__in POWER_STATE PowerState,__in_opt PVOID Context,__in PIO_STATUS_BLOCK IoStatus)7462 FxPkgPnp::_PowerPolDevicePowerUpComplete(
7463     __in MdDeviceObject DeviceObject,
7464     __in UCHAR MinorFunction,
7465     __in POWER_STATE PowerState,
7466     __in_opt PVOID Context,
7467     __in PIO_STATUS_BLOCK IoStatus
7468     )
7469 /*++
7470 
7471 Routine Description:
7472     Completion routine for a requested power irp.  Called once the power irp
7473     has traveled through the entire stack.  We feed the result of the power
7474     operation back into the power policy state machine through an event.
7475 
7476 Arguments:
7477     Context - instance of the state machine
7478     All others ignored
7479 
7480 Return Value:
7481     None
7482 
7483   --*/
7484 
7485 {
7486     FxPkgPnp* pThis;
7487 
7488     UNREFERENCED_PARAMETER(DeviceObject);
7489     UNREFERENCED_PARAMETER(MinorFunction);
7490     UNREFERENCED_PARAMETER(PowerState);
7491     UNREFERENCED_PARAMETER(IoStatus);
7492 
7493     pThis = (FxPkgPnp*) Context;
7494 
7495     //
7496     // The state machine handles an upper filter completing the
7497     // D0 irp before our device gets to process it (which would be a bug in the
7498     // filter driver).
7499     //
7500     if (pThis->m_PowerPolicyMachine.m_Owner->m_RequestedPowerUpIrp) {
7501         //
7502         // We requested a Power Irp but that never arrived in dispatch routine.
7503         // We know this because m_RequestedPowerUpIrp is still TRUE at the end of
7504         // the power irp completion (it is set to false when it arrives in
7505         // dispatch routine).
7506         //
7507         DoTraceLevelMessage(
7508             pThis->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
7509             "PowerDeviceD0 requested by WDFDEVICE 0x%p !devobj 0x%p, "
7510             "is being completed by upper driver without sending it to "
7511             "driver that requested it",
7512             pThis->m_Device->GetHandle(),
7513             pThis->m_Device->GetDeviceObject());
7514 
7515         //
7516         // Power-up request not seen, send ourself an event indicating that.
7517         //
7518         pThis->PowerPolicyProcessEvent(PwrPolPowerUpNotSeen);
7519     }
7520 }
7521 
7522 _Must_inspect_result_
7523 NTSTATUS
PowerPolicySendDevicePowerRequest(__in DEVICE_POWER_STATE DeviceState,__in SendDeviceRequestAction Action)7524 FxPkgPnp::PowerPolicySendDevicePowerRequest(
7525     __in DEVICE_POWER_STATE DeviceState,
7526     __in SendDeviceRequestAction Action
7527     )
7528 /*++
7529 
7530 Routine Description:
7531     Attempts to send a D irp to the stack.  The caller can specify if the
7532     request allocation is retried in case of failure.
7533 
7534 Design Notes:
7535     The timeout and number of retries are somewhat magical numbers.  They were
7536     picked so that the total amount of time spent attempting to retry would be
7537     under a minute.  Any memory pressure the machine would be under after the
7538     first failure should be over by the end of the minute; if not, there are
7539     bigger problems.
7540 
7541     If you look at each of the callers who specify Retry for the Action, nearly
7542     each one transitions to the WdfDevStatePwrPolDevicePowerRequestFailed state
7543     if the request cannot be allocated.  This transition could be placed in this
7544     function, but it is not for 2 reasons:
7545 
7546     1)  Keep this function simple
7547 
7548     2)  It makes the flow of the state transition function easier to understand;
7549         all transitions out of the current state happen within top level
7550         transition function
7551 
7552 Arguments:
7553     DeviceState - The new D state being request
7554 
7555     Action - Whether to retry upon failure to allocate the request
7556 
7557 Return Value:
7558     NT_SUCCESS if the request was allocated, !NT_SUCCESS otherwise
7559 
7560   --*/
7561 {
7562     MdRequestPowerComplete pCompletionRoutine;
7563     LARGE_INTEGER interval;
7564     NTSTATUS status;
7565     POWER_STATE state;
7566     ULONG i;
7567 
7568     status = STATUS_UNSUCCESSFUL;
7569     interval.QuadPart = WDF_REL_TIMEOUT_IN_MS(500);
7570     state.DeviceState = DeviceState;
7571 
7572     if (DeviceState == PowerDeviceD0) {
7573         //
7574         // We are powering up, we do not synchronize the completion of the D0 irp
7575         // with a potential S0 irp. However we need to ensure that if an upper filter
7576         // driver fails the power irp, we handle it gracefully rather than keep waiting
7577         // for the power irp to arrive.
7578         //
7579         pCompletionRoutine = _PowerPolDevicePowerUpComplete;
7580     }
7581     else {
7582         //
7583         // We are powering down, we synchronize the completion of the Dx irp
7584         // with a potential Sx irp.  If there is no pending Sx irp, the state
7585         // machine takes care of it.
7586         //
7587         pCompletionRoutine = _PowerPolDevicePowerDownComplete;
7588     }
7589 
7590     //
7591     // We track when we request power irps to catch someone other then ourselves
7592     // sending power irps to our own stack.
7593     //
7594     if (DeviceState == PowerDeviceD0) {
7595         m_PowerPolicyMachine.m_Owner->m_RequestedPowerUpIrp = TRUE;
7596     }
7597     else {
7598         m_PowerPolicyMachine.m_Owner->m_RequestedPowerDownIrp = TRUE;
7599     }
7600 
7601     for (i = 0; i < 100; i++) {
7602         status = FxIrp::RequestPowerIrp(m_Device->GetDeviceObject(),
7603                                    IRP_MN_SET_POWER,
7604                                    state,
7605                                    pCompletionRoutine,
7606                                    this);
7607 
7608         //
7609         // If we are not retrying, we always break out
7610         //
7611         if (NT_SUCCESS(status) || Action == NoRetry) {
7612             break;
7613         }
7614 
7615         Mx::MxDelayExecutionThread(KernelMode, FALSE, &interval);
7616     }
7617 
7618     if (!NT_SUCCESS(status)) {
7619         //
7620         // We are no longer requesting a power irp
7621         //
7622         if (DeviceState == PowerDeviceD0) {
7623             m_PowerPolicyMachine.m_Owner->m_RequestedPowerUpIrp = FALSE;
7624         }
7625         else {
7626             m_PowerPolicyMachine.m_Owner->m_RequestedPowerDownIrp = FALSE;
7627         }
7628 
7629         if (Action == Retry) {
7630             COVERAGE_TRAP();
7631 
7632             DoTraceLevelMessage(
7633                 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
7634                 "Could not request D%d irp for device %p (WDFDEVICE %p), "
7635                 "%!STATUS!", DeviceState-1,
7636                 m_Device->GetDeviceObject(),
7637                 m_Device->GetHandle(), status);
7638         }
7639     }
7640 
7641     DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGPNP,
7642                         "Requesting D%d irp, %!STATUS!",
7643                         DeviceState-1, status);
7644 
7645     return status;
7646 }
7647 
7648 _Must_inspect_result_
7649 NTSTATUS
PowerPolicySendWaitWakeRequest(__in SYSTEM_POWER_STATE SystemState)7650 FxPkgPnp::PowerPolicySendWaitWakeRequest(
7651     __in SYSTEM_POWER_STATE SystemState
7652     )
7653 {
7654     NTSTATUS status;
7655     POWER_STATE state;
7656 
7657     state.SystemState = SystemState;
7658 
7659     //
7660     // We track when we request power irps to catch someone other then ourselves
7661     // sending power irps to our own stack.
7662     //
7663     m_PowerPolicyMachine.m_Owner->m_RequestedWaitWakeIrp = TRUE;
7664 
7665     //
7666     // Since we are sending a fresh wake, clear any state that was meant
7667     // for the last wake IRP
7668     //
7669     m_SystemWokenByWakeInterrupt = FALSE;
7670 
7671     //
7672     // we are requesting new ww irp so re-initialize dropped event tracker.
7673     //
7674     m_PowerPolicyMachine.m_Owner->m_WakeCompletionEventDropped = FALSE;
7675 
7676     DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGPNP,
7677                         "Requesting wait wake irp for S%d", SystemState-1);
7678 
7679     status = FxIrp::RequestPowerIrp(m_Device->GetDeviceObject(),
7680                                IRP_MN_WAIT_WAKE,
7681                                state,
7682                                _PowerPolDeviceWaitWakeComplete,
7683                                this);
7684 
7685     if (!NT_SUCCESS(status)) {
7686         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
7687                             "Requesting wait wake irp for S%d failed, %!STATUS!",
7688                             SystemState-1, status);
7689 
7690         //
7691         // We are no longer requesting a power irp
7692         //
7693         m_PowerPolicyMachine.m_Owner->m_RequestedWaitWakeIrp = FALSE;
7694     }
7695 
7696     return status;
7697 }
7698 
7699 VOID
PowerPolicyCompleteSystemPowerIrp(VOID)7700 FxPkgPnp::PowerPolicyCompleteSystemPowerIrp(
7701     VOID
7702     )
7703 {
7704     FxIrp irp(m_PendingSystemPowerIrp);
7705     NTSTATUS status;
7706 
7707     ASSERT(m_PendingSystemPowerIrp != NULL);
7708 
7709     status = STATUS_SUCCESS;
7710 
7711     DoTraceLevelMessage(
7712         GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGPNP,
7713         "Completing system power irp %p (S%d), %!STATUS!",
7714         m_PendingSystemPowerIrp,
7715         irp.GetParameterPowerStateSystemState()-1,
7716         status);
7717 
7718     m_PendingSystemPowerIrp = NULL;
7719 
7720     CompletePowerRequest(&irp, STATUS_SUCCESS);
7721 }
7722 
7723 BOOLEAN
PowerPolicyCancelWaitWake(VOID)7724 FxPkgPnp::PowerPolicyCancelWaitWake(
7725     VOID
7726     )
7727 /*++
7728 
7729 Routine Description:
7730     Completes or cancels a pending wait wake irp depending on if the irp is
7731     present and if the device is the owner of the wait wake irp.
7732 
7733 Arguments:
7734 
7735 Return Value:
7736 
7737 
7738   --*/
7739 {
7740     MdIrp wwIrp;
7741     BOOLEAN cancelled, result;
7742 
7743     if (m_SharedPower.m_WaitWakeOwner) {
7744         //
7745         // This will complete the irp and then post the appropriate events to
7746         // both the power and power policy state machines.
7747         //
7748         cancelled = PowerIndicateWaitWakeStatus(STATUS_CANCELLED);
7749     }
7750     else {
7751         wwIrp = (MdIrp) InterlockedExchangePointer(
7752             (PVOID*) &m_SharedPower.m_WaitWakeIrp, NULL);
7753 
7754         if (wwIrp != NULL) {
7755             FxIrp irp(wwIrp);
7756 
7757             DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGPNP,
7758                                 "Successfully got WaitWake irp %p for cancelling", wwIrp);
7759 
7760             result = irp.Cancel();
7761 
7762             DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGPNP,
7763                                 "Cancel of irp %p returned %d", wwIrp, result);
7764 
7765 
7766             if (m_PowerPolicyMachine.CanCompleteWaitWakeIrp()) {
7767                 CompletePowerRequest(&irp, irp.GetStatus());
7768             }
7769             else {
7770                 //
7771                 // Irp has been completed by the lower bus driver, that's OK
7772                 // because the completion of the request will trigger the
7773                 // same transition
7774                 //
7775                 DO_NOTHING();
7776             }
7777 
7778             cancelled = TRUE;
7779         }
7780         else {
7781             DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGPNP,
7782                                 "No WaitWake irp to cancel");
7783 
7784             cancelled = FALSE;
7785         }
7786     }
7787 
7788     return cancelled;
7789 }
7790 
7791 __drv_sameIRQL
7792 NTSTATUS
7793 FxPkgPnp::_PowerPolicyWaitWakeCompletionRoutine(
7794     __in MdDeviceObject DeviceObject,
7795     __in MdIrp OriginalIrp,
7796     __in_xcount_opt("varies") PVOID Context
7797     )
7798 {
7799     FxIrp originalIrp(OriginalIrp);
7800     MdIrp pOldIrp;
7801     FxPkgPnp *pThis;
7802     NTSTATUS status;
7803 
7804     pThis = (FxPkgPnp*) Context;
7805 
7806     if (originalIrp.PendingReturned()) {
7807         originalIrp.MarkIrpPending();
7808     }
7809 
7810     DoTraceLevelMessage(pThis->GetDriverGlobals(),
7811                         TRACE_LEVEL_INFORMATION, TRACINGPNP,
7812                         "WDFDEVICE %p !devobj %p Completion of WaitWake irp %p,"
7813                         " %!STATUS!", pThis->m_Device->GetHandle(),
7814                         DeviceObject, originalIrp.GetIrp(),
7815                         originalIrp.GetStatus());
7816 
7817     if (NT_SUCCESS(originalIrp.GetStatus())) {
7818 
7819         //
7820         // Check to see if this device caused the machine to wake up
7821         //
7822         pThis->PowerPolicyUpdateSystemWakeSource(&originalIrp);
7823     }
7824 
7825     if (pThis->m_SystemWokenByWakeInterrupt) {
7826         //
7827         // If the system was woken by a wake interrupt, we need to mark this
7828         // device as the wake source. Since we typically cancel the wait
7829         // wake IRP in this path, it is expected that the completion
7830         // status will not be success. We need to change this status code to
7831         // success because power manager ignores the wake source information
7832         // reported by a wait wake IRP that is not completed successfully.
7833         //
7834         pThis->_PowerSetSystemWakeSource(&originalIrp);
7835         originalIrp.SetStatus(STATUS_SUCCESS);
7836     }
7837 
7838     //
7839     // Attempt to gain exclusive ownership of the irp from the cancel call site.
7840     // If we do (indicated by the exchange returning a non-NULL pointer), we can
7841     // complete the request w/out worrying about the cancel call site.
7842     //
7843     // If we can't, we must check to see if we can complete the wait wake irp
7844     // (the cancel call site at least has the irp pointer value and has called
7845     // IoCancelIrp on it).
7846     //
7847     pOldIrp = (MdIrp) InterlockedExchangePointer(
7848         (PVOID*)&pThis->m_SharedPower.m_WaitWakeIrp, NULL);
7849 
7850     ASSERT(pOldIrp == NULL || pOldIrp == originalIrp.GetIrp());
7851 
7852     if (pOldIrp != NULL ||
7853         pThis->m_PowerPolicyMachine.CanCompleteWaitWakeIrp()) {
7854         DoTraceLevelMessage(pThis->GetDriverGlobals(),
7855                             TRACE_LEVEL_VERBOSE, TRACINGPNP,
7856                             "Completion of WaitWake irp %p",
7857                             originalIrp.GetIrp());
7858 
7859         originalIrp.StartNextPowerIrp();
7860 
7861         status = STATUS_CONTINUE_COMPLETION;
7862 
7863         Mx::MxReleaseRemoveLock(
7864             &FxDevice::_GetFxWdmExtension(
7865                 DeviceObject)->IoRemoveLock,
7866             originalIrp.GetIrp()
7867             );
7868     }
7869     else {
7870         //
7871         // ************ WARNING *************
7872         // By this time the IRP may have got completed by cancel call site, so
7873         // don't touch irp *members* in this path (it is ok to use the IRP
7874         // address though as in the log below).
7875         //
7876         DoTraceLevelMessage(
7877             pThis->GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGPNP,
7878             "Not completing WaitWake irp %p in completion routine",
7879             originalIrp.GetIrp());
7880 
7881         status = STATUS_MORE_PROCESSING_REQUIRED;
7882     }
7883 
7884     return status;
7885 }
7886 
7887 __drv_sameIRQL
7888 NTSTATUS
7889 FxPkgPnp::_PowerPolicyUsbSelectiveSuspendCompletionRoutine(
7890     __in MdDeviceObject DeviceObject,
7891     __in MdIrp Irp,
7892     __in_xcount_opt("varies") PVOID Context
7893     )
7894 {
7895     FxPkgPnp* This;
7896     FxIrp irp(Irp);
7897 
7898     UNREFERENCED_PARAMETER(DeviceObject);
7899 
7900     This = (FxPkgPnp*) Context;
7901 
7902     //
7903     // Parameters DeviceObejct and Irp are always set to NULL in UMDF, so
7904     // don't touch these in UMDF trace
7905     //
7906 #if FX_IS_KERNEL_MODE
7907     DoTraceLevelMessage(This->GetDriverGlobals(),
7908         TRACE_LEVEL_INFORMATION, TRACINGPNP,
7909         "WDFDEVICE %p, !devobj %p Completion of UsbSS irp %p, %!STATUS!",
7910         This->m_Device, This->m_Device->GetDeviceObject(),
7911         irp.GetIrp(), irp.GetStatus());
7912 
7913 #elif FX_IS_USER_MODE
7914     UNREFERENCED_PARAMETER(irp);
7915 
7916     DoTraceLevelMessage(This->GetDriverGlobals(),
7917         TRACE_LEVEL_INFORMATION, TRACINGPNP,
7918         "WDFDEVICE %p, !devobj %p Completion of UsbSS irp",
7919         This->m_Device, This->m_Device->GetDeviceObject());
7920 #endif
7921 
7922     //
7923     // Post an event indicating that the irp has been completed
7924     //
7925     This->PowerPolicyProcessEvent(
7926         PwrPolUsbSelectiveSuspendCompleted
7927         );
7928 
7929     return STATUS_MORE_PROCESSING_REQUIRED;
7930 }
7931 
7932 BOOLEAN
PowerPolicyCanIdlePowerDown(__in DEVICE_POWER_STATE DxState)7933 FxPkgPnp::PowerPolicyCanIdlePowerDown(
7934     __in DEVICE_POWER_STATE DxState
7935     )
7936 /*++
7937 
7938 Routine Description:
7939     Attempts to send a Dx irp down the stack after this device has idled out.
7940     Before the Dx can be set, we must check that no child devices have attempted
7941     to power up in between the idle timer firing and the state machine
7942     processing the event.  After we have determined that no children are in
7943     D0, we setup a guard so that any child which attempts to power up after this
7944     point will pend the power up until this device has either powered all the
7945     way down and back up or could not allocate a device power irp
7946 
7947 Arguments:
7948     DxState - the destination device state
7949 
7950 Return Value:
7951     TRUE if the device power irp was sent, FALSE otherwise
7952 
7953   --*/
7954 {
7955     BOOLEAN powerDown;
7956 
7957     //
7958     // If we potentially have children, make sure that they are all in Dx before
7959     // the parent powers down.
7960     //
7961     if (m_EnumInfo != NULL) {
7962         m_EnumInfo->AcquireParentPowerStateLock(GetDriverGlobals());
7963         if (m_PowerPolicyMachine.m_Owner->m_ChildrenPoweredOnCount == 0) {
7964             //
7965             // Setup a guard so that no children power up until we either fail
7966             // this power down or power all the way down and back up.
7967             //
7968             m_PowerPolicyMachine.m_Owner->m_ChildrenCanPowerUp = FALSE;
7969             powerDown = TRUE;
7970         }
7971         else {
7972             DoTraceLevelMessage(
7973                 GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGPNP,
7974                 "WDFDEVICE %p !devobj 0x%p not idling out because there are %d "
7975                 "children who are powered up", m_Device->GetHandle(),
7976                 m_Device->GetDeviceObject(),
7977                 m_PowerPolicyMachine.m_Owner->m_ChildrenPoweredOnCount);
7978             powerDown = FALSE;
7979         }
7980         m_EnumInfo->ReleaseParentPowerStateLock(GetDriverGlobals());
7981     }
7982     else {
7983         powerDown = TRUE;
7984     }
7985 
7986     if (powerDown) {
7987         NTSTATUS status;
7988 
7989         status = PowerPolicySendDevicePowerRequest(DxState, NoRetry);
7990 
7991         if (!NT_SUCCESS(status)) {
7992             //
7993             // This will set m_ChildrenCanPowerUp to TRUE and send a
7994             // ParentMovesToD0 in case any children powered down in between
7995             // determining if the parent can go idle and failing to do so.
7996             //
7997             PowerPolicyChildrenCanPowerUp();
7998 
7999             powerDown = FALSE;
8000         }
8001     }
8002 
8003     return powerDown;
8004 }
8005 
8006 VOID
PowerPolicyPostParentToD0ToChildren(VOID)8007 FxPkgPnp::PowerPolicyPostParentToD0ToChildren(
8008     VOID
8009     )
8010 /*++
8011 
8012 Routine Description:
8013     Indicates to all of the children that the parent is in D0
8014 
8015 Arguments:
8016     None
8017 
8018 Return Value:
8019     None.
8020 
8021   --*/
8022 {
8023     FxTransactionedEntry* ple;
8024 
8025     ASSERT(IsPowerPolicyOwner());
8026 
8027     if (m_EnumInfo != NULL) {
8028         m_EnumInfo->m_ChildListList.LockForEnum(GetDriverGlobals());
8029 
8030         ple = NULL;
8031         while ((ple = m_EnumInfo->m_ChildListList.GetNextEntry(ple)) != NULL) {
8032             ((FxChildList*) ple->GetTransactionedObject())->PostParentToD0();
8033         }
8034 
8035         m_EnumInfo->m_ChildListList.UnlockFromEnum(GetDriverGlobals());
8036     }
8037 }
8038 
8039 VOID
PowerPolicyChildrenCanPowerUp(VOID)8040 FxPkgPnp::PowerPolicyChildrenCanPowerUp(
8041     VOID
8042     )
8043 /*++
8044 
8045 Routine Description:
8046     After this function returns, any child devices rooted off of this parent
8047     device can now move into D0.
8048 
8049 Arguments:
8050     None
8051 
8052 Return Value:
8053     None
8054 
8055   --*/
8056 {
8057     //
8058     // This can be called for any PPO so we must check first if we have any
8059     // possibility of children.
8060     //
8061     if (m_EnumInfo == NULL) {
8062         return;
8063     }
8064 
8065     if (IsPowerPolicyOwner()) {
8066         m_EnumInfo->AcquireParentPowerStateLock(GetDriverGlobals());
8067 
8068         //
8069         // When the child attempts to power up, m_ChildrenPoweredOnCount can
8070         // be incremented while the parent is in Dx. The important value
8071         // here is the guard value, m_ChildrenCanPowerUp which must be
8072         // FALSE.
8073         //
8074         // ASSERT (m_PowerPolicyMachine.m_Owner->m_ChildrenPoweredOnCount == 0);
8075 
8076         //
8077         // In the USB SS case, we can return to StartingDecideS0Wake without
8078         // ever attempting to go into a Dx state state, so m_ChildrenCanPowerUp
8079         // can be TRUE.
8080         //
8081         // ASSERT(m_PowerPolicyMachine.m_Owner->m_ChildrenCanPowerUp == FALSE);
8082 
8083         m_PowerPolicyMachine.m_Owner->m_ChildrenCanPowerUp = TRUE;
8084         m_EnumInfo->ReleaseParentPowerStateLock(GetDriverGlobals());
8085 
8086         //
8087         // Now that we have set the state of the parent, any child which checks
8088         // the power state after we have released the lock will be able to
8089         // power up immediately.  We now need to unblock all children which
8090         // checked the parent state before this function was called by posting
8091         // a PowerParentToD0 event to each child (regardless of the PDO device
8092         // power state).
8093         //
8094         PowerPolicyPostParentToD0ToChildren();
8095     }
8096     else {
8097         //
8098         // Since we are not the power policy owner for the parent device,
8099         // we cannot make any guarantees about the child being in D0 while
8100         // the parent is in D0 so we do not call PowerPostParentToD0ToChildren().
8101         // Additionally in PowerPolicyCanChildPowerUp(), if the parent (this)
8102         // device is not the PPO, we don't even check the parent D state before
8103         // powering up the child.
8104         //
8105         DO_NOTHING();
8106     }
8107 }
8108 
8109 VOID
8110 __inline
PowerPolicyDisarmWakeFromSx(VOID)8111 FxPkgPnp::PowerPolicyDisarmWakeFromSx(
8112     VOID
8113     )
8114 /*++
8115 
8116 Routine Description:
8117     Calls into the client driver to disarm itself from wake and the clears the
8118     flag which indicates that the device is a source of system wake.  The disarm
8119     callback is the last callback available to the driver to indicate the wake
8120     status of its children and have the wake status propagate upwards to the
8121     PDO's stack.
8122 
8123   --*/
8124 {
8125     NTSTATUS wwStatus;
8126     FxTransactionedEntry* ple;
8127 
8128     m_PowerPolicyMachine.m_Owner->m_DeviceDisarmWakeFromSx.Invoke(
8129         m_Device->GetHandle()
8130         );
8131 
8132     wwStatus = m_PowerPolicyMachine.m_Owner->m_WaitWakeStatus;
8133 
8134     if (wwStatus != STATUS_CANCELLED &&
8135         m_EnumInfo != NULL &&
8136         PowerPolicyShouldPropagateWakeStatusToChildren()) {
8137         m_EnumInfo->m_ChildListList.LockForEnum(GetDriverGlobals());
8138 
8139         ple = NULL;
8140         while ((ple = m_EnumInfo->m_ChildListList.GetNextEntry(ple)) != NULL) {
8141             ((FxChildList*) ple->GetTransactionedObject())->
8142                 IndicateWakeStatus(wwStatus);
8143         }
8144 
8145         m_EnumInfo->m_ChildListList.UnlockFromEnum(GetDriverGlobals());
8146     }
8147 
8148     m_PowerPolicyMachine.m_Owner->m_WaitWakeStatus = STATUS_NOT_SUPPORTED;
8149 
8150     //
8151     // Always set the wake source back to FALSE regardless of it previous value.
8152     //
8153     m_PowerPolicyMachine.m_Owner->m_SystemWakeSource = FALSE;
8154 }
8155 
8156 WDF_DEVICE_POWER_POLICY_STATE
PowerPolWaitingArmedStoppingCancelUsbSS(__inout FxPkgPnp * This)8157 FxPkgPnp::PowerPolWaitingArmedStoppingCancelUsbSS(
8158     __inout FxPkgPnp* This
8159     )
8160 /*++
8161 
8162 Routine Description:
8163     The device is in Dx and surprise removed. Cancel the idle notification so
8164     we can move to another state
8165 
8166 Arguments:
8167     This - instance of the state machine
8168 
8169 Return Value:
8170     WdfDevStatePwrPolStoppingCancelWake
8171 
8172   --*/
8173 {
8174     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolWaitingArmedStoppingCancelUsbSS);
8175 
8176     This->m_PowerPolicyMachine.m_Owner->m_PowerIdleMachine.DisableTimer();
8177 
8178     //
8179     // Since we are in Dx and surprise removed, cancel the usb SS irp if it is
8180     // there.  Otherwise, the USB PDO will call us back after we have processed
8181     // remove.
8182     //
8183     if (This->PowerPolicyCancelUsbSSIfCapable()) {
8184         //
8185         // Usbss completion event will move us from this state.
8186         //
8187         return WdfDevStatePwrPolNull;
8188     }
8189 
8190     //
8191     // If usbss irp was there it has already been canceled, so march on.
8192     //
8193     return WdfDevStatePwrPolStoppingCancelWake;
8194 }
8195 
8196 WDF_DEVICE_POWER_POLICY_STATE
PowerPolWaitingArmedWakeFailedCancelUsbSS(__inout FxPkgPnp * This)8197 FxPkgPnp::PowerPolWaitingArmedWakeFailedCancelUsbSS(
8198     __inout FxPkgPnp* This
8199     )
8200 /*++
8201 
8202 Routine Description:
8203     The device is in Dx armed for wake and wait wake irp got failed.
8204     Cancel the idle notification so we can move to another state
8205 
8206 Arguments:
8207     This - instance of the state machine
8208 
8209 Return Value:
8210     WdfDevStatePwrPolIoPresentArmedWakeCanceled
8211 
8212   --*/
8213 {
8214     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolWaitingArmedWakeFailedCancelUsbSS);
8215 
8216     if (This->PowerPolicyCancelUsbSSIfCapable()) {
8217         //
8218         // Usbss completion event will move us from this state.
8219         //
8220         return WdfDevStatePwrPolNull;
8221     }
8222 
8223     //
8224     // If usbss irp was there it has already been canceled, so march on.
8225     //
8226     return WdfDevStatePwrPolIoPresentArmedWakeCanceled;
8227 }
8228 
8229 WDF_DEVICE_POWER_POLICY_STATE
PowerPolWaitingArmedIoPresentCancelUsbSS(__inout FxPkgPnp * This)8230 FxPkgPnp::PowerPolWaitingArmedIoPresentCancelUsbSS(
8231     __inout FxPkgPnp* This
8232     )
8233 /*++
8234 
8235 Routine Description:
8236     The device is in Dx armed for wake.
8237     Cancel the idle notification so we can move to another state
8238 
8239 Arguments:
8240     This - instance of the state machine
8241 
8242 Return Value:
8243     WdfDevStatePwrPolIoPresentArmed
8244 
8245   --*/
8246 {
8247     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolWaitingArmedIoPresentCancelUsbSS);
8248 
8249     if (This->PowerPolicyCancelUsbSSIfCapable()) {
8250         //
8251         // Usbss completion event will move us from this state.
8252         //
8253         return WdfDevStatePwrPolNull;
8254     }
8255 
8256     //
8257     // If usbss irp was there it has already been canceled, so march on.
8258     //
8259     return WdfDevStatePwrPolIoPresentArmed;
8260 }
8261 
8262 WDF_DEVICE_POWER_POLICY_STATE
PowerPolWaitingArmedWakeSucceededCancelUsbSS(__inout FxPkgPnp * This)8263 FxPkgPnp::PowerPolWaitingArmedWakeSucceededCancelUsbSS(
8264     __inout FxPkgPnp* This
8265     )
8266 /*++
8267 
8268 Routine Description:
8269     The device woke from S0.
8270     Cancel the idle notification so we can move to another state
8271 
8272 Arguments:
8273     This - instance of the state machine
8274 
8275 Return Value:
8276     WdfDevStatePwrPolWokeFromS0
8277 
8278   --*/
8279 {
8280     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolWaitingArmedWakeSucceededCancelUsbSS);
8281 
8282     if (This->PowerPolicyCancelUsbSSIfCapable()) {
8283         //
8284         // Usbss completion event will move us from this state.
8285         //
8286         return WdfDevStatePwrPolNull;
8287     }
8288 
8289     //
8290     // If usbss irp was there it has already been canceled, so march on.
8291     //
8292     return WdfDevStatePwrPolWokeFromS0;
8293 }
8294 
8295 WDF_DEVICE_POWER_POLICY_STATE
PowerPolCancelingUsbSSForSystemSleep(__inout FxPkgPnp * This)8296 FxPkgPnp::PowerPolCancelingUsbSSForSystemSleep(
8297     __inout FxPkgPnp* This
8298     )
8299 /*++
8300 
8301 Routine Description:
8302     The system is going to sleep..
8303     Cancel the idle notification so we can move to another state
8304 
8305 Arguments:
8306     This - instance of the state machine
8307 
8308 Return Value:
8309     WdfDevStatePwrPolCancelingWakeForSystemSleep
8310 
8311   --*/
8312 {
8313     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolCancelingUsbSSForSystemSleep);
8314 
8315     if (This->PowerPolicyCancelUsbSSIfCapable()) {
8316         //
8317         // Usbss completion event will move us from this state.
8318         //
8319         return WdfDevStatePwrPolNull;
8320     }
8321 
8322     //
8323     // If usbss irp was there it has already been canceled, so march on.
8324     //
8325     return WdfDevStatePwrPolCancelingWakeForSystemSleep;
8326 }
8327 
8328 WDF_DEVICE_POWER_POLICY_STATE
PowerPolStoppingD0CancelUsbSS(__inout FxPkgPnp * This)8329 FxPkgPnp::PowerPolStoppingD0CancelUsbSS(
8330     __inout FxPkgPnp* This
8331     )
8332 /*++
8333 
8334 Routine Description:
8335     Cancel the idle notification so we can move to another state
8336 
8337 Arguments:
8338     This - instance of the state machine
8339 
8340 Return Value:
8341     WdfDevStatePwrPolStoppingD0
8342 
8343   --*/
8344 {
8345     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolStoppingD0CancelUsbSS);
8346 
8347     if (This->PowerPolicyCancelUsbSSIfCapable()) {
8348         //
8349         // Usbss completion event will move us from this state.
8350         //
8351         return WdfDevStatePwrPolNull;
8352     }
8353 
8354     //
8355     // If usbss irp was there it has already been canceled, so march on.
8356     //
8357     return WdfDevStatePwrPolStoppingD0;
8358 }
8359 
8360 BOOLEAN
PowerPolicyCancelUsbSSIfCapable(VOID)8361 FxPkgPnp::PowerPolicyCancelUsbSSIfCapable(
8362     VOID
8363     )
8364 /*++
8365 
8366 Routine Description:
8367     Cancel the idle notification irp if capable
8368 
8369 Arguments:
8370     none
8371 
8372 Return Value:
8373     TRUE if irp was canceled
8374     FALSE if not capable of USBSS or if Irp was already completed.
8375 
8376   --*/
8377 {
8378     if (m_PowerPolicyMachine.m_Owner->m_UsbIdle == NULL ||
8379         m_PowerPolicyMachine.m_Owner->m_UsbIdle->m_EventDropped) {
8380         return FALSE;
8381     }
8382     else {
8383         PowerPolicyCancelUsbSS();
8384         return TRUE;
8385     }
8386 }
8387 
8388 WDF_DEVICE_POWER_POLICY_STATE
PowerPolTimerExpiredWakeCapableWakeInterruptArrived(__inout FxPkgPnp * This)8389 FxPkgPnp::PowerPolTimerExpiredWakeCapableWakeInterruptArrived(
8390     __inout FxPkgPnp* This
8391     )
8392 {
8393     ASSERT_PWR_POL_STATE(This, WdfDevStatePwrPolTimerExpiredWakeCapableWakeInterruptArrived);
8394 
8395     if (This->PowerPolicyCancelWaitWake() == FALSE &&
8396         This->m_PowerPolicyMachine.m_Owner->m_WakeCompletionEventDropped) {
8397         return WdfDevStatePwrPolTimerExpiredWakeCapableWakeSucceeded;
8398     }
8399 
8400     return WdfDevStatePwrPolNull;
8401 }
8402 
8403 
8404