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