1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 NotPowerPolicyOwnerStateMachine.cpp
8
9 Abstract:
10
11 This module implements the Not Power Policy Owner state machine for the driver
12 framework. This code was split out from PowerPolicyStateMachine.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 extern "C" {
32 #if defined(EVENT_TRACING)
33 #include "NotPowerPolicyOwnerStateMachine.tmh"
34 #endif
35 }
36
37 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_NotPowerPolOwnerObjectCreatedStates[] =
38 {
39 { PwrPolStart, WdfDevStatePwrPolStarting DEBUGGED_EVENT },
40 { PwrPolRemove, WdfDevStatePwrPolRemoved DEBUGGED_EVENT },
41 };
42
43 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_NotPowerPolOwnerStartingStates[] =
44 {
45 { PwrPolPowerUp, WdfDevStatePwrPolStarted DEBUGGED_EVENT },
46 { PwrPolPowerUpFailed, WdfDevStatePwrPolStartingFailed DEBUGGED_EVENT },
47 };
48
49 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_NotPowerPolOwnerStartingSucceededStates[] =
50 {
51 { PwrPolPowerDownIoStopped, WdfDevStatePwrPolGotoDx DEBUGGED_EVENT },
52 { PwrPolStop, WdfDevStatePwrPolStopping DEBUGGED_EVENT },
53 { PwrPolSurpriseRemove, WdfDevStatePwrPolStopping DEBUGGED_EVENT },
54 { PwrPolPowerUpHwStarted, WdfDevStatePwrPolGotoD0InD0 TRAP_ON_EVENT },
55 };
56
57 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_NotPowerPolOwnerStartingFailedStates[] =
58 {
59 { PwrPolRemove, WdfDevStatePwrPolRemoved DEBUGGED_EVENT },
60 };
61
62 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_NotPowerPolOwnerGotoDxStates[] =
63 {
64 { PwrPolPowerDown, WdfDevStatePwrPolDx DEBUGGED_EVENT },
65 { PwrPolPowerDownFailed, WdfDevStatePwrPolStartingSucceeded DEBUGGED_EVENT },
66 };
67
68 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_NotPowerPolOwnerGotoDxInDxStates[] =
69 {
70 { PwrPolPowerDown, WdfDevStatePwrPolDx TRAP_ON_EVENT },
71 { PwrPolPowerDownFailed, WdfDevStatePwrPolDx TRAP_ON_EVENT },
72 };
73
74 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_NotPowerPolOwnerDxStates[] =
75 {
76 { PwrPolPowerUpHwStarted, WdfDevStatePwrPolGotoD0 DEBUGGED_EVENT },
77 { PwrPolStop, WdfDevStatePwrPolStopping DEBUGGED_EVENT },
78 { PwrPolSurpriseRemove, WdfDevStatePwrPolStopping DEBUGGED_EVENT },
79 { PwrPolPowerDownIoStopped, WdfDevStatePwrPolGotoDxInDx TRAP_ON_EVENT },
80 };
81
82 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_NotPowerPolOwnerGotoD0States[] =
83 {
84 { PwrPolPowerUp, WdfDevStatePwrPolStartingSucceeded DEBUGGED_EVENT },
85 { PwrPolPowerUpFailed, WdfDevStatePwrPolStartingSucceeded TRAP_ON_EVENT },
86 };
87
88 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_NotPowerPolOwnerGotoD0InD0States[] =
89 {
90 { PwrPolPowerUp, WdfDevStatePwrPolStartingSucceeded TRAP_ON_EVENT },
91 { PwrPolPowerUpFailed, WdfDevStatePwrPolStartingSucceeded TRAP_ON_EVENT },
92 };
93
94 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_NotPowerPolOwnerStoppedStates[] =
95 {
96 { PwrPolStart, WdfDevStatePwrPolStarting DEBUGGED_EVENT },
97 { PwrPolRemove, WdfDevStatePwrPolRemoved DEBUGGED_EVENT },
98 };
99
100 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_NotPowerPolOwnerStoppingWaitForImplicitPowerDownStates[] =
101 {
102 { PwrPolImplicitPowerDown, WdfDevStatePwrPolStoppingSendStatus DEBUGGED_EVENT },
103 { PwrPolImplicitPowerDownFailed, WdfDevStatePwrPolStoppingFailed DEBUGGED_EVENT },
104 { PwrPolPowerDownIoStopped, WdfDevStatePwrPolStoppingPoweringDown DEBUGGED_EVENT },
105 { PwrPolPowerUpHwStarted, WdfDevStatePwrPolStoppingPoweringUp DEBUGGED_EVENT },
106 };
107
108 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_NotPowerPolOwnerStoppingPoweringUpStates[] =
109 {
110 { PwrPolPowerUp, WdfDevStatePwrPolStoppingWaitingForImplicitPowerDown DEBUGGED_EVENT },
111 { PwrPolPowerUpFailed, WdfDevStatePwrPolStoppingWaitingForImplicitPowerDown TRAP_ON_EVENT },
112 };
113
114 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_NotPowerPolOwnerStoppingPoweringDownStates[] =
115 {
116 { PwrPolPowerDown, WdfDevStatePwrPolStoppingWaitingForImplicitPowerDown DEBUGGED_EVENT },
117 { PwrPolPowerDownFailed, WdfDevStatePwrPolStoppingWaitingForImplicitPowerDown DEBUGGED_EVENT },
118 };
119
120 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_NotPowerPolOwnerRemovedStates[] =
121 {
122 { PwrPolStart, WdfDevStatePwrPolStarting DEBUGGED_EVENT },
123 { PwrPolRemove, WdfDevStatePwrPolRemoved DEBUGGED_EVENT },
124 };
125
126 const NOT_POWER_POLICY_OWNER_STATE_TABLE FxPkgPnp::m_WdfNotPowerPolicyOwnerStates[] =
127 {
128 // current state
129 // transition function,
130 // target states
131 // count of target states
132 // Queue state
133 //
134 { WdfDevStatePwrPolObjectCreated,
135 NULL,
136 FxPkgPnp::m_NotPowerPolOwnerObjectCreatedStates,
137 ARRAY_SIZE(FxPkgPnp::m_NotPowerPolOwnerObjectCreatedStates),
138 TRUE,
139 },
140
141 { WdfDevStatePwrPolStarting,
142 FxPkgPnp::NotPowerPolOwnerStarting,
143 FxPkgPnp::m_NotPowerPolOwnerStartingStates,
144 ARRAY_SIZE(FxPkgPnp::m_NotPowerPolOwnerStartingStates),
145 FALSE,
146 },
147
148 { WdfDevStatePwrPolStarted,
149 FxPkgPnp::NotPowerPolOwnerStarted,
150 NULL,
151 0,
152 FALSE,
153 },
154
155 { WdfDevStatePwrPolStartingSucceeded,
156 NULL,
157 FxPkgPnp::m_NotPowerPolOwnerStartingSucceededStates,
158 ARRAY_SIZE(FxPkgPnp::m_NotPowerPolOwnerStartingSucceededStates),
159 TRUE,
160 },
161
162 { WdfDevStatePwrPolGotoDx,
163 FxPkgPnp::NotPowerPolOwnerGotoDx,
164 FxPkgPnp::m_NotPowerPolOwnerGotoDxStates,
165 ARRAY_SIZE(FxPkgPnp::m_NotPowerPolOwnerGotoDxStates),
166 FALSE,
167 },
168
169 { WdfDevStatePwrPolGotoDxInDx,
170 FxPkgPnp::NotPowerPolOwnerGotoDxInDx,
171 FxPkgPnp::m_NotPowerPolOwnerGotoDxInDxStates,
172 ARRAY_SIZE(FxPkgPnp::m_NotPowerPolOwnerGotoDxInDxStates),
173 FALSE,
174 },
175
176 { WdfDevStatePwrPolDx,
177 NULL,
178 FxPkgPnp::m_NotPowerPolOwnerDxStates,
179 ARRAY_SIZE(FxPkgPnp::m_NotPowerPolOwnerDxStates),
180 TRUE,
181 },
182
183 { WdfDevStatePwrPolGotoD0,
184 FxPkgPnp::NotPowerPolOwnerGotoD0,
185 FxPkgPnp::m_NotPowerPolOwnerGotoD0States,
186 ARRAY_SIZE(FxPkgPnp::m_NotPowerPolOwnerGotoD0States),
187 FALSE,
188 },
189
190 { WdfDevStatePwrPolGotoD0InD0,
191 FxPkgPnp::NotPowerPolOwnerGotoD0InD0,
192 FxPkgPnp::m_NotPowerPolOwnerGotoD0InD0States,
193 ARRAY_SIZE(FxPkgPnp::m_NotPowerPolOwnerGotoD0InD0States),
194 FALSE,
195 },
196
197 { WdfDevStatePwrPolStopping,
198 FxPkgPnp::NotPowerPolOwnerStopping,
199 NULL,
200 0,
201 FALSE,
202 },
203
204 { WdfDevStatePwrPolStoppingSendStatus,
205 FxPkgPnp::NotPowerPolOwnerStoppingSendStatus,
206 NULL,
207 0,
208 FALSE,
209 },
210
211 { WdfDevStatePwrPolStartingFailed,
212 FxPkgPnp::NotPowerPolOwnerStartingFailed,
213 FxPkgPnp::m_NotPowerPolOwnerStartingFailedStates,
214 ARRAY_SIZE(FxPkgPnp::m_NotPowerPolOwnerStartingFailedStates),
215 TRUE,
216 },
217
218 { WdfDevStatePwrPolStoppingFailed,
219 FxPkgPnp::NotPowerPolOwnerStoppingFailed,
220 NULL,
221 0,
222 FALSE,
223 },
224
225 { WdfDevStatePwrPolStopped,
226 NULL,
227 FxPkgPnp::m_NotPowerPolOwnerStoppedStates,
228 ARRAY_SIZE(FxPkgPnp::m_NotPowerPolOwnerStoppedStates),
229 TRUE,
230 },
231
232 { WdfDevStatePwrPolStoppingWaitingForImplicitPowerDown,
233 NULL,
234 FxPkgPnp::m_NotPowerPolOwnerStoppingWaitForImplicitPowerDownStates,
235 ARRAY_SIZE(FxPkgPnp::m_NotPowerPolOwnerStoppingWaitForImplicitPowerDownStates),
236 TRUE,
237 },
238
239 { WdfDevStatePwrPolStoppingPoweringUp,
240 FxPkgPnp::NotPowerPolOwnerStoppingPoweringUp,
241 FxPkgPnp::m_NotPowerPolOwnerStoppingPoweringUpStates,
242 ARRAY_SIZE(FxPkgPnp::m_NotPowerPolOwnerStoppingPoweringUpStates),
243 FALSE,
244 },
245
246 { WdfDevStatePwrPolStoppingPoweringDown,
247 FxPkgPnp::NotPowerPolOwnerStoppingPoweringDown,
248 FxPkgPnp::m_NotPowerPolOwnerStoppingPoweringDownStates,
249 ARRAY_SIZE(FxPkgPnp::m_NotPowerPolOwnerStoppingPoweringDownStates),
250 FALSE,
251 },
252
253 { WdfDevStatePwrPolRemoved,
254 FxPkgPnp::NotPowerPolOwnerRemoved,
255 FxPkgPnp::m_NotPowerPolOwnerRemovedStates,
256 ARRAY_SIZE(FxPkgPnp::m_NotPowerPolOwnerRemovedStates),
257 TRUE,
258 },
259
260 // the last entry must have WdfDevStatePwrPolNull as the current state
261 { WdfDevStatePwrPolNull,
262 NULL,
263 NULL,
264 0,
265 FALSE,
266 },
267 };
268
269 VOID
NotPowerPolicyOwnerEnterNewState(__in WDF_DEVICE_POWER_POLICY_STATE NewState)270 FxPkgPnp::NotPowerPolicyOwnerEnterNewState(
271 __in WDF_DEVICE_POWER_POLICY_STATE NewState
272 )
273 {
274 CPNOT_POWER_POLICY_OWNER_STATE_TABLE entry;
275 WDF_DEVICE_POWER_POLICY_STATE currentState, newState;
276 WDF_DEVICE_POWER_POLICY_NOTIFICATION_DATA data;
277
278 currentState = m_Device->GetDevicePowerPolicyState();
279 newState = NewState;
280
281 while (newState != WdfDevStatePwrPolNull) {
282 DoTraceLevelMessage(
283 GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGPNPPOWERSTATES,
284 "WDFDEVICE 0x%p !devobj 0x%p entering not power policy owner state "
285 "%!WDF_DEVICE_POWER_POLICY_STATE! from "
286 "%!WDF_DEVICE_POWER_POLICY_STATE!", m_Device->GetHandle(),
287 m_Device->GetDeviceObject(), newState, currentState);
288
289 if (m_PowerPolicyStateCallbacks != NULL) {
290 //
291 // Callback for leaving the old state
292 //
293 RtlZeroMemory(&data, sizeof(data));
294
295 data.Type = StateNotificationLeaveState;
296 data.Data.LeaveState.CurrentState = currentState;
297 data.Data.LeaveState.NewState = newState;
298
299 m_PowerPolicyStateCallbacks->Invoke(currentState,
300 StateNotificationLeaveState,
301 m_Device->GetHandle(),
302 &data);
303 }
304
305 m_PowerPolicyMachine.m_States.History[
306 m_PowerPolicyMachine.IncrementHistoryIndex()] = (USHORT) newState;
307
308 if (m_PowerPolicyStateCallbacks != NULL) {
309 //
310 // Callback for entering the new state
311 //
312 RtlZeroMemory(&data, sizeof(data));
313
314 data.Type = StateNotificationEnterState;
315 data.Data.EnterState.CurrentState = currentState;
316 data.Data.EnterState.NewState = newState;
317
318 m_PowerPolicyStateCallbacks->Invoke(newState,
319 StateNotificationEnterState,
320 m_Device->GetHandle(),
321 &data);
322 }
323
324 m_Device->SetDevicePowerPolicyState(newState);
325 currentState = newState;
326
327 entry = GetNotPowerPolicyOwnerTableEntry(currentState);
328
329 //
330 // Call the state handler, if there is one.
331 //
332 if (entry->StateFunc != NULL) {
333 newState = entry->StateFunc(this);
334 }
335 else {
336 newState = WdfDevStatePwrPolNull;
337 }
338
339 if (m_PowerPolicyStateCallbacks != NULL) {
340 //
341 // Callback for post processing the new state
342 //
343 RtlZeroMemory(&data, sizeof(data));
344
345 data.Type = StateNotificationPostProcessState;
346 data.Data.PostProcessState.CurrentState = currentState;
347
348 m_PowerPolicyStateCallbacks->Invoke(currentState,
349 StateNotificationPostProcessState,
350 m_Device->GetHandle(),
351 &data);
352 }
353 }
354 }
355
356 WDF_DEVICE_POWER_POLICY_STATE
NotPowerPolOwnerStarting(__inout FxPkgPnp * This)357 FxPkgPnp::NotPowerPolOwnerStarting(
358 __inout FxPkgPnp* This
359 )
360 /*++
361
362 Routine Description:
363 Starting the power policy state machine for a device which is not the power
364 policy owner. Tell the power state machine to start up.
365
366 Arguments:
367 This - instance of the state machine
368
369 Return Value:
370 WdfDevStatePwrPolNull
371
372 --*/
373 {
374 This->PowerProcessEvent(PowerImplicitD0);
375 return WdfDevStatePwrPolNull;
376 }
377
378 WDF_DEVICE_POWER_POLICY_STATE
NotPowerPolOwnerStarted(__inout FxPkgPnp * This)379 FxPkgPnp::NotPowerPolOwnerStarted(
380 __inout FxPkgPnp* This
381 )
382 /*++
383
384 Routine Description:
385 Starting the power policy state machine for a device which is not the power
386 policy owner has succeeded. Indicate status to the pnp state machine.
387
388 Arguments:
389 This - instance of the state machine
390
391 Return Value:
392 WdfDevStatePwrPolNull
393
394 --*/
395 {
396 This->PnpProcessEvent(PnpEventPwrPolStarted);
397 return WdfDevStatePwrPolStartingSucceeded;
398 }
399
400 WDF_DEVICE_POWER_POLICY_STATE
NotPowerPolOwnerGotoDx(__inout FxPkgPnp * This)401 FxPkgPnp::NotPowerPolOwnerGotoDx(
402 __inout FxPkgPnp* This
403 )
404 {
405 This->PowerProcessEvent(PowerCompleteDx);
406 return WdfDevStatePwrPolNull;
407 }
408
409 WDF_DEVICE_POWER_POLICY_STATE
NotPowerPolOwnerGotoDxInDx(__inout FxPkgPnp * This)410 FxPkgPnp::NotPowerPolOwnerGotoDxInDx(
411 __inout FxPkgPnp* This
412 )
413 {
414 This->PowerProcessEvent(PowerCompleteDx);
415 return WdfDevStatePwrPolNull;
416 }
417
418 WDF_DEVICE_POWER_POLICY_STATE
NotPowerPolOwnerGotoD0(__inout FxPkgPnp * This)419 FxPkgPnp::NotPowerPolOwnerGotoD0(
420 __inout FxPkgPnp* This
421 )
422 {
423 This->PowerProcessEvent(PowerCompleteD0);
424 return WdfDevStatePwrPolNull;
425 }
426
427 WDF_DEVICE_POWER_POLICY_STATE
NotPowerPolOwnerGotoD0InD0(__inout FxPkgPnp * This)428 FxPkgPnp::NotPowerPolOwnerGotoD0InD0(
429 __inout FxPkgPnp* This
430 )
431 {
432 This->PowerProcessEvent(PowerCompleteD0);
433 return WdfDevStatePwrPolNull;
434 }
435
436 WDF_DEVICE_POWER_POLICY_STATE
NotPowerPolOwnerStopping(__inout FxPkgPnp * This)437 FxPkgPnp::NotPowerPolOwnerStopping(
438 __inout FxPkgPnp* This
439 )
440 /*++
441
442 Routine Description:
443 Stopping the power policy state machine for a device which is not the power
444 policy owner. Tell the power state machine to power down.
445
446 Arguments:
447 This - instance of the state machine
448
449 Return Value:
450 WdfDevStatePwrPolStoppingWaitingForImplicitPowerDown
451
452 --*/
453 {
454 This->PowerProcessEvent(PowerImplicitD3);
455 return WdfDevStatePwrPolStoppingWaitingForImplicitPowerDown;
456 }
457
458 WDF_DEVICE_POWER_POLICY_STATE
NotPowerPolOwnerStoppingSendStatus(__inout FxPkgPnp * This)459 FxPkgPnp::NotPowerPolOwnerStoppingSendStatus(
460 __inout FxPkgPnp* This
461 )
462 /*++
463
464 Routine Description:
465 Stopping the power policy state machine for a device which is not the power
466 policy owner has succeeded. Inidcate status to the pnp state machine.
467
468 Arguments:
469 This - instance of the state machine
470
471 Return Value:
472 WdfDevStatePwrPolStopped
473
474 --*/
475 {
476 This->PnpProcessEvent(PnpEventPwrPolStopped);
477 return WdfDevStatePwrPolStopped;
478 }
479
480 WDF_DEVICE_POWER_POLICY_STATE
NotPowerPolOwnerStartingFailed(__inout FxPkgPnp * This)481 FxPkgPnp::NotPowerPolOwnerStartingFailed(
482 __inout FxPkgPnp* This
483 )
484 /*++
485
486 Routine Description:
487 Starting the power policy state machine for a device which is not the power
488 policy owner has failed. Inidcate status to the pnp state machine.
489
490 Arguments:
491 This - instance of the state machine
492
493 Return Value:
494 WdfDevStatePwrPolNull
495
496 --*/
497 {
498 This->PnpProcessEvent(PnpEventPwrPolStartFailed);
499 return WdfDevStatePwrPolNull;
500 }
501
502 WDF_DEVICE_POWER_POLICY_STATE
NotPowerPolOwnerStoppingFailed(__inout FxPkgPnp * This)503 FxPkgPnp::NotPowerPolOwnerStoppingFailed(
504 __inout FxPkgPnp* This
505 )
506 /*++
507
508 Routine Description:
509 Stopping the power policy state machine for a device which is not the power
510 policy owner has failed. Inidcate status to the pnp state machine.
511
512 Arguments:
513 This - instance of the state machine
514
515 Return Value:
516 WdfDevStatePwrPolStopped
517
518 --*/
519 {
520 This->PnpProcessEvent(PnpEventPwrPolStopFailed);
521 return WdfDevStatePwrPolStopped;
522 }
523
524 WDF_DEVICE_POWER_POLICY_STATE
NotPowerPolOwnerStoppingPoweringUp(__inout FxPkgPnp * This)525 FxPkgPnp::NotPowerPolOwnerStoppingPoweringUp(
526 __inout FxPkgPnp* This
527 )
528 /*++
529
530 Routine Description:
531 Right as we attempted to implicitly power down, a real D0 irp came into the
532 stack. Complete the D0 irp in the power state machine so that the power
533 state machine can process the implicit power irp
534
535 Arguments:
536 This - instance of the state machine
537
538 Return Value:
539 WdfDevStatePwrPolNull
540
541 --*/
542 {
543 This->PowerProcessEvent(PowerCompleteD0);
544 return WdfDevStatePwrPolNull;
545 }
546
547 WDF_DEVICE_POWER_POLICY_STATE
NotPowerPolOwnerStoppingPoweringDown(__inout FxPkgPnp * This)548 FxPkgPnp::NotPowerPolOwnerStoppingPoweringDown(
549 __inout FxPkgPnp* This
550 )
551 /*++
552
553 Routine Description:
554 Right as we attempted to implicitly power down, a real Dx irp came into the
555 stack. Complete the Dx irp in the power state machine so that the power
556 state machine can process the implicit power irp
557
558 Arguments:
559 This - instance of the state machine
560
561 Return Value:
562 WdfDevStatePwrPolNull
563
564 --*/
565 {
566 This->PowerProcessEvent(PowerCompleteDx);
567 return WdfDevStatePwrPolNull;
568 }
569
570 WDF_DEVICE_POWER_POLICY_STATE
NotPowerPolOwnerRemoved(__inout FxPkgPnp * This)571 FxPkgPnp::NotPowerPolOwnerRemoved(
572 __inout FxPkgPnp* This
573 )
574 /*++
575
576 Routine Description:
577 The device is being removed, so prepare for removal.
578
579 Arguments:
580 This - instance of the state machine
581
582 Return Value:
583 WdfDevStatePwrPolNull
584
585 --*/
586 {
587 //
588 // Since we are not the power policy owner, there is nothing to be done.
589 // Indicate to the PNP state machine that we are ready for removal.
590 //
591 This->PnpProcessEvent(PnpEventPwrPolRemoved);
592 return WdfDevStatePwrPolNull;
593 }
594