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