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
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
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
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
401 FxPkgPnp::NotPowerPolOwnerGotoDx(
402     __inout FxPkgPnp* This
403     )
404 {
405     This->PowerProcessEvent(PowerCompleteDx);
406     return WdfDevStatePwrPolNull;
407 }
408 
409 WDF_DEVICE_POWER_POLICY_STATE
410 FxPkgPnp::NotPowerPolOwnerGotoDxInDx(
411     __inout FxPkgPnp* This
412     )
413 {
414     This->PowerProcessEvent(PowerCompleteDx);
415     return WdfDevStatePwrPolNull;
416 }
417 
418 WDF_DEVICE_POWER_POLICY_STATE
419 FxPkgPnp::NotPowerPolOwnerGotoD0(
420     __inout FxPkgPnp* This
421     )
422 {
423     This->PowerProcessEvent(PowerCompleteD0);
424     return WdfDevStatePwrPolNull;
425 }
426 
427 WDF_DEVICE_POWER_POLICY_STATE
428 FxPkgPnp::NotPowerPolOwnerGotoD0InD0(
429     __inout FxPkgPnp* This
430     )
431 {
432     This->PowerProcessEvent(PowerCompleteD0);
433     return WdfDevStatePwrPolNull;
434 }
435 
436 WDF_DEVICE_POWER_POLICY_STATE
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
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
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
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
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
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
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