1 //
2 //    Copyright (C) Microsoft.  All rights reserved.
3 //
4 #ifndef _FXPNPSTATEMACHINE_H_
5 #define _FXPNPSTATEMACHINE_H_
6 
7 // @@SMVERIFY_SPLIT_BEGIN
8 
9 typedef
10 WDF_DEVICE_PNP_STATE
11 (*PFN_PNP_STATE_ENTRY_FUNCTION)(
12     FxPkgPnp* This
13     );
14 
15 //
16 // Treat these values as a bit field when comparing for known dropped events in
17 // the current state and treat them as values when they known transition events
18 // from state to the next.
19 //
20 enum FxPnpEvent {
21     PnpEventInvalid                 = 0x000000,
22     PnpEventAddDevice               = 0x000001,
23     PnpEventStartDevice             = 0x000002,
24     PnpEventStartDeviceComplete     = 0x000004,
25     PnpEventStartDeviceFailed       = 0x000008,
26     PnpEventQueryRemove             = 0x000010,
27     PnpEventQueryStop               = 0x000020,
28     PnpEventCancelRemove            = 0x000040,
29     PnpEventCancelStop              = 0x000080,
30     PnpEventStop                    = 0x000100,
31     PnpEventRemove                  = 0x000200,
32     PnpEventSurpriseRemove          = 0x000400,
33     PnpEventEject                   = 0x000800,
34     PnpEventPwrPolStopped           = 0x001000,
35     PnpEventPwrPolStopFailed        = 0x002000,
36     PnpEventPowerUpFailed           = 0x004000,
37     PnpEventPowerDownFailed         = 0x008000,
38     PnpEventParentRemoved           = 0x010000,
39     PnpEventChildrenRemovalComplete = 0x020000,
40     PnpEventPwrPolStarted           = 0x040000,
41     PnpEventPwrPolStartFailed       = 0x080000,
42     PnpEventDeviceInD0              = 0x100000,
43     PnpEventPwrPolRemoved           = 0x200000,
44 
45     //
46     // Not a real event, just a value that shows all of the events which have
47     // queued the pnp irp.  If we drop one of these events, we *must* complete
48     // the pended pnp irp.  See PnpProcessEventInner.
49     //
50     PnpEventPending                 = PnpEventStartDeviceComplete |
51                                       PnpEventQueryRemove         |
52                                       PnpEventQueryStop           |
53                                       PnpEventCancelRemove        |
54                                       PnpEventCancelStop          |
55                                       PnpEventStop                |
56                                       PnpEventSurpriseRemove      |
57                                       PnpEventEject,
58 
59     //
60     // Not a real event, just a value that indicates all of the events which
61     // goto the head of the queue and are always processed, even if the state is
62     // locked.
63     //
64     PnpPriorityEventsMask            = PnpEventPwrPolStarted |
65                                        PnpEventPwrPolStartFailed |
66                                        PnpEventPwrPolStopped |
67                                        PnpEventPwrPolStopFailed |
68                                        PnpEventDeviceInD0 |
69                                        PnpEventPwrPolRemoved,
70 
71     PnpEventNull                    = 0xFFFFFFFF,
72 };
73 
74 //
75 // Bit packed ULONG.
76 //
77 union FxPnpStateInfo {
78     struct {
79         //
80         // Indicates whether the state is open to all events
81         //
82         ULONG QueueOpen : 1;
83 
84         //
85         // Bit of events we know we can drop in this state
86         //
87         ULONG KnownDroppedEvents : 31;
88     } Bits;
89 
90     struct {
91         //
92         // Maps to the same bit location as QueueOpen.  Since we start
93         // KnownDroppedEvents at the next bit, start our bits by at the next
94         // bit as well.
95         //
96         ULONG Reserved : 1;
97 
98         //
99         // These are defined so that we can easily tell in the debugger what
100         // each set bit in KnownDroppedEvents maps to in the FxPnpEvent enum
101         //
102         ULONG PnpEventAddDeviceKnown : 1;
103         ULONG PnpEventStartDeviceKnown : 1;
104         ULONG PnpEventStartDeviceCompleteKnown : 1;
105         ULONG PnpEventStartDeviceFailedKnown : 1;
106         ULONG PnpEventQueryRemoveKnown : 1;
107         ULONG PnpEventQueryStopKnown : 1;
108         ULONG PnpEventCancelRemoveKnown : 1;
109         ULONG PnpEventCancelStopKnown : 1;
110         ULONG PnpEventStopKnown : 1;
111         ULONG PnpEventRemoveKnown : 1;
112         ULONG PnpEventSurpriseRemoveKnown : 1;
113         ULONG PnpEventEjectKnown : 1;
114         ULONG PnpEventPwrPolStopped : 1;
115         ULONG PnpEventPwrPolStopFailed : 1;
116         ULONG PnpEventPowerUpFailedKnown : 1;
117         ULONG PnpEventPowerDownFailedKnown : 1;
118         ULONG PnpEventParentRemovedKnown : 1;
119         ULONG PnpEventChildrenRemovalCompleteKnown : 1;
120         ULONG PnpEventPwrPolStarted : 1;
121         ULONG PnpEventPwrPolStartFailed : 1;
122     } BitsByName;
123 };
124 
125 struct PNP_EVENT_TARGET_STATE {
126     FxPnpEvent PnpEvent;
127 
128     WDF_DEVICE_PNP_STATE TargetState;
129 
130     EVENT_TRAP_FIELD
131 };
132 
133 typedef const PNP_EVENT_TARGET_STATE* CPPNP_EVENT_TARGET_STATE;
134 
135 struct PNP_STATE_TABLE {
136     //
137     // Framework internal function
138     //
139     PFN_PNP_STATE_ENTRY_FUNCTION StateFunc;
140 
141     PNP_EVENT_TARGET_STATE FirstTargetState;
142 
143     CPPNP_EVENT_TARGET_STATE OtherTargetStates;
144 
145     FxPnpStateInfo StateInfo;
146 
147 };
148 
149 typedef const PNP_STATE_TABLE* CPPNP_STATE_TABLE;
150 
151 #if FX_STATE_MACHINE_VERIFY
152 #define MAX_PNP_STATE_ENTRY_FN_RETURN_STATES            (5)
153 
154 struct PNP_STATE_ENTRY_FUNCTION_TARGET_STATE {
155     //
156     // Return value from state entry function
157     //
158     WDF_DEVICE_PNP_STATE State;
159 
160     //
161     // type of device the returning state applies to
162     //
163     FxStateMachineDeviceType  DeviceType;
164 
165     //
166     // Info about the state transition
167     //
168     PSTR Comment;
169 };
170 
171 typedef const PNP_STATE_ENTRY_FUNCTION_TARGET_STATE* CPPNP_STATE_ENTRY_FUNCTION_TARGET_STATE;
172 
173 struct PNP_STATE_ENTRY_FN_RETURN_STATE_TABLE {
174     //
175     // array of state transitions caused by state entry function
176     //
177     PNP_STATE_ENTRY_FUNCTION_TARGET_STATE TargetStates[MAX_PNP_STATE_ENTRY_FN_RETURN_STATES];
178 };
179 
180 typedef const PNP_STATE_ENTRY_FN_RETURN_STATE_TABLE*  CPPNP_STATE_ENTRY_FN_RETURN_STATE_TABLE;
181 #endif //FX_STATE_MACHINE_VERIFY
182 
183 // @@SMVERIFY_SPLIT_END
184 
185 //
186 // This type of union is done so that we can
187 // 1) shrink the array element to the smallest size possible
188 // 2) keep types within the structure so we can dump it in the debugger
189 //
190 union FxPnpMachineStateHistory {
191     struct {
192         WDF_DEVICE_PNP_STATE State1 : 16;
193         WDF_DEVICE_PNP_STATE State2 : 16;
194         WDF_DEVICE_PNP_STATE State3 : 16;
195         WDF_DEVICE_PNP_STATE State4 : 16;
196         WDF_DEVICE_PNP_STATE State5 : 16;
197         WDF_DEVICE_PNP_STATE State6 : 16;
198         WDF_DEVICE_PNP_STATE State7 : 16;
199         WDF_DEVICE_PNP_STATE State8 : 16;
200     } S;
201 
202     USHORT History[PnpEventQueueDepth];
203 };
204 
205 
206 struct FxPnpMachine : public FxWorkItemEventQueue {
FxPnpMachineFxPnpMachine207     FxPnpMachine(
208         VOID
209         ) : FxWorkItemEventQueue(PnpEventQueueDepth)
210     {
211         RtlZeroMemory(&m_Queue[0], sizeof(m_Queue));
212         RtlZeroMemory(&m_States, sizeof(m_States));
213 
214         m_States.History[IncrementHistoryIndex()] = WdfDevStatePnpObjectCreated;
215         m_FireAndForget = FALSE;
216     }
217 
218     FxPnpEvent m_Queue[PnpEventQueueDepth];
219 
220     FxPnpMachineStateHistory m_States;
221 
222     BOOLEAN m_FireAndForget;
223 };
224 
225 #endif // _FXPNPSTATEMACHINE_H_
226