1 //
2 //    Copyright (C) Microsoft.  All rights reserved.
3 //
4 #ifndef _FXWAKEINTERRUPTSTATEMACHINE_H_
5 #define _FXWAKEINTERRUPTSTATEMACHINE_H_
6 
7 //
8 // This is a magical number based on inspection.  If the queue overflows,
9 // it is OK to increase these numbers without fear of either dependencies or
10 // weird side affects.
11 //
12 const UCHAR FxWakeInterruptEventQueueDepth = 8;
13 
14 enum FxWakeInterruptEvents : UINT32 {
15     WakeInterruptEventInvalid                  = 0x00,
16     WakeInterruptEventIsr                      = 0x01,
17     WakeInterruptEventEnteringD0               = 0x02,
18     WakeInterruptEventLeavingD0                = 0x04,
19     WakeInterruptEventD0EntryFailed            = 0x08,
20     WakeInterruptEventLeavingD0NotArmedForWake = 0x10,
21     WakeInterruptEventNull                     = 0xFF,
22 };
23 
24 enum FxWakeInterruptStates {
25     WakeInterruptInvalid = 0,
26     WakeInterruptFailed,
27     WakeInterruptD0,
28     WakeInterruptDx,
29     WakeInterruptWaking,
30     WakeInterruptInvokingEvtIsrPostWake,
31     WakeInterruptCompletingD0,
32     WakeInterruptInvokingEvtIsrInD0,
33     WakeInterruptDxNotArmedForWake,
34     WakeInterruptInvokingEvtIsrInDxNotArmedForWake,
35     WakeInterruptMax
36 };
37 
38 //
39 // Forward declaration
40 //
41 class FxWakeInterruptMachine;
42 class FxInterrupt;
43 
44 typedef
45 _Must_inspect_result_
46 FxWakeInterruptStates
47 (*PFN_WAKE_INTERRUPT_STATE_ENTRY_FUNCTION)(
48     __in FxWakeInterruptMachine* This
49     );
50 
51 struct FxWakeInterruptTargetState {
52     FxWakeInterruptEvents WakeInterruptEvent;
53 
54     FxWakeInterruptStates WakeInterruptState;
55 
56 #if FX_SUPER_DBG
57     BOOLEAN EventDebugged;
58 #endif
59 };
60 
61 //
62 // This type of union is done so that we can
63 // 1) shrink the array element to the smallest size possible
64 // 2) keep types within the structure so we can dump it in the debugger
65 //
66 union FxWakeInterruptMachineStateHistory {
67     struct {
68         FxWakeInterruptStates State1 : 8;
69         FxWakeInterruptStates State2 : 8;
70         FxWakeInterruptStates State3 : 8;
71         FxWakeInterruptStates State4 : 8;
72         FxWakeInterruptStates State5 : 8;
73         FxWakeInterruptStates State6 : 8;
74         FxWakeInterruptStates State7 : 8;
75         FxWakeInterruptStates State8 : 8;
76     } S;
77 
78     UCHAR History[FxWakeInterruptEventQueueDepth];
79 };
80 
81 struct FxWakeInterruptStateTable {
82     PFN_WAKE_INTERRUPT_STATE_ENTRY_FUNCTION StateFunc;
83 
84     const FxWakeInterruptTargetState* TargetStates;
85 
86     ULONG TargetStatesCount;
87 };
88 
89 class FxWakeInterruptMachine : public FxThreadedEventQueue {
90 
91     friend FxInterrupt;
92 
93 public:
94     FxWakeInterruptMachine(
95         __in FxInterrupt * Interrupt
96         );
97 
98     VOID
99     ProcessEvent(
100         __in FxWakeInterruptEvents Event
101         );
102 
103     static
104     VOID
105     _ProcessEventInner(
106         __inout FxPkgPnp* PkgPnp,
107         __inout FxPostProcessInfo* Info,
108         __in PVOID WorkerContext
109         );
110 
111 private:
112     VOID
113     ProcessEventInner(
114         __inout FxPostProcessInfo* Info
115         );
116 
117     static
118     FxWakeInterruptStates
119     Waking(
120         __in FxWakeInterruptMachine* This
121         );
122 
123     static
124     FxWakeInterruptStates
125     Dx(
126         __in FxWakeInterruptMachine* This
127         );
128 
129     static
130     FxWakeInterruptStates
131     DxNotArmedForWake(
132         __in FxWakeInterruptMachine* This
133         );
134 
135     static
136     FxWakeInterruptStates
137     Failed(
138         __in FxWakeInterruptMachine* This
139         );
140 
141     static
142     FxWakeInterruptStates
143     InvokingEvtIsrPostWake(
144         __in FxWakeInterruptMachine* This
145         );
146 
147     static
148     FxWakeInterruptStates
149     InvokingEvtIsrInDxNotArmedForWake(
150         __in FxWakeInterruptMachine* This
151         );
152 
153     static
154     FxWakeInterruptStates
155     InvokingEvtIsrInD0(
156         __in FxWakeInterruptMachine* This
157         );
158 
159     static
160     FxWakeInterruptStates
161     CompletingD0(
162         __in FxWakeInterruptMachine* This
163         );
164 
165 protected:
166     //FxPkgPnp* m_PkgPnp;
167     FxInterrupt* m_Interrupt;
168     //
169     // Set if the interrupt was left active during Dx transition to handle wake
170     // events.
171     //
172     BOOLEAN m_ActiveForWake;
173     BOOLEAN m_Claimed;
174     MxEvent m_IsrEvent;
175 
176     // uses FxWakeInterruptStates values
177     BYTE m_CurrentState;
178 
179     // three extra padded bytes are put in here by the compiler
180 
181     FxWakeInterruptEvents m_Queue[FxWakeInterruptEventQueueDepth];
182     FxWakeInterruptMachineStateHistory m_States;
183 
184     static const FxWakeInterruptStateTable m_StateTable[];
185 
186     static const FxWakeInterruptTargetState m_FailedStates[];
187     static const FxWakeInterruptTargetState m_D0States[];
188     static const FxWakeInterruptTargetState m_DxStates[];
189     static const FxWakeInterruptTargetState m_DxNotArmedForWakeStates[];
190     static const FxWakeInterruptTargetState m_WakingStates[];
191     static const FxWakeInterruptTargetState m_InvokingEvtIsrPostWakeStates[];
192     static const FxWakeInterruptTargetState m_CompletingD0States[];
193     static const FxWakeInterruptTargetState m_InvokingIsrInD0[];
194 };
195 
196 #endif // _FXWAKEINTERRUPTSTATEMACHINE_H_
197