1*8a978a17SVictor Perevertkin /*++
2*8a978a17SVictor Perevertkin
3*8a978a17SVictor Perevertkin Copyright (c) Microsoft. All rights reserved.
4*8a978a17SVictor Perevertkin
5*8a978a17SVictor Perevertkin Module Name:
6*8a978a17SVictor Perevertkin
7*8a978a17SVictor Perevertkin PowerIdleStateMachine.cpp
8*8a978a17SVictor Perevertkin
9*8a978a17SVictor Perevertkin Abstract:
10*8a978a17SVictor Perevertkin
11*8a978a17SVictor Perevertkin This module implements the Power Policy idle state machine for the driver
12*8a978a17SVictor Perevertkin framework.
13*8a978a17SVictor Perevertkin
14*8a978a17SVictor Perevertkin Author:
15*8a978a17SVictor Perevertkin
16*8a978a17SVictor Perevertkin
17*8a978a17SVictor Perevertkin
18*8a978a17SVictor Perevertkin Environment:
19*8a978a17SVictor Perevertkin
20*8a978a17SVictor Perevertkin Both kernel and user mode
21*8a978a17SVictor Perevertkin
22*8a978a17SVictor Perevertkin Revision History:
23*8a978a17SVictor Perevertkin
24*8a978a17SVictor Perevertkin
25*8a978a17SVictor Perevertkin
26*8a978a17SVictor Perevertkin --*/
27*8a978a17SVictor Perevertkin
28*8a978a17SVictor Perevertkin #include "pnppriv.hpp"
29*8a978a17SVictor Perevertkin
30*8a978a17SVictor Perevertkin extern "C" {
31*8a978a17SVictor Perevertkin #if defined(EVENT_TRACING)
32*8a978a17SVictor Perevertkin #include "PowerIdleStateMachine.tmh"
33*8a978a17SVictor Perevertkin #endif
34*8a978a17SVictor Perevertkin }
35*8a978a17SVictor Perevertkin
36*8a978a17SVictor Perevertkin const FxPowerIdleTargetState FxPowerIdleMachine::m_StoppedStates[] =
37*8a978a17SVictor Perevertkin {
38*8a978a17SVictor Perevertkin { PowerIdleEventStart, FxIdleStarted DEBUGGED_EVENT },
39*8a978a17SVictor Perevertkin };
40*8a978a17SVictor Perevertkin
41*8a978a17SVictor Perevertkin const FxPowerIdleTargetState FxPowerIdleMachine::m_StartedStates[] =
42*8a978a17SVictor Perevertkin {
43*8a978a17SVictor Perevertkin { PowerIdleEventPowerUpComplete, FxIdleStartedPowerUp DEBUGGED_EVENT },
44*8a978a17SVictor Perevertkin { PowerIdleEventPowerUpFailed, FxIdleStartedPowerFailed DEBUGGED_EVENT },
45*8a978a17SVictor Perevertkin { PowerIdleEventStop, FxIdleStopped DEBUGGED_EVENT },
46*8a978a17SVictor Perevertkin };
47*8a978a17SVictor Perevertkin
48*8a978a17SVictor Perevertkin const FxPowerIdleTargetState FxPowerIdleMachine::m_DisabledStates[] =
49*8a978a17SVictor Perevertkin {
50*8a978a17SVictor Perevertkin { PowerIdleEventEnabled, FxIdleCheckIoCount DEBUGGED_EVENT },
51*8a978a17SVictor Perevertkin { PowerIdleEventDisabled, FxIdleDisabled DEBUGGED_EVENT },
52*8a978a17SVictor Perevertkin { PowerIdleEventPowerDown, FxIdleGoingToDx DEBUGGED_EVENT },
53*8a978a17SVictor Perevertkin { PowerIdleEventPowerDownFailed, FxIdlePowerFailed DEBUGGED_EVENT },
54*8a978a17SVictor Perevertkin { PowerIdleEventPowerUpFailed, FxIdlePowerFailed DEBUGGED_EVENT },
55*8a978a17SVictor Perevertkin { PowerIdleEventStop, FxIdleStopped DEBUGGED_EVENT },
56*8a978a17SVictor Perevertkin };
57*8a978a17SVictor Perevertkin
58*8a978a17SVictor Perevertkin const FxPowerIdleTargetState FxPowerIdleMachine::m_BusyStates[] =
59*8a978a17SVictor Perevertkin {
60*8a978a17SVictor Perevertkin { PowerIdleEventIoDecrement, FxIdleDecrementIo DEBUGGED_EVENT },
61*8a978a17SVictor Perevertkin { PowerIdleEventDisabled, FxIdleDisabled DEBUGGED_EVENT },
62*8a978a17SVictor Perevertkin { PowerIdleEventPowerDown, FxIdleGoingToDx TRAP_ON_EVENT },
63*8a978a17SVictor Perevertkin { PowerIdleEventPowerDownFailed, FxIdlePowerFailed TRAP_ON_EVENT },
64*8a978a17SVictor Perevertkin };
65*8a978a17SVictor Perevertkin
66*8a978a17SVictor Perevertkin const FxPowerIdleTargetState FxPowerIdleMachine::m_TimerRunningStates[] =
67*8a978a17SVictor Perevertkin {
68*8a978a17SVictor Perevertkin { PowerIdleEventDisabled, FxIdleDisabling DEBUGGED_EVENT },
69*8a978a17SVictor Perevertkin { PowerIdleEventIoIncrement, FxIdleCancelTimer DEBUGGED_EVENT },
70*8a978a17SVictor Perevertkin { PowerIdleEventEnabled, FxIdleCancelTimer DEBUGGED_EVENT },
71*8a978a17SVictor Perevertkin { PowerIdleEventTimerExpired, FxIdleTimingOut DEBUGGED_EVENT },
72*8a978a17SVictor Perevertkin };
73*8a978a17SVictor Perevertkin
74*8a978a17SVictor Perevertkin const FxPowerIdleTargetState FxPowerIdleMachine::m_TimedOutStates[] =
75*8a978a17SVictor Perevertkin {
76*8a978a17SVictor Perevertkin { PowerIdleEventPowerDown, FxIdleTimedOutPowerDown DEBUGGED_EVENT },
77*8a978a17SVictor Perevertkin { PowerIdleEventPowerDownFailed, FxIdleTimedOutPowerDownFailed DEBUGGED_EVENT },
78*8a978a17SVictor Perevertkin { PowerIdleEventDisabled, FxIdleTimedOutDisabled DEBUGGED_EVENT },
79*8a978a17SVictor Perevertkin { PowerIdleEventEnabled, FxIdleTimedOutEnabled DEBUGGED_EVENT },
80*8a978a17SVictor Perevertkin { PowerIdleEventIoIncrement, FxIdleTimedOutIoIncrement DEBUGGED_EVENT },
81*8a978a17SVictor Perevertkin };
82*8a978a17SVictor Perevertkin
83*8a978a17SVictor Perevertkin const FxPowerIdleTargetState FxPowerIdleMachine::m_InDxStates[] =
84*8a978a17SVictor Perevertkin {
85*8a978a17SVictor Perevertkin { PowerIdleEventPowerUpComplete, FxIdlePowerUp DEBUGGED_EVENT },
86*8a978a17SVictor Perevertkin { PowerIdleEventPowerUpFailed, FxIdleInDxPowerUpFailure DEBUGGED_EVENT },
87*8a978a17SVictor Perevertkin { PowerIdleEventPowerDownFailed, FxIdleInDxPowerUpFailure TRAP_ON_EVENT },
88*8a978a17SVictor Perevertkin { PowerIdleEventStop, FxIdleInDxStopped DEBUGGED_EVENT },
89*8a978a17SVictor Perevertkin { PowerIdleEventDisabled, FxIdleInDxDisabled DEBUGGED_EVENT },
90*8a978a17SVictor Perevertkin { PowerIdleEventIoIncrement, FxIdleInDxIoIncrement DEBUGGED_EVENT },
91*8a978a17SVictor Perevertkin { PowerIdleEventIoDecrement, FxIdleInDx DEBUGGED_EVENT },
92*8a978a17SVictor Perevertkin { PowerIdleEventPowerDown, FxIdleInDx DEBUGGED_EVENT },
93*8a978a17SVictor Perevertkin { PowerIdleEventEnabled, FxIdleInDxEnabled DEBUGGED_EVENT },
94*8a978a17SVictor Perevertkin };
95*8a978a17SVictor Perevertkin
96*8a978a17SVictor Perevertkin const FxPowerIdleTargetState FxPowerIdleMachine::m_WaitForTimeoutStates[] =
97*8a978a17SVictor Perevertkin {
98*8a978a17SVictor Perevertkin { PowerIdleEventTimerExpired, FxIdleTimerExpired DEBUGGED_EVENT },
99*8a978a17SVictor Perevertkin { PowerIdleEventPowerDownFailed, FxIdlePowerFailedWaitForTimeout TRAP_ON_EVENT },
100*8a978a17SVictor Perevertkin { PowerIdleEventDisabled, FxIdleDisablingWaitForTimeout DEBUGGED_EVENT },
101*8a978a17SVictor Perevertkin };
102*8a978a17SVictor Perevertkin
103*8a978a17SVictor Perevertkin const FxPowerIdleTargetState FxPowerIdleMachine::m_DisablingWaitForTimeoutStates[] =
104*8a978a17SVictor Perevertkin {
105*8a978a17SVictor Perevertkin { PowerIdleEventTimerExpired, FxIdleDisablingTimerExpired DEBUGGED_EVENT },
106*8a978a17SVictor Perevertkin };
107*8a978a17SVictor Perevertkin
108*8a978a17SVictor Perevertkin const FxPowerIdleTargetState FxPowerIdleMachine::m_PowerFailedWaitForTimeoutStates[] =
109*8a978a17SVictor Perevertkin {
110*8a978a17SVictor Perevertkin { PowerIdleEventTimerExpired, FxIdlePowerFailed TRAP_ON_EVENT },
111*8a978a17SVictor Perevertkin };
112*8a978a17SVictor Perevertkin
113*8a978a17SVictor Perevertkin const FxIdleStateTable FxPowerIdleMachine::m_StateTable[] =
114*8a978a17SVictor Perevertkin {
115*8a978a17SVictor Perevertkin // FxIdleStopped
116*8a978a17SVictor Perevertkin { FxPowerIdleMachine::Stopped,
117*8a978a17SVictor Perevertkin FxPowerIdleMachine::m_StoppedStates,
118*8a978a17SVictor Perevertkin ARRAY_SIZE(FxPowerIdleMachine::m_StoppedStates),
119*8a978a17SVictor Perevertkin },
120*8a978a17SVictor Perevertkin
121*8a978a17SVictor Perevertkin // FxIdleStarted
122*8a978a17SVictor Perevertkin { FxPowerIdleMachine::Started,
123*8a978a17SVictor Perevertkin FxPowerIdleMachine::m_StartedStates,
124*8a978a17SVictor Perevertkin ARRAY_SIZE(FxPowerIdleMachine::m_StartedStates),
125*8a978a17SVictor Perevertkin },
126*8a978a17SVictor Perevertkin
127*8a978a17SVictor Perevertkin // FxIdleStartedPowerUp
128*8a978a17SVictor Perevertkin { FxPowerIdleMachine::StartedPowerUp,
129*8a978a17SVictor Perevertkin NULL,
130*8a978a17SVictor Perevertkin 0,
131*8a978a17SVictor Perevertkin },
132*8a978a17SVictor Perevertkin
133*8a978a17SVictor Perevertkin // FxIdleStartedPowerFailed
134*8a978a17SVictor Perevertkin { FxPowerIdleMachine::StartedPowerFailed,
135*8a978a17SVictor Perevertkin NULL,
136*8a978a17SVictor Perevertkin 0,
137*8a978a17SVictor Perevertkin },
138*8a978a17SVictor Perevertkin
139*8a978a17SVictor Perevertkin // FxIdleDisabled
140*8a978a17SVictor Perevertkin { FxPowerIdleMachine::Disabled,
141*8a978a17SVictor Perevertkin FxPowerIdleMachine::m_DisabledStates,
142*8a978a17SVictor Perevertkin ARRAY_SIZE(FxPowerIdleMachine::m_DisabledStates),
143*8a978a17SVictor Perevertkin },
144*8a978a17SVictor Perevertkin
145*8a978a17SVictor Perevertkin // FxIdleCheckIoCount
146*8a978a17SVictor Perevertkin { FxPowerIdleMachine::CheckIoCount,
147*8a978a17SVictor Perevertkin NULL,
148*8a978a17SVictor Perevertkin 0,
149*8a978a17SVictor Perevertkin },
150*8a978a17SVictor Perevertkin
151*8a978a17SVictor Perevertkin // FxIdleBusy
152*8a978a17SVictor Perevertkin { NULL,
153*8a978a17SVictor Perevertkin FxPowerIdleMachine::m_BusyStates,
154*8a978a17SVictor Perevertkin ARRAY_SIZE(FxPowerIdleMachine::m_BusyStates),
155*8a978a17SVictor Perevertkin },
156*8a978a17SVictor Perevertkin
157*8a978a17SVictor Perevertkin // FxIdleDecrementIo
158*8a978a17SVictor Perevertkin { FxPowerIdleMachine::DecrementIo,
159*8a978a17SVictor Perevertkin NULL,
160*8a978a17SVictor Perevertkin 0,
161*8a978a17SVictor Perevertkin },
162*8a978a17SVictor Perevertkin
163*8a978a17SVictor Perevertkin // FxIdleStartTimer
164*8a978a17SVictor Perevertkin { FxPowerIdleMachine::StartTimer,
165*8a978a17SVictor Perevertkin NULL,
166*8a978a17SVictor Perevertkin 0,
167*8a978a17SVictor Perevertkin },
168*8a978a17SVictor Perevertkin
169*8a978a17SVictor Perevertkin // FxIdleTimerRunning
170*8a978a17SVictor Perevertkin { NULL,
171*8a978a17SVictor Perevertkin FxPowerIdleMachine::m_TimerRunningStates,
172*8a978a17SVictor Perevertkin ARRAY_SIZE(FxPowerIdleMachine::m_TimerRunningStates)
173*8a978a17SVictor Perevertkin },
174*8a978a17SVictor Perevertkin
175*8a978a17SVictor Perevertkin // FxIdleTimingOut
176*8a978a17SVictor Perevertkin { FxPowerIdleMachine::TimingOut,
177*8a978a17SVictor Perevertkin NULL,
178*8a978a17SVictor Perevertkin 0,
179*8a978a17SVictor Perevertkin },
180*8a978a17SVictor Perevertkin
181*8a978a17SVictor Perevertkin // FxIdleTimedOut
182*8a978a17SVictor Perevertkin { NULL,
183*8a978a17SVictor Perevertkin FxPowerIdleMachine::m_TimedOutStates,
184*8a978a17SVictor Perevertkin ARRAY_SIZE(FxPowerIdleMachine::m_TimedOutStates),
185*8a978a17SVictor Perevertkin },
186*8a978a17SVictor Perevertkin
187*8a978a17SVictor Perevertkin // FxIdleTimedOutIoIncrement
188*8a978a17SVictor Perevertkin { FxPowerIdleMachine::TimedOutIoIncrement,
189*8a978a17SVictor Perevertkin NULL,
190*8a978a17SVictor Perevertkin 0,
191*8a978a17SVictor Perevertkin },
192*8a978a17SVictor Perevertkin
193*8a978a17SVictor Perevertkin // FxIdleTimedOutPowerDown
194*8a978a17SVictor Perevertkin { FxPowerIdleMachine::TimedOutPowerDown,
195*8a978a17SVictor Perevertkin NULL,
196*8a978a17SVictor Perevertkin 0,
197*8a978a17SVictor Perevertkin },
198*8a978a17SVictor Perevertkin
199*8a978a17SVictor Perevertkin // FxIdleTimedOutPowerDownFailed
200*8a978a17SVictor Perevertkin { FxPowerIdleMachine::TimedOutPowerDownFailed,
201*8a978a17SVictor Perevertkin NULL,
202*8a978a17SVictor Perevertkin 0,
203*8a978a17SVictor Perevertkin },
204*8a978a17SVictor Perevertkin
205*8a978a17SVictor Perevertkin // FxIdleGoingToDx,
206*8a978a17SVictor Perevertkin { FxPowerIdleMachine::GoingToDx,
207*8a978a17SVictor Perevertkin NULL,
208*8a978a17SVictor Perevertkin 0,
209*8a978a17SVictor Perevertkin },
210*8a978a17SVictor Perevertkin
211*8a978a17SVictor Perevertkin // FxIdleInDx,
212*8a978a17SVictor Perevertkin { FxPowerIdleMachine::InDx,
213*8a978a17SVictor Perevertkin FxPowerIdleMachine::m_InDxStates,
214*8a978a17SVictor Perevertkin ARRAY_SIZE(FxPowerIdleMachine::m_InDxStates),
215*8a978a17SVictor Perevertkin },
216*8a978a17SVictor Perevertkin
217*8a978a17SVictor Perevertkin // FxIdleInDxIoIncrement
218*8a978a17SVictor Perevertkin { FxPowerIdleMachine::InDxIoIncrement,
219*8a978a17SVictor Perevertkin NULL,
220*8a978a17SVictor Perevertkin 0,
221*8a978a17SVictor Perevertkin },
222*8a978a17SVictor Perevertkin
223*8a978a17SVictor Perevertkin // FxIdleInDxPowerUpFailure
224*8a978a17SVictor Perevertkin { FxPowerIdleMachine::InDxPowerUpFailure,
225*8a978a17SVictor Perevertkin NULL,
226*8a978a17SVictor Perevertkin 0,
227*8a978a17SVictor Perevertkin },
228*8a978a17SVictor Perevertkin
229*8a978a17SVictor Perevertkin // FxIdleInDxStopped
230*8a978a17SVictor Perevertkin { FxPowerIdleMachine::InDxStopped,
231*8a978a17SVictor Perevertkin NULL,
232*8a978a17SVictor Perevertkin 0,
233*8a978a17SVictor Perevertkin },
234*8a978a17SVictor Perevertkin
235*8a978a17SVictor Perevertkin // FxIdleInDxDisabled
236*8a978a17SVictor Perevertkin { FxPowerIdleMachine::InDxDisabled,
237*8a978a17SVictor Perevertkin NULL,
238*8a978a17SVictor Perevertkin 0,
239*8a978a17SVictor Perevertkin },
240*8a978a17SVictor Perevertkin
241*8a978a17SVictor Perevertkin // FxIdleInDxEnabled
242*8a978a17SVictor Perevertkin { FxPowerIdleMachine::InDxEnabled,
243*8a978a17SVictor Perevertkin NULL,
244*8a978a17SVictor Perevertkin 0,
245*8a978a17SVictor Perevertkin },
246*8a978a17SVictor Perevertkin
247*8a978a17SVictor Perevertkin // FxIdlePowerUp
248*8a978a17SVictor Perevertkin { FxPowerIdleMachine::PowerUp,
249*8a978a17SVictor Perevertkin NULL,
250*8a978a17SVictor Perevertkin 0,
251*8a978a17SVictor Perevertkin },
252*8a978a17SVictor Perevertkin
253*8a978a17SVictor Perevertkin // FxIdlePowerUpComplete
254*8a978a17SVictor Perevertkin { FxPowerIdleMachine::PowerUpComplete,
255*8a978a17SVictor Perevertkin NULL,
256*8a978a17SVictor Perevertkin 0,
257*8a978a17SVictor Perevertkin },
258*8a978a17SVictor Perevertkin
259*8a978a17SVictor Perevertkin // FxIdleTimedOutDisabled
260*8a978a17SVictor Perevertkin { FxPowerIdleMachine::TimedOutDisabled,
261*8a978a17SVictor Perevertkin NULL,
262*8a978a17SVictor Perevertkin 0,
263*8a978a17SVictor Perevertkin },
264*8a978a17SVictor Perevertkin
265*8a978a17SVictor Perevertkin // FxIdleTimedOutEnabled
266*8a978a17SVictor Perevertkin { FxPowerIdleMachine::TimedOutEnabled,
267*8a978a17SVictor Perevertkin NULL,
268*8a978a17SVictor Perevertkin 0,
269*8a978a17SVictor Perevertkin },
270*8a978a17SVictor Perevertkin
271*8a978a17SVictor Perevertkin // FxIdleCancelTimer
272*8a978a17SVictor Perevertkin { FxPowerIdleMachine::CancelTimer,
273*8a978a17SVictor Perevertkin NULL,
274*8a978a17SVictor Perevertkin 0,
275*8a978a17SVictor Perevertkin },
276*8a978a17SVictor Perevertkin
277*8a978a17SVictor Perevertkin // FxIdleWaitForTimeout
278*8a978a17SVictor Perevertkin { NULL,
279*8a978a17SVictor Perevertkin FxPowerIdleMachine::m_WaitForTimeoutStates,
280*8a978a17SVictor Perevertkin ARRAY_SIZE(FxPowerIdleMachine::m_WaitForTimeoutStates),
281*8a978a17SVictor Perevertkin },
282*8a978a17SVictor Perevertkin
283*8a978a17SVictor Perevertkin // FxIdleTimerExpired
284*8a978a17SVictor Perevertkin { FxPowerIdleMachine::TimerExpired,
285*8a978a17SVictor Perevertkin NULL,
286*8a978a17SVictor Perevertkin 0,
287*8a978a17SVictor Perevertkin },
288*8a978a17SVictor Perevertkin
289*8a978a17SVictor Perevertkin // FxIdleDisabling
290*8a978a17SVictor Perevertkin { FxPowerIdleMachine::Disabling,
291*8a978a17SVictor Perevertkin NULL,
292*8a978a17SVictor Perevertkin 0,
293*8a978a17SVictor Perevertkin },
294*8a978a17SVictor Perevertkin
295*8a978a17SVictor Perevertkin // FxIdleDisablingWaitForTimeout
296*8a978a17SVictor Perevertkin { NULL,
297*8a978a17SVictor Perevertkin FxPowerIdleMachine::m_DisablingWaitForTimeoutStates,
298*8a978a17SVictor Perevertkin ARRAY_SIZE(FxPowerIdleMachine::m_DisablingWaitForTimeoutStates),
299*8a978a17SVictor Perevertkin },
300*8a978a17SVictor Perevertkin
301*8a978a17SVictor Perevertkin // FxIdleDisablingTimerExpired
302*8a978a17SVictor Perevertkin { FxPowerIdleMachine::DisablingTimerExpired,
303*8a978a17SVictor Perevertkin NULL,
304*8a978a17SVictor Perevertkin 0,
305*8a978a17SVictor Perevertkin },
306*8a978a17SVictor Perevertkin
307*8a978a17SVictor Perevertkin // FxIdlePowerFailedWaitForTimeout
308*8a978a17SVictor Perevertkin { NULL,
309*8a978a17SVictor Perevertkin FxPowerIdleMachine::m_PowerFailedWaitForTimeoutStates,
310*8a978a17SVictor Perevertkin ARRAY_SIZE(FxPowerIdleMachine::m_PowerFailedWaitForTimeoutStates),
311*8a978a17SVictor Perevertkin },
312*8a978a17SVictor Perevertkin
313*8a978a17SVictor Perevertkin // FxIdlePowerFailed
314*8a978a17SVictor Perevertkin { FxPowerIdleMachine::PowerFailed,
315*8a978a17SVictor Perevertkin NULL,
316*8a978a17SVictor Perevertkin 0,
317*8a978a17SVictor Perevertkin },
318*8a978a17SVictor Perevertkin };
319*8a978a17SVictor Perevertkin
320*8a978a17SVictor Perevertkin __inline
321*8a978a17SVictor Perevertkin FxPkgPnp*
GetPnpPkg(__inout FxPowerIdleMachine * This)322*8a978a17SVictor Perevertkin GetPnpPkg(
323*8a978a17SVictor Perevertkin __inout FxPowerIdleMachine* This
324*8a978a17SVictor Perevertkin )
325*8a978a17SVictor Perevertkin {
326*8a978a17SVictor Perevertkin return CONTAINING_RECORD(This,
327*8a978a17SVictor Perevertkin FxPowerPolicyOwnerSettings,
328*8a978a17SVictor Perevertkin m_PowerIdleMachine)->m_PkgPnp;
329*8a978a17SVictor Perevertkin }
330*8a978a17SVictor Perevertkin
331*8a978a17SVictor Perevertkin
FxPowerIdleMachine(VOID)332*8a978a17SVictor Perevertkin FxPowerIdleMachine::FxPowerIdleMachine(
333*8a978a17SVictor Perevertkin VOID
334*8a978a17SVictor Perevertkin )
335*8a978a17SVictor Perevertkin /*++
336*8a978a17SVictor Perevertkin
337*8a978a17SVictor Perevertkin Routine Description:
338*8a978a17SVictor Perevertkin Constructs the power idle state machine
339*8a978a17SVictor Perevertkin
340*8a978a17SVictor Perevertkin Arguments:
341*8a978a17SVictor Perevertkin None
342*8a978a17SVictor Perevertkin
343*8a978a17SVictor Perevertkin Return Value:
344*8a978a17SVictor Perevertkin None
345*8a978a17SVictor Perevertkin
346*8a978a17SVictor Perevertkin --*/
347*8a978a17SVictor Perevertkin {
348*8a978a17SVictor Perevertkin //
349*8a978a17SVictor Perevertkin // m_Lock and m_PowerTimeoutTimer are now being initialized in Init method
350*8a978a17SVictor Perevertkin // since they may fail for UM.
351*8a978a17SVictor Perevertkin //
352*8a978a17SVictor Perevertkin
353*8a978a17SVictor Perevertkin m_PowerTimeout.QuadPart = 0;
354*8a978a17SVictor Perevertkin m_CurrentIdleState = FxIdleStopped;
355*8a978a17SVictor Perevertkin
356*8a978a17SVictor Perevertkin m_EventHistoryIndex = 0;
357*8a978a17SVictor Perevertkin m_StateHistoryIndex = 0;
358*8a978a17SVictor Perevertkin
359*8a978a17SVictor Perevertkin RtlZeroMemory(&m_EventHistory[0], sizeof(m_EventHistory));
360*8a978a17SVictor Perevertkin RtlZeroMemory(&m_StateHistory[0], sizeof(m_StateHistory));
361*8a978a17SVictor Perevertkin
362*8a978a17SVictor Perevertkin m_TagTracker = NULL;
363*8a978a17SVictor Perevertkin }
364*8a978a17SVictor Perevertkin
~FxPowerIdleMachine(VOID)365*8a978a17SVictor Perevertkin FxPowerIdleMachine::~FxPowerIdleMachine(
366*8a978a17SVictor Perevertkin VOID
367*8a978a17SVictor Perevertkin )
368*8a978a17SVictor Perevertkin {
369*8a978a17SVictor Perevertkin if (m_TagTracker != NULL) {
370*8a978a17SVictor Perevertkin delete m_TagTracker;
371*8a978a17SVictor Perevertkin m_TagTracker = NULL;
372*8a978a17SVictor Perevertkin }
373*8a978a17SVictor Perevertkin }
374*8a978a17SVictor Perevertkin
375*8a978a17SVictor Perevertkin _Must_inspect_result_
376*8a978a17SVictor Perevertkin NTSTATUS
Init(VOID)377*8a978a17SVictor Perevertkin FxPowerIdleMachine::Init(
378*8a978a17SVictor Perevertkin VOID
379*8a978a17SVictor Perevertkin )
380*8a978a17SVictor Perevertkin {
381*8a978a17SVictor Perevertkin NTSTATUS status;
382*8a978a17SVictor Perevertkin
383*8a978a17SVictor Perevertkin //
384*8a978a17SVictor Perevertkin // For KM, event initialize always succeeds. For UM, it might fail.
385*8a978a17SVictor Perevertkin //
386*8a978a17SVictor Perevertkin status = m_D0NotificationEvent.Initialize(NotificationEvent, TRUE);
387*8a978a17SVictor Perevertkin if (!NT_SUCCESS(status)) {
388*8a978a17SVictor Perevertkin return status;
389*8a978a17SVictor Perevertkin }
390*8a978a17SVictor Perevertkin
391*8a978a17SVictor Perevertkin //
392*8a978a17SVictor Perevertkin // For KM, timer initialize always succeeds. For UM, it might fail.
393*8a978a17SVictor Perevertkin //
394*8a978a17SVictor Perevertkin status = m_PowerTimeoutTimer.Initialize(this, _PowerTimeoutDpcRoutine, 0);
395*8a978a17SVictor Perevertkin if (!NT_SUCCESS(status)) {
396*8a978a17SVictor Perevertkin return status;
397*8a978a17SVictor Perevertkin }
398*8a978a17SVictor Perevertkin
399*8a978a17SVictor Perevertkin Reset();
400*8a978a17SVictor Perevertkin
401*8a978a17SVictor Perevertkin return STATUS_SUCCESS;
402*8a978a17SVictor Perevertkin }
403*8a978a17SVictor Perevertkin
404*8a978a17SVictor Perevertkin VOID
CheckAssumptions(VOID)405*8a978a17SVictor Perevertkin FxPowerIdleMachine::CheckAssumptions(
406*8a978a17SVictor Perevertkin VOID
407*8a978a17SVictor Perevertkin )
408*8a978a17SVictor Perevertkin /*++
409*8a978a17SVictor Perevertkin
410*8a978a17SVictor Perevertkin Routine Description:
411*8a978a17SVictor Perevertkin This routine is never actually called by running code, it just has
412*8a978a17SVictor Perevertkin WDFCASSERTs who upon failure, would not allow this file to be compiled.
413*8a978a17SVictor Perevertkin
414*8a978a17SVictor Perevertkin DO NOT REMOVE THIS FUNCTION just because it is not called by any running
415*8a978a17SVictor Perevertkin code.
416*8a978a17SVictor Perevertkin
417*8a978a17SVictor Perevertkin Arguments:
418*8a978a17SVictor Perevertkin None
419*8a978a17SVictor Perevertkin
420*8a978a17SVictor Perevertkin Return Value:
421*8a978a17SVictor Perevertkin None
422*8a978a17SVictor Perevertkin
423*8a978a17SVictor Perevertkin --*/
424*8a978a17SVictor Perevertkin {
425*8a978a17SVictor Perevertkin WDFCASSERT((sizeof(m_StateTable)/sizeof(m_StateTable[0]))
426*8a978a17SVictor Perevertkin ==
427*8a978a17SVictor Perevertkin (FxIdleMax - FxIdleStopped));
428*8a978a17SVictor Perevertkin }
429*8a978a17SVictor Perevertkin
430*8a978a17SVictor Perevertkin FxPowerIdleStates
Stopped(__inout FxPowerIdleMachine * This)431*8a978a17SVictor Perevertkin FxPowerIdleMachine::Stopped(
432*8a978a17SVictor Perevertkin __inout FxPowerIdleMachine* This
433*8a978a17SVictor Perevertkin )
434*8a978a17SVictor Perevertkin /*++
435*8a978a17SVictor Perevertkin
436*8a978a17SVictor Perevertkin Routine Description:
437*8a978a17SVictor Perevertkin State machine has entered the stopped state, clear the started flag
438*8a978a17SVictor Perevertkin
439*8a978a17SVictor Perevertkin Arguments:
440*8a978a17SVictor Perevertkin This - instance of the state machine
441*8a978a17SVictor Perevertkin
442*8a978a17SVictor Perevertkin Return Value:
443*8a978a17SVictor Perevertkin FxIdleMax
444*8a978a17SVictor Perevertkin
445*8a978a17SVictor Perevertkin --*/
446*8a978a17SVictor Perevertkin {
447*8a978a17SVictor Perevertkin This->m_Flags &= ~FxPowerIdleIsStarted;
448*8a978a17SVictor Perevertkin
449*8a978a17SVictor Perevertkin return FxIdleMax;
450*8a978a17SVictor Perevertkin }
451*8a978a17SVictor Perevertkin
452*8a978a17SVictor Perevertkin FxPowerIdleStates
Started(__inout FxPowerIdleMachine * This)453*8a978a17SVictor Perevertkin FxPowerIdleMachine::Started(
454*8a978a17SVictor Perevertkin __inout FxPowerIdleMachine* This
455*8a978a17SVictor Perevertkin )
456*8a978a17SVictor Perevertkin /*++
457*8a978a17SVictor Perevertkin
458*8a978a17SVictor Perevertkin Routine Description:
459*8a978a17SVictor Perevertkin State machine has entered the started state, set the started flag
460*8a978a17SVictor Perevertkin
461*8a978a17SVictor Perevertkin Arguments:
462*8a978a17SVictor Perevertkin This - instance of the state machine
463*8a978a17SVictor Perevertkin
464*8a978a17SVictor Perevertkin Return Value:
465*8a978a17SVictor Perevertkin FxIdleMax
466*8a978a17SVictor Perevertkin
467*8a978a17SVictor Perevertkin --*/
468*8a978a17SVictor Perevertkin {
469*8a978a17SVictor Perevertkin This->m_Flags |= FxPowerIdleIsStarted;
470*8a978a17SVictor Perevertkin
471*8a978a17SVictor Perevertkin //
472*8a978a17SVictor Perevertkin // We are in the started state, but we are not powered up.
473*8a978a17SVictor Perevertkin //
474*8a978a17SVictor Perevertkin This->m_D0NotificationEvent.Clear();
475*8a978a17SVictor Perevertkin
476*8a978a17SVictor Perevertkin return FxIdleMax;
477*8a978a17SVictor Perevertkin }
478*8a978a17SVictor Perevertkin
479*8a978a17SVictor Perevertkin FxPowerIdleStates
StartedPowerUp(__inout FxPowerIdleMachine * This)480*8a978a17SVictor Perevertkin FxPowerIdleMachine::StartedPowerUp(
481*8a978a17SVictor Perevertkin __inout FxPowerIdleMachine* This
482*8a978a17SVictor Perevertkin )
483*8a978a17SVictor Perevertkin /*++
484*8a978a17SVictor Perevertkin
485*8a978a17SVictor Perevertkin Routine Description:
486*8a978a17SVictor Perevertkin We were in the started and powered off state. We are powered up,
487*8a978a17SVictor Perevertkin so set the event now so that we can wake up any waiters.
488*8a978a17SVictor Perevertkin
489*8a978a17SVictor Perevertkin Arguments:
490*8a978a17SVictor Perevertkin This - instance of the state machine
491*8a978a17SVictor Perevertkin
492*8a978a17SVictor Perevertkin Return Value:
493*8a978a17SVictor Perevertkin FxIdleDisabled
494*8a978a17SVictor Perevertkin
495*8a978a17SVictor Perevertkin --*/
496*8a978a17SVictor Perevertkin {
497*8a978a17SVictor Perevertkin //
498*8a978a17SVictor Perevertkin // Moving from the started state to the powered on state
499*8a978a17SVictor Perevertkin //
500*8a978a17SVictor Perevertkin This->SendD0Notification();
501*8a978a17SVictor Perevertkin
502*8a978a17SVictor Perevertkin return FxIdleDisabled;
503*8a978a17SVictor Perevertkin }
504*8a978a17SVictor Perevertkin
505*8a978a17SVictor Perevertkin FxPowerIdleStates
StartedPowerFailed(__inout FxPowerIdleMachine * This)506*8a978a17SVictor Perevertkin FxPowerIdleMachine::StartedPowerFailed(
507*8a978a17SVictor Perevertkin __inout FxPowerIdleMachine* This
508*8a978a17SVictor Perevertkin )
509*8a978a17SVictor Perevertkin /*++
510*8a978a17SVictor Perevertkin
511*8a978a17SVictor Perevertkin Routine Description:
512*8a978a17SVictor Perevertkin The state machine was started, but the initial power up failed. Mark the
513*8a978a17SVictor Perevertkin failure.
514*8a978a17SVictor Perevertkin
515*8a978a17SVictor Perevertkin Arguments:
516*8a978a17SVictor Perevertkin This - instance of the state machine
517*8a978a17SVictor Perevertkin
518*8a978a17SVictor Perevertkin Return Value:
519*8a978a17SVictor Perevertkin FxIdleStarted
520*8a978a17SVictor Perevertkin
521*8a978a17SVictor Perevertkin --*/
522*8a978a17SVictor Perevertkin {
523*8a978a17SVictor Perevertkin //
524*8a978a17SVictor Perevertkin // Failed to initially power up
525*8a978a17SVictor Perevertkin //
526*8a978a17SVictor Perevertkin This->m_Flags |= FxPowerIdlePowerFailed;
527*8a978a17SVictor Perevertkin
528*8a978a17SVictor Perevertkin //
529*8a978a17SVictor Perevertkin // We assume in the started state that the event is set
530*8a978a17SVictor Perevertkin //
531*8a978a17SVictor Perevertkin ASSERT(This->m_D0NotificationEvent.ReadState() == 0);
532*8a978a17SVictor Perevertkin
533*8a978a17SVictor Perevertkin return FxIdleStarted;
534*8a978a17SVictor Perevertkin }
535*8a978a17SVictor Perevertkin
536*8a978a17SVictor Perevertkin FxPowerIdleStates
Disabled(__inout FxPowerIdleMachine * This)537*8a978a17SVictor Perevertkin FxPowerIdleMachine::Disabled(
538*8a978a17SVictor Perevertkin __inout FxPowerIdleMachine* This
539*8a978a17SVictor Perevertkin )
540*8a978a17SVictor Perevertkin /*++
541*8a978a17SVictor Perevertkin
542*8a978a17SVictor Perevertkin Routine Description:
543*8a978a17SVictor Perevertkin State machine has entered the disabled state, unblock all waiters
544*8a978a17SVictor Perevertkin
545*8a978a17SVictor Perevertkin Arguments:
546*8a978a17SVictor Perevertkin This - instance of the state machine
547*8a978a17SVictor Perevertkin
548*8a978a17SVictor Perevertkin Return Value:
549*8a978a17SVictor Perevertkin FxIdleMax
550*8a978a17SVictor Perevertkin
551*8a978a17SVictor Perevertkin --*/
552*8a978a17SVictor Perevertkin
553*8a978a17SVictor Perevertkin {
554*8a978a17SVictor Perevertkin This->m_Flags &= ~FxPowerIdleTimerEnabled;
555*8a978a17SVictor Perevertkin
556*8a978a17SVictor Perevertkin return FxIdleMax;
557*8a978a17SVictor Perevertkin }
558*8a978a17SVictor Perevertkin
559*8a978a17SVictor Perevertkin FxPowerIdleStates
CheckIoCount(__inout FxPowerIdleMachine * This)560*8a978a17SVictor Perevertkin FxPowerIdleMachine::CheckIoCount(
561*8a978a17SVictor Perevertkin __inout FxPowerIdleMachine* This
562*8a978a17SVictor Perevertkin )
563*8a978a17SVictor Perevertkin /*++
564*8a978a17SVictor Perevertkin
565*8a978a17SVictor Perevertkin Routine Description:
566*8a978a17SVictor Perevertkin Checks the IO count and transitions the appropriate state. This is the
567*8a978a17SVictor Perevertkin first state we are in after being disabled or after transitioning from Dx to
568*8a978a17SVictor Perevertkin D0.
569*8a978a17SVictor Perevertkin
570*8a978a17SVictor Perevertkin Arguments:
571*8a978a17SVictor Perevertkin This - instance of the state machine
572*8a978a17SVictor Perevertkin
573*8a978a17SVictor Perevertkin Return Value:
574*8a978a17SVictor Perevertkin new state machine state
575*8a978a17SVictor Perevertkin
576*8a978a17SVictor Perevertkin --*/
577*8a978a17SVictor Perevertkin {
578*8a978a17SVictor Perevertkin This->m_Flags |= FxPowerIdleTimerEnabled;
579*8a978a17SVictor Perevertkin
580*8a978a17SVictor Perevertkin if (This->m_IoCount == 0) {
581*8a978a17SVictor Perevertkin return FxIdleStartTimer;
582*8a978a17SVictor Perevertkin }
583*8a978a17SVictor Perevertkin else {
584*8a978a17SVictor Perevertkin return FxIdleBusy;
585*8a978a17SVictor Perevertkin }
586*8a978a17SVictor Perevertkin }
587*8a978a17SVictor Perevertkin
588*8a978a17SVictor Perevertkin FxPowerIdleStates
DecrementIo(__inout FxPowerIdleMachine * This)589*8a978a17SVictor Perevertkin FxPowerIdleMachine::DecrementIo(
590*8a978a17SVictor Perevertkin __inout FxPowerIdleMachine* This
591*8a978a17SVictor Perevertkin )
592*8a978a17SVictor Perevertkin /*++
593*8a978a17SVictor Perevertkin
594*8a978a17SVictor Perevertkin Routine Description:
595*8a978a17SVictor Perevertkin Checks the IO count and returns a new state
596*8a978a17SVictor Perevertkin
597*8a978a17SVictor Perevertkin Arguments:
598*8a978a17SVictor Perevertkin This - instance of the state machine
599*8a978a17SVictor Perevertkin
600*8a978a17SVictor Perevertkin Return Value:
601*8a978a17SVictor Perevertkin new state machine state
602*8a978a17SVictor Perevertkin
603*8a978a17SVictor Perevertkin --*/
604*8a978a17SVictor Perevertkin {
605*8a978a17SVictor Perevertkin if (This->m_IoCount == 0) {
606*8a978a17SVictor Perevertkin return FxIdleStartTimer;
607*8a978a17SVictor Perevertkin }
608*8a978a17SVictor Perevertkin else {
609*8a978a17SVictor Perevertkin return FxIdleBusy;
610*8a978a17SVictor Perevertkin }
611*8a978a17SVictor Perevertkin }
612*8a978a17SVictor Perevertkin
613*8a978a17SVictor Perevertkin FxPowerIdleStates
StartTimer(__inout FxPowerIdleMachine * This)614*8a978a17SVictor Perevertkin FxPowerIdleMachine::StartTimer(
615*8a978a17SVictor Perevertkin __inout FxPowerIdleMachine* This
616*8a978a17SVictor Perevertkin )
617*8a978a17SVictor Perevertkin /*++
618*8a978a17SVictor Perevertkin
619*8a978a17SVictor Perevertkin Routine Description:
620*8a978a17SVictor Perevertkin The io count is now at zero. Start the idle timer so that when it expires,
621*8a978a17SVictor Perevertkin the device will move into Dx.
622*8a978a17SVictor Perevertkin
623*8a978a17SVictor Perevertkin Arguments:
624*8a978a17SVictor Perevertkin This - instance of the state machine
625*8a978a17SVictor Perevertkin
626*8a978a17SVictor Perevertkin Return Value:
627*8a978a17SVictor Perevertkin FxIdleMax
628*8a978a17SVictor Perevertkin
629*8a978a17SVictor Perevertkin --*/
630*8a978a17SVictor Perevertkin {
631*8a978a17SVictor Perevertkin ASSERT((This->m_Flags & FxPowerIdleTimerEnabled) && This->m_IoCount == 0);
632*8a978a17SVictor Perevertkin
633*8a978a17SVictor Perevertkin This->m_Flags |= FxPowerIdleTimerStarted;
634*8a978a17SVictor Perevertkin This->m_PowerTimeoutTimer.Start(This->m_PowerTimeout,
635*8a978a17SVictor Perevertkin m_IdleTimerTolerableDelayMS);
636*8a978a17SVictor Perevertkin
637*8a978a17SVictor Perevertkin return FxIdleTimerRunning;
638*8a978a17SVictor Perevertkin }
639*8a978a17SVictor Perevertkin
640*8a978a17SVictor Perevertkin
641*8a978a17SVictor Perevertkin FxPowerIdleStates
TimingOut(__inout FxPowerIdleMachine * This)642*8a978a17SVictor Perevertkin FxPowerIdleMachine::TimingOut(
643*8a978a17SVictor Perevertkin __inout FxPowerIdleMachine* This
644*8a978a17SVictor Perevertkin )
645*8a978a17SVictor Perevertkin /*++
646*8a978a17SVictor Perevertkin
647*8a978a17SVictor Perevertkin Routine Description:
648*8a978a17SVictor Perevertkin The idle timer has expired. Indicate to the power policy state machine
649*8a978a17SVictor Perevertkin that it should power down.
650*8a978a17SVictor Perevertkin
651*8a978a17SVictor Perevertkin Arguments:
652*8a978a17SVictor Perevertkin This - instance of the state machine
653*8a978a17SVictor Perevertkin
654*8a978a17SVictor Perevertkin Return Value:
655*8a978a17SVictor Perevertkin FxIdleTimedOut
656*8a978a17SVictor Perevertkin
657*8a978a17SVictor Perevertkin --*/
658*8a978a17SVictor Perevertkin {
659*8a978a17SVictor Perevertkin #if (FX_CORE_MODE==FX_CORE_KERNEL_MODE)
660*8a978a17SVictor Perevertkin GetPnpPkg(This)->PowerPolicyProcessEvent(PwrPolPowerTimeoutExpired);
661*8a978a17SVictor Perevertkin #else
662*8a978a17SVictor Perevertkin GetPnpPkg(This)->PowerPolicyProcessEvent(
663*8a978a17SVictor Perevertkin PwrPolPowerTimeoutExpired,
664*8a978a17SVictor Perevertkin TRUE // ProcessEventOnDifferentThread
665*8a978a17SVictor Perevertkin );
666*8a978a17SVictor Perevertkin #endif
667*8a978a17SVictor Perevertkin
668*8a978a17SVictor Perevertkin //
669*8a978a17SVictor Perevertkin // Timer is no longer running. Used when we disable the state machine and
670*8a978a17SVictor Perevertkin // need to know the timer's running state.
671*8a978a17SVictor Perevertkin //
672*8a978a17SVictor Perevertkin //
673*8a978a17SVictor Perevertkin This->m_Flags &= ~FxPowerIdleTimerStarted;
674*8a978a17SVictor Perevertkin
675*8a978a17SVictor Perevertkin //
676*8a978a17SVictor Perevertkin // While the device is still powered up, we are no longer in D0 in terms of
677*8a978a17SVictor Perevertkin // PowerReference returning immmediately if TRUE is specified to that call.
678*8a978a17SVictor Perevertkin //
679*8a978a17SVictor Perevertkin This->m_D0NotificationEvent.Clear();
680*8a978a17SVictor Perevertkin
681*8a978a17SVictor Perevertkin return FxIdleTimedOut;
682*8a978a17SVictor Perevertkin }
683*8a978a17SVictor Perevertkin
684*8a978a17SVictor Perevertkin FxPowerIdleStates
TimedOutIoIncrement(__inout FxPowerIdleMachine * This)685*8a978a17SVictor Perevertkin FxPowerIdleMachine::TimedOutIoIncrement(
686*8a978a17SVictor Perevertkin __inout FxPowerIdleMachine* This
687*8a978a17SVictor Perevertkin )
688*8a978a17SVictor Perevertkin /*++
689*8a978a17SVictor Perevertkin
690*8a978a17SVictor Perevertkin Routine Description:
691*8a978a17SVictor Perevertkin A power reference occurred after we notified the power policy machine of
692*8a978a17SVictor Perevertkin a power timeout, but before we timed out. Send an io present event to the
693*8a978a17SVictor Perevertkin power policy machine so that it can move into the D0 state/not timed out
694*8a978a17SVictor Perevertkin state again.
695*8a978a17SVictor Perevertkin
696*8a978a17SVictor Perevertkin Arguments:
697*8a978a17SVictor Perevertkin This - instance of the state machine
698*8a978a17SVictor Perevertkin
699*8a978a17SVictor Perevertkin Return Value:
700*8a978a17SVictor Perevertkin FxIdleTimedOut
701*8a978a17SVictor Perevertkin
702*8a978a17SVictor Perevertkin --*/
703*8a978a17SVictor Perevertkin {
704*8a978a17SVictor Perevertkin FxPkgPnp* pPkgPnp;
705*8a978a17SVictor Perevertkin
706*8a978a17SVictor Perevertkin pPkgPnp = GetPnpPkg(This);
707*8a978a17SVictor Perevertkin
708*8a978a17SVictor Perevertkin if (This->m_Flags & FxPowerIdleIoPresentSent) {
709*8a978a17SVictor Perevertkin DoTraceLevelMessage(
710*8a978a17SVictor Perevertkin pPkgPnp->GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGPNP,
711*8a978a17SVictor Perevertkin "WDFDEVICE %p idle (in D0) not sending io present event (already sent)",
712*8a978a17SVictor Perevertkin pPkgPnp->GetDevice()->GetHandle());
713*8a978a17SVictor Perevertkin }
714*8a978a17SVictor Perevertkin else {
715*8a978a17SVictor Perevertkin #if (FX_CORE_MODE==FX_CORE_KERNEL_MODE)
716*8a978a17SVictor Perevertkin pPkgPnp->PowerPolicyProcessEvent(PwrPolIoPresent);
717*8a978a17SVictor Perevertkin #else
718*8a978a17SVictor Perevertkin pPkgPnp->PowerPolicyProcessEvent(
719*8a978a17SVictor Perevertkin PwrPolIoPresent,
720*8a978a17SVictor Perevertkin TRUE // ProcessEventOnDifferentThread
721*8a978a17SVictor Perevertkin );
722*8a978a17SVictor Perevertkin #endif
723*8a978a17SVictor Perevertkin
724*8a978a17SVictor Perevertkin This->m_Flags |= FxPowerIdleIoPresentSent;
725*8a978a17SVictor Perevertkin }
726*8a978a17SVictor Perevertkin
727*8a978a17SVictor Perevertkin return FxIdleTimedOut;
728*8a978a17SVictor Perevertkin }
729*8a978a17SVictor Perevertkin
730*8a978a17SVictor Perevertkin FxPowerIdleStates
TimedOutPowerDown(__inout FxPowerIdleMachine * This)731*8a978a17SVictor Perevertkin FxPowerIdleMachine::TimedOutPowerDown(
732*8a978a17SVictor Perevertkin __inout FxPowerIdleMachine* This
733*8a978a17SVictor Perevertkin )
734*8a978a17SVictor Perevertkin /*++
735*8a978a17SVictor Perevertkin
736*8a978a17SVictor Perevertkin Routine Description:
737*8a978a17SVictor Perevertkin The idle timer fired and we are now powering down. Clear the flag that
738*8a978a17SVictor Perevertkin limits our sending of the io present event to one time while in the timed
739*8a978a17SVictor Perevertkin out state.
740*8a978a17SVictor Perevertkin
741*8a978a17SVictor Perevertkin Arguments:
742*8a978a17SVictor Perevertkin This - instance of the state machine
743*8a978a17SVictor Perevertkin
744*8a978a17SVictor Perevertkin Return Value:
745*8a978a17SVictor Perevertkin FxIdleGoingToDx
746*8a978a17SVictor Perevertkin
747*8a978a17SVictor Perevertkin --*/
748*8a978a17SVictor Perevertkin {
749*8a978a17SVictor Perevertkin //
750*8a978a17SVictor Perevertkin // We can send the io present event again
751*8a978a17SVictor Perevertkin //
752*8a978a17SVictor Perevertkin This->m_Flags &= ~FxPowerIdleIoPresentSent;
753*8a978a17SVictor Perevertkin
754*8a978a17SVictor Perevertkin return FxIdleGoingToDx;
755*8a978a17SVictor Perevertkin }
756*8a978a17SVictor Perevertkin
757*8a978a17SVictor Perevertkin FxPowerIdleStates
TimedOutPowerDownFailed(__inout FxPowerIdleMachine * This)758*8a978a17SVictor Perevertkin FxPowerIdleMachine::TimedOutPowerDownFailed(
759*8a978a17SVictor Perevertkin __inout FxPowerIdleMachine* This
760*8a978a17SVictor Perevertkin )
761*8a978a17SVictor Perevertkin /*++
762*8a978a17SVictor Perevertkin
763*8a978a17SVictor Perevertkin Routine Description:
764*8a978a17SVictor Perevertkin The idle timer fired and we could no power down. Clear the flag that
765*8a978a17SVictor Perevertkin limits our sending of the io present event to one time while in the timed
766*8a978a17SVictor Perevertkin out state.
767*8a978a17SVictor Perevertkin
768*8a978a17SVictor Perevertkin Arguments:
769*8a978a17SVictor Perevertkin This - instance of the state machine
770*8a978a17SVictor Perevertkin
771*8a978a17SVictor Perevertkin Return Value:
772*8a978a17SVictor Perevertkin FxIdlePowerFailed
773*8a978a17SVictor Perevertkin
774*8a978a17SVictor Perevertkin --*/
775*8a978a17SVictor Perevertkin {
776*8a978a17SVictor Perevertkin //
777*8a978a17SVictor Perevertkin // We can send the io present event again
778*8a978a17SVictor Perevertkin //
779*8a978a17SVictor Perevertkin This->m_Flags &= ~FxPowerIdleIoPresentSent;
780*8a978a17SVictor Perevertkin
781*8a978a17SVictor Perevertkin return FxIdlePowerFailed;
782*8a978a17SVictor Perevertkin }
783*8a978a17SVictor Perevertkin
784*8a978a17SVictor Perevertkin FxPowerIdleStates
GoingToDx(__inout FxPowerIdleMachine * This)785*8a978a17SVictor Perevertkin FxPowerIdleMachine::GoingToDx(
786*8a978a17SVictor Perevertkin __inout FxPowerIdleMachine* This
787*8a978a17SVictor Perevertkin )
788*8a978a17SVictor Perevertkin /*++
789*8a978a17SVictor Perevertkin
790*8a978a17SVictor Perevertkin Routine Description:
791*8a978a17SVictor Perevertkin The device is going into Dx. It could be going into Dx because the idle
792*8a978a17SVictor Perevertkin timer expired or because the machine is moving into Sx, the reason doesn't
793*8a978a17SVictor Perevertkin matter though. Clear the in D0 event.
794*8a978a17SVictor Perevertkin
795*8a978a17SVictor Perevertkin Arguments:
796*8a978a17SVictor Perevertkin This - instance of the state machine
797*8a978a17SVictor Perevertkin
798*8a978a17SVictor Perevertkin Return Value:
799*8a978a17SVictor Perevertkin FxIdleInDx
800*8a978a17SVictor Perevertkin
801*8a978a17SVictor Perevertkin --*/
802*8a978a17SVictor Perevertkin {
803*8a978a17SVictor Perevertkin This->m_D0NotificationEvent.Clear();
804*8a978a17SVictor Perevertkin return FxIdleInDx;
805*8a978a17SVictor Perevertkin }
806*8a978a17SVictor Perevertkin
807*8a978a17SVictor Perevertkin FxPowerIdleStates
InDx(__inout FxPowerIdleMachine * This)808*8a978a17SVictor Perevertkin FxPowerIdleMachine::InDx(
809*8a978a17SVictor Perevertkin __inout FxPowerIdleMachine* This
810*8a978a17SVictor Perevertkin )
811*8a978a17SVictor Perevertkin /*++
812*8a978a17SVictor Perevertkin
813*8a978a17SVictor Perevertkin Routine Description:
814*8a978a17SVictor Perevertkin The device has moved into Dx. If there is no pending io, mark the device
815*8a978a17SVictor Perevertkin as idle. We can be in Dx with pending io if IoIncrement was called after
816*8a978a17SVictor Perevertkin the device moved into Dx.
817*8a978a17SVictor Perevertkin
818*8a978a17SVictor Perevertkin Arguments:
819*8a978a17SVictor Perevertkin This - instance of the state machine
820*8a978a17SVictor Perevertkin
821*8a978a17SVictor Perevertkin Return Value:
822*8a978a17SVictor Perevertkin FxIdleMax
823*8a978a17SVictor Perevertkin
824*8a978a17SVictor Perevertkin --*/
825*8a978a17SVictor Perevertkin {
826*8a978a17SVictor Perevertkin This->m_Flags |= FxPowerIdleInDx;
827*8a978a17SVictor Perevertkin
828*8a978a17SVictor Perevertkin return FxIdleMax;
829*8a978a17SVictor Perevertkin }
830*8a978a17SVictor Perevertkin
831*8a978a17SVictor Perevertkin FxPowerIdleStates
InDxIoIncrement(__inout FxPowerIdleMachine * This)832*8a978a17SVictor Perevertkin FxPowerIdleMachine::InDxIoIncrement(
833*8a978a17SVictor Perevertkin __inout FxPowerIdleMachine* This
834*8a978a17SVictor Perevertkin )
835*8a978a17SVictor Perevertkin /*++
836*8a978a17SVictor Perevertkin
837*8a978a17SVictor Perevertkin Routine Description:
838*8a978a17SVictor Perevertkin In Dx and the io count went up. Send the event to the power policy state
839*8a978a17SVictor Perevertkin machine indicating new io is present.
840*8a978a17SVictor Perevertkin
841*8a978a17SVictor Perevertkin Arguments:
842*8a978a17SVictor Perevertkin This - instance of the state machine
843*8a978a17SVictor Perevertkin
844*8a978a17SVictor Perevertkin Return Value:
845*8a978a17SVictor Perevertkin FxIdleInDx
846*8a978a17SVictor Perevertkin
847*8a978a17SVictor Perevertkin --*/
848*8a978a17SVictor Perevertkin {
849*8a978a17SVictor Perevertkin FxPkgPnp* pPkgPnp;
850*8a978a17SVictor Perevertkin
851*8a978a17SVictor Perevertkin pPkgPnp = GetPnpPkg(This);
852*8a978a17SVictor Perevertkin
853*8a978a17SVictor Perevertkin if (This->m_Flags & FxPowerIdleIoPresentSent) {
854*8a978a17SVictor Perevertkin DoTraceLevelMessage(
855*8a978a17SVictor Perevertkin pPkgPnp->GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGPNP,
856*8a978a17SVictor Perevertkin "WDFDEVICE %p idle (in Dx) not sending io present event (already sent)",
857*8a978a17SVictor Perevertkin pPkgPnp->GetDevice()->GetHandle());
858*8a978a17SVictor Perevertkin }
859*8a978a17SVictor Perevertkin else {
860*8a978a17SVictor Perevertkin #if (FX_CORE_MODE==FX_CORE_KERNEL_MODE)
861*8a978a17SVictor Perevertkin pPkgPnp->PowerPolicyProcessEvent(PwrPolIoPresent);
862*8a978a17SVictor Perevertkin #else
863*8a978a17SVictor Perevertkin pPkgPnp->PowerPolicyProcessEvent(
864*8a978a17SVictor Perevertkin PwrPolIoPresent,
865*8a978a17SVictor Perevertkin TRUE // ProcessEventOnDifferentThread
866*8a978a17SVictor Perevertkin );
867*8a978a17SVictor Perevertkin #endif
868*8a978a17SVictor Perevertkin This->m_Flags |= FxPowerIdleIoPresentSent;
869*8a978a17SVictor Perevertkin }
870*8a978a17SVictor Perevertkin
871*8a978a17SVictor Perevertkin return FxIdleInDx;
872*8a978a17SVictor Perevertkin }
873*8a978a17SVictor Perevertkin
874*8a978a17SVictor Perevertkin FxPowerIdleStates
InDxPowerUpFailure(__inout FxPowerIdleMachine * This)875*8a978a17SVictor Perevertkin FxPowerIdleMachine::InDxPowerUpFailure(
876*8a978a17SVictor Perevertkin __inout FxPowerIdleMachine* This
877*8a978a17SVictor Perevertkin )
878*8a978a17SVictor Perevertkin /*++
879*8a978a17SVictor Perevertkin
880*8a978a17SVictor Perevertkin Routine Description:
881*8a978a17SVictor Perevertkin Device is in Dx and there was a failure in the power up path. The device
882*8a978a17SVictor Perevertkin is no longer idle, even though it is stil in Dx.
883*8a978a17SVictor Perevertkin
884*8a978a17SVictor Perevertkin Arguments:
885*8a978a17SVictor Perevertkin This - instance of the state machine
886*8a978a17SVictor Perevertkin
887*8a978a17SVictor Perevertkin Return Value:
888*8a978a17SVictor Perevertkin FxIdlePowerFailed
889*8a978a17SVictor Perevertkin
890*8a978a17SVictor Perevertkin --*/
891*8a978a17SVictor Perevertkin {
892*8a978a17SVictor Perevertkin //
893*8a978a17SVictor Perevertkin // FxPowerIdleInDx - We are no longer in Dx
894*8a978a17SVictor Perevertkin // FxPowerIdleIoPresentSent = We can send the io present event again
895*8a978a17SVictor Perevertkin //
896*8a978a17SVictor Perevertkin This->m_Flags &= ~(FxPowerIdleInDx | FxPowerIdleIoPresentSent);
897*8a978a17SVictor Perevertkin
898*8a978a17SVictor Perevertkin return FxIdlePowerFailed;
899*8a978a17SVictor Perevertkin }
900*8a978a17SVictor Perevertkin
901*8a978a17SVictor Perevertkin FxPowerIdleStates
InDxStopped(__inout FxPowerIdleMachine * This)902*8a978a17SVictor Perevertkin FxPowerIdleMachine::InDxStopped(
903*8a978a17SVictor Perevertkin __inout FxPowerIdleMachine* This
904*8a978a17SVictor Perevertkin )
905*8a978a17SVictor Perevertkin /*++
906*8a978a17SVictor Perevertkin
907*8a978a17SVictor Perevertkin Routine Description:
908*8a978a17SVictor Perevertkin The state machine was stopped while in the Dx state. When the machine is in
909*8a978a17SVictor Perevertkin the stopped state, the notification event is in the signaled state.
910*8a978a17SVictor Perevertkin
911*8a978a17SVictor Perevertkin Arguments:
912*8a978a17SVictor Perevertkin This - instance of the state machine
913*8a978a17SVictor Perevertkin
914*8a978a17SVictor Perevertkin Return Value:
915*8a978a17SVictor Perevertkin FxIdleStopped
916*8a978a17SVictor Perevertkin
917*8a978a17SVictor Perevertkin --*/
918*8a978a17SVictor Perevertkin {
919*8a978a17SVictor Perevertkin //
920*8a978a17SVictor Perevertkin // When the machine is in the stopped state, the notification event is in
921*8a978a17SVictor Perevertkin // the signaled state.
922*8a978a17SVictor Perevertkin //
923*8a978a17SVictor Perevertkin This->SendD0Notification();
924*8a978a17SVictor Perevertkin
925*8a978a17SVictor Perevertkin //
926*8a978a17SVictor Perevertkin // We are not longer idle since we are not in the Dx state anymore
927*8a978a17SVictor Perevertkin //
928*8a978a17SVictor Perevertkin This->m_Flags &= ~FxPowerIdleInDx;
929*8a978a17SVictor Perevertkin
930*8a978a17SVictor Perevertkin //
931*8a978a17SVictor Perevertkin // We are no longer enabled since we are stopped from the Dx state
932*8a978a17SVictor Perevertkin //
933*8a978a17SVictor Perevertkin This->m_Flags &= ~FxPowerIdleTimerEnabled;
934*8a978a17SVictor Perevertkin
935*8a978a17SVictor Perevertkin //
936*8a978a17SVictor Perevertkin // We can send the io present event again
937*8a978a17SVictor Perevertkin //
938*8a978a17SVictor Perevertkin This->m_Flags &= ~FxPowerIdleIoPresentSent;
939*8a978a17SVictor Perevertkin
940*8a978a17SVictor Perevertkin return FxIdleStopped;
941*8a978a17SVictor Perevertkin }
942*8a978a17SVictor Perevertkin
943*8a978a17SVictor Perevertkin FxPowerIdleStates
InDxDisabled(__inout FxPowerIdleMachine * This)944*8a978a17SVictor Perevertkin FxPowerIdleMachine::InDxDisabled(
945*8a978a17SVictor Perevertkin __inout FxPowerIdleMachine* This
946*8a978a17SVictor Perevertkin )
947*8a978a17SVictor Perevertkin /*++
948*8a978a17SVictor Perevertkin
949*8a978a17SVictor Perevertkin Routine Description:
950*8a978a17SVictor Perevertkin The device is in Dx and the state machine is being disabled (most likely due
951*8a978a17SVictor Perevertkin to a surprise remove).
952*8a978a17SVictor Perevertkin
953*8a978a17SVictor Perevertkin Arguments:
954*8a978a17SVictor Perevertkin This - instance of the state machine
955*8a978a17SVictor Perevertkin
956*8a978a17SVictor Perevertkin Return Value:
957*8a978a17SVictor Perevertkin FxIdleDisabled
958*8a978a17SVictor Perevertkin
959*8a978a17SVictor Perevertkin --*/
960*8a978a17SVictor Perevertkin {
961*8a978a17SVictor Perevertkin //
962*8a978a17SVictor Perevertkin // Idle timer is being disabled while in Dx. Remain in Dx.
963*8a978a17SVictor Perevertkin //
964*8a978a17SVictor Perevertkin This->m_Flags &= ~FxPowerIdleTimerEnabled;
965*8a978a17SVictor Perevertkin
966*8a978a17SVictor Perevertkin return FxIdleInDx;
967*8a978a17SVictor Perevertkin }
968*8a978a17SVictor Perevertkin
969*8a978a17SVictor Perevertkin FxPowerIdleStates
InDxEnabled(__inout FxPowerIdleMachine * This)970*8a978a17SVictor Perevertkin FxPowerIdleMachine::InDxEnabled(
971*8a978a17SVictor Perevertkin __inout FxPowerIdleMachine* This
972*8a978a17SVictor Perevertkin )
973*8a978a17SVictor Perevertkin /*++
974*8a978a17SVictor Perevertkin
975*8a978a17SVictor Perevertkin Routine Description:
976*8a978a17SVictor Perevertkin The device is in Dx and the state machine is being enabled (most like due
977*8a978a17SVictor Perevertkin to trying to remain in Dx after Sx->S0.
978*8a978a17SVictor Perevertkin
979*8a978a17SVictor Perevertkin Arguments:
980*8a978a17SVictor Perevertkin This - instance of the state machine
981*8a978a17SVictor Perevertkin
982*8a978a17SVictor Perevertkin Return Value:
983*8a978a17SVictor Perevertkin FxIdleInDx
984*8a978a17SVictor Perevertkin
985*8a978a17SVictor Perevertkin --*/
986*8a978a17SVictor Perevertkin {
987*8a978a17SVictor Perevertkin //
988*8a978a17SVictor Perevertkin // Idle timer is being enabled while in Dx. Remain in Dx.
989*8a978a17SVictor Perevertkin //
990*8a978a17SVictor Perevertkin This->m_Flags |= FxPowerIdleTimerEnabled;
991*8a978a17SVictor Perevertkin
992*8a978a17SVictor Perevertkin return FxIdleInDx;
993*8a978a17SVictor Perevertkin }
994*8a978a17SVictor Perevertkin
995*8a978a17SVictor Perevertkin FxPowerIdleStates
PowerUp(__inout FxPowerIdleMachine * This)996*8a978a17SVictor Perevertkin FxPowerIdleMachine::PowerUp(
997*8a978a17SVictor Perevertkin __inout FxPowerIdleMachine* This
998*8a978a17SVictor Perevertkin )
999*8a978a17SVictor Perevertkin /*++
1000*8a978a17SVictor Perevertkin
1001*8a978a17SVictor Perevertkin Routine Description:
1002*8a978a17SVictor Perevertkin The device powered up enough to where we can let waiters go and start pounding
1003*8a978a17SVictor Perevertkin on their hardware.
1004*8a978a17SVictor Perevertkin
1005*8a978a17SVictor Perevertkin Arguments:
1006*8a978a17SVictor Perevertkin This - instance of the state machine
1007*8a978a17SVictor Perevertkin
1008*8a978a17SVictor Perevertkin Return Value:
1009*8a978a17SVictor Perevertkin FxIdlePowerUpComplete
1010*8a978a17SVictor Perevertkin
1011*8a978a17SVictor Perevertkin --*/
1012*8a978a17SVictor Perevertkin {
1013*8a978a17SVictor Perevertkin //
1014*8a978a17SVictor Perevertkin // FxPowerIdleInDx - we are not longer idle since we are not in the Dx state
1015*8a978a17SVictor Perevertkin // anymore
1016*8a978a17SVictor Perevertkin // FxPowerIdleIoPresentSent - We can send the io present event again
1017*8a978a17SVictor Perevertkin //
1018*8a978a17SVictor Perevertkin This->m_Flags &= ~(FxPowerIdleInDx | FxPowerIdleIoPresentSent);
1019*8a978a17SVictor Perevertkin
1020*8a978a17SVictor Perevertkin This->SendD0Notification();
1021*8a978a17SVictor Perevertkin
1022*8a978a17SVictor Perevertkin return FxIdlePowerUpComplete;
1023*8a978a17SVictor Perevertkin }
1024*8a978a17SVictor Perevertkin
1025*8a978a17SVictor Perevertkin FxPowerIdleStates
PowerUpComplete(__inout FxPowerIdleMachine * This)1026*8a978a17SVictor Perevertkin FxPowerIdleMachine::PowerUpComplete(
1027*8a978a17SVictor Perevertkin __inout FxPowerIdleMachine* This
1028*8a978a17SVictor Perevertkin )
1029*8a978a17SVictor Perevertkin /*++
1030*8a978a17SVictor Perevertkin
1031*8a978a17SVictor Perevertkin Routine Description:
1032*8a978a17SVictor Perevertkin The device is moving into D0, determine which D0 state to move into
1033*8a978a17SVictor Perevertkin based on the enabled state and io count.
1034*8a978a17SVictor Perevertkin
1035*8a978a17SVictor Perevertkin Arguments:
1036*8a978a17SVictor Perevertkin This - instance of the state machine
1037*8a978a17SVictor Perevertkin
1038*8a978a17SVictor Perevertkin Return Value:
1039*8a978a17SVictor Perevertkin new state
1040*8a978a17SVictor Perevertkin
1041*8a978a17SVictor Perevertkin --*/
1042*8a978a17SVictor Perevertkin {
1043*8a978a17SVictor Perevertkin if (This->m_Flags & FxPowerIdleTimerEnabled) {
1044*8a978a17SVictor Perevertkin if (This->m_Flags & FxPowerIdleTimerStarted) {
1045*8a978a17SVictor Perevertkin COVERAGE_TRAP();
1046*8a978a17SVictor Perevertkin return FxIdleTimerRunning;
1047*8a978a17SVictor Perevertkin }
1048*8a978a17SVictor Perevertkin else {
1049*8a978a17SVictor Perevertkin return FxIdleCheckIoCount;
1050*8a978a17SVictor Perevertkin }
1051*8a978a17SVictor Perevertkin }
1052*8a978a17SVictor Perevertkin else {
1053*8a978a17SVictor Perevertkin //
1054*8a978a17SVictor Perevertkin // Not enabled, better not have a timer running
1055*8a978a17SVictor Perevertkin //
1056*8a978a17SVictor Perevertkin ASSERT((This->m_Flags & FxPowerIdleTimerStarted) == 0);
1057*8a978a17SVictor Perevertkin
1058*8a978a17SVictor Perevertkin return FxIdleDisabled;
1059*8a978a17SVictor Perevertkin }
1060*8a978a17SVictor Perevertkin }
1061*8a978a17SVictor Perevertkin
1062*8a978a17SVictor Perevertkin FxPowerIdleStates
TimedOutDisabled(__inout FxPowerIdleMachine * This)1063*8a978a17SVictor Perevertkin FxPowerIdleMachine::TimedOutDisabled(
1064*8a978a17SVictor Perevertkin __inout FxPowerIdleMachine* This
1065*8a978a17SVictor Perevertkin )
1066*8a978a17SVictor Perevertkin /*++
1067*8a978a17SVictor Perevertkin
1068*8a978a17SVictor Perevertkin Routine Description:
1069*8a978a17SVictor Perevertkin The power idle state machine is moving into the disabled state. Set the
1070*8a978a17SVictor Perevertkin D0 event.
1071*8a978a17SVictor Perevertkin
1072*8a978a17SVictor Perevertkin Arguments:
1073*8a978a17SVictor Perevertkin This - instance of the state machine
1074*8a978a17SVictor Perevertkin
1075*8a978a17SVictor Perevertkin Return Value:
1076*8a978a17SVictor Perevertkin FxIdleDisabled
1077*8a978a17SVictor Perevertkin
1078*8a978a17SVictor Perevertkin --*/
1079*8a978a17SVictor Perevertkin {
1080*8a978a17SVictor Perevertkin //
1081*8a978a17SVictor Perevertkin // Notify any waiters that we are now in D0
1082*8a978a17SVictor Perevertkin //
1083*8a978a17SVictor Perevertkin This->SendD0Notification();
1084*8a978a17SVictor Perevertkin
1085*8a978a17SVictor Perevertkin //
1086*8a978a17SVictor Perevertkin // We can send the io present event again
1087*8a978a17SVictor Perevertkin //
1088*8a978a17SVictor Perevertkin This->m_Flags &= ~FxPowerIdleIoPresentSent;
1089*8a978a17SVictor Perevertkin
1090*8a978a17SVictor Perevertkin return FxIdleDisabled;
1091*8a978a17SVictor Perevertkin }
1092*8a978a17SVictor Perevertkin
1093*8a978a17SVictor Perevertkin FxPowerIdleStates
TimedOutEnabled(__inout FxPowerIdleMachine * This)1094*8a978a17SVictor Perevertkin FxPowerIdleMachine::TimedOutEnabled(
1095*8a978a17SVictor Perevertkin __inout FxPowerIdleMachine* This
1096*8a978a17SVictor Perevertkin )
1097*8a978a17SVictor Perevertkin {
1098*8a978a17SVictor Perevertkin //
1099*8a978a17SVictor Perevertkin // Notify any waiters that we are now in D0
1100*8a978a17SVictor Perevertkin //
1101*8a978a17SVictor Perevertkin This->SendD0Notification();
1102*8a978a17SVictor Perevertkin
1103*8a978a17SVictor Perevertkin //
1104*8a978a17SVictor Perevertkin // We can send the io present event again
1105*8a978a17SVictor Perevertkin //
1106*8a978a17SVictor Perevertkin This->m_Flags &= ~FxPowerIdleIoPresentSent;
1107*8a978a17SVictor Perevertkin
1108*8a978a17SVictor Perevertkin return FxIdleCheckIoCount;
1109*8a978a17SVictor Perevertkin }
1110*8a978a17SVictor Perevertkin
1111*8a978a17SVictor Perevertkin FxPowerIdleStates
CancelTimer(__inout FxPowerIdleMachine * This)1112*8a978a17SVictor Perevertkin FxPowerIdleMachine::CancelTimer(
1113*8a978a17SVictor Perevertkin __inout FxPowerIdleMachine* This
1114*8a978a17SVictor Perevertkin )
1115*8a978a17SVictor Perevertkin /*++
1116*8a978a17SVictor Perevertkin
1117*8a978a17SVictor Perevertkin Routine Description:
1118*8a978a17SVictor Perevertkin The timer is running and we need to cancel it because of an io increment or
1119*8a978a17SVictor Perevertkin the state machine being disabled.
1120*8a978a17SVictor Perevertkin
1121*8a978a17SVictor Perevertkin Arguments:
1122*8a978a17SVictor Perevertkin This - instance of the state machine
1123*8a978a17SVictor Perevertkin
1124*8a978a17SVictor Perevertkin Return Value:
1125*8a978a17SVictor Perevertkin new state
1126*8a978a17SVictor Perevertkin
1127*8a978a17SVictor Perevertkin --*/
1128*8a978a17SVictor Perevertkin {
1129*8a978a17SVictor Perevertkin if (This->CancelIdleTimer()) {
1130*8a978a17SVictor Perevertkin return FxIdleCheckIoCount;
1131*8a978a17SVictor Perevertkin }
1132*8a978a17SVictor Perevertkin else {
1133*8a978a17SVictor Perevertkin return FxIdleWaitForTimeout;
1134*8a978a17SVictor Perevertkin }
1135*8a978a17SVictor Perevertkin }
1136*8a978a17SVictor Perevertkin
1137*8a978a17SVictor Perevertkin FxPowerIdleStates
TimerExpired(__inout FxPowerIdleMachine * This)1138*8a978a17SVictor Perevertkin FxPowerIdleMachine::TimerExpired(
1139*8a978a17SVictor Perevertkin __inout FxPowerIdleMachine* This
1140*8a978a17SVictor Perevertkin )
1141*8a978a17SVictor Perevertkin /*++
1142*8a978a17SVictor Perevertkin
1143*8a978a17SVictor Perevertkin Routine Description:
1144*8a978a17SVictor Perevertkin The timer was not canceled because it was running. The timer has now
1145*8a978a17SVictor Perevertkin fired, so we can move forward.
1146*8a978a17SVictor Perevertkin
1147*8a978a17SVictor Perevertkin Arguments:
1148*8a978a17SVictor Perevertkin This - instance of the state machine
1149*8a978a17SVictor Perevertkin
1150*8a978a17SVictor Perevertkin Return Value:
1151*8a978a17SVictor Perevertkin FxIdleCheckIoCount
1152*8a978a17SVictor Perevertkin
1153*8a978a17SVictor Perevertkin --*/
1154*8a978a17SVictor Perevertkin {
1155*8a978a17SVictor Perevertkin This->m_Flags &= ~FxPowerIdleTimerStarted;
1156*8a978a17SVictor Perevertkin
1157*8a978a17SVictor Perevertkin return FxIdleCheckIoCount;
1158*8a978a17SVictor Perevertkin }
1159*8a978a17SVictor Perevertkin
1160*8a978a17SVictor Perevertkin FxPowerIdleStates
Disabling(__inout FxPowerIdleMachine * This)1161*8a978a17SVictor Perevertkin FxPowerIdleMachine::Disabling(
1162*8a978a17SVictor Perevertkin __inout FxPowerIdleMachine* This
1163*8a978a17SVictor Perevertkin )
1164*8a978a17SVictor Perevertkin /*++
1165*8a978a17SVictor Perevertkin
1166*8a978a17SVictor Perevertkin Routine Description:
1167*8a978a17SVictor Perevertkin Timer is running and the state machine is being disabled. Cancel the idle
1168*8a978a17SVictor Perevertkin timer.
1169*8a978a17SVictor Perevertkin
1170*8a978a17SVictor Perevertkin Arguments:
1171*8a978a17SVictor Perevertkin This - instance of the state machine
1172*8a978a17SVictor Perevertkin
1173*8a978a17SVictor Perevertkin Return Value:
1174*8a978a17SVictor Perevertkin new state
1175*8a978a17SVictor Perevertkin
1176*8a978a17SVictor Perevertkin --*/
1177*8a978a17SVictor Perevertkin {
1178*8a978a17SVictor Perevertkin if (This->CancelIdleTimer()) {
1179*8a978a17SVictor Perevertkin return FxIdleDisabled;
1180*8a978a17SVictor Perevertkin }
1181*8a978a17SVictor Perevertkin else {
1182*8a978a17SVictor Perevertkin return FxIdleDisablingWaitForTimeout;
1183*8a978a17SVictor Perevertkin }
1184*8a978a17SVictor Perevertkin }
1185*8a978a17SVictor Perevertkin
1186*8a978a17SVictor Perevertkin FxPowerIdleStates
DisablingTimerExpired(__inout FxPowerIdleMachine * This)1187*8a978a17SVictor Perevertkin FxPowerIdleMachine::DisablingTimerExpired(
1188*8a978a17SVictor Perevertkin __inout FxPowerIdleMachine* This
1189*8a978a17SVictor Perevertkin )
1190*8a978a17SVictor Perevertkin /*++
1191*8a978a17SVictor Perevertkin
1192*8a978a17SVictor Perevertkin Routine Description:
1193*8a978a17SVictor Perevertkin When disabling the state machine, the timer could not be canceled. The
1194*8a978a17SVictor Perevertkin timer has now expired and the state machine can move forward.
1195*8a978a17SVictor Perevertkin
1196*8a978a17SVictor Perevertkin Arguments:
1197*8a978a17SVictor Perevertkin This - instance of the state machine
1198*8a978a17SVictor Perevertkin
1199*8a978a17SVictor Perevertkin Return Value:
1200*8a978a17SVictor Perevertkin FxIdleDisabled
1201*8a978a17SVictor Perevertkin
1202*8a978a17SVictor Perevertkin --*/
1203*8a978a17SVictor Perevertkin {
1204*8a978a17SVictor Perevertkin This->m_Flags &= ~FxPowerIdleTimerStarted;
1205*8a978a17SVictor Perevertkin
1206*8a978a17SVictor Perevertkin #if (FX_CORE_MODE==FX_CORE_KERNEL_MODE)
1207*8a978a17SVictor Perevertkin GetPnpPkg(This)->PowerPolicyProcessEvent(PwrPolPowerTimeoutExpired);
1208*8a978a17SVictor Perevertkin #else
1209*8a978a17SVictor Perevertkin GetPnpPkg(This)->PowerPolicyProcessEvent(
1210*8a978a17SVictor Perevertkin PwrPolPowerTimeoutExpired,
1211*8a978a17SVictor Perevertkin TRUE // ProcessEventOnDifferentThread
1212*8a978a17SVictor Perevertkin );
1213*8a978a17SVictor Perevertkin #endif
1214*8a978a17SVictor Perevertkin
1215*8a978a17SVictor Perevertkin return FxIdleDisabled;
1216*8a978a17SVictor Perevertkin }
1217*8a978a17SVictor Perevertkin
1218*8a978a17SVictor Perevertkin FxPowerIdleStates
PowerFailed(__inout FxPowerIdleMachine * This)1219*8a978a17SVictor Perevertkin FxPowerIdleMachine::PowerFailed(
1220*8a978a17SVictor Perevertkin __inout FxPowerIdleMachine* This
1221*8a978a17SVictor Perevertkin )
1222*8a978a17SVictor Perevertkin /*++
1223*8a978a17SVictor Perevertkin
1224*8a978a17SVictor Perevertkin Routine Description:
1225*8a978a17SVictor Perevertkin A power operation (up or down) failed. Mark the machine as failed so that
1226*8a978a17SVictor Perevertkin PowerReference will fail properly.
1227*8a978a17SVictor Perevertkin
1228*8a978a17SVictor Perevertkin Arguments:
1229*8a978a17SVictor Perevertkin This - instance of the state machine
1230*8a978a17SVictor Perevertkin
1231*8a978a17SVictor Perevertkin Return Value:
1232*8a978a17SVictor Perevertkin FxIdleDisabled
1233*8a978a17SVictor Perevertkin
1234*8a978a17SVictor Perevertkin --*/
1235*8a978a17SVictor Perevertkin {
1236*8a978a17SVictor Perevertkin //
1237*8a978a17SVictor Perevertkin // By this time, the timer should be stopped
1238*8a978a17SVictor Perevertkin //
1239*8a978a17SVictor Perevertkin ASSERT((This->m_Flags & FxPowerIdleTimerStarted) == 0);
1240*8a978a17SVictor Perevertkin
1241*8a978a17SVictor Perevertkin This->m_Flags |= FxPowerIdlePowerFailed;
1242*8a978a17SVictor Perevertkin
1243*8a978a17SVictor Perevertkin //
1244*8a978a17SVictor Perevertkin // We are no longer enabled to time out since we are in a failed state
1245*8a978a17SVictor Perevertkin //
1246*8a978a17SVictor Perevertkin This->m_Flags &= ~FxPowerIdleTimerEnabled;
1247*8a978a17SVictor Perevertkin
1248*8a978a17SVictor Perevertkin //
1249*8a978a17SVictor Perevertkin // Wake up any waiters and indicate failure to them.
1250*8a978a17SVictor Perevertkin //
1251*8a978a17SVictor Perevertkin This->SendD0Notification();
1252*8a978a17SVictor Perevertkin
1253*8a978a17SVictor Perevertkin return FxIdleDisabled;
1254*8a978a17SVictor Perevertkin }
1255*8a978a17SVictor Perevertkin
1256*8a978a17SVictor Perevertkin __drv_maxIRQL(DISPATCH_LEVEL)
__drv_minIRQL(DISPATCH_LEVEL)1257*8a978a17SVictor Perevertkin __drv_minIRQL(DISPATCH_LEVEL)
1258*8a978a17SVictor Perevertkin __drv_requiresIRQL(DISPATCH_LEVEL)
1259*8a978a17SVictor Perevertkin __drv_sameIRQL
1260*8a978a17SVictor Perevertkin VOID
1261*8a978a17SVictor Perevertkin FxPowerIdleMachine::_PowerTimeoutDpcRoutine(
1262*8a978a17SVictor Perevertkin __in PKDPC Dpc,
1263*8a978a17SVictor Perevertkin __in_opt PVOID Context,
1264*8a978a17SVictor Perevertkin __in_opt PVOID SystemArgument1,
1265*8a978a17SVictor Perevertkin __in_opt PVOID SystemArgument2
1266*8a978a17SVictor Perevertkin )
1267*8a978a17SVictor Perevertkin /*++
1268*8a978a17SVictor Perevertkin
1269*8a978a17SVictor Perevertkin Routine Description:
1270*8a978a17SVictor Perevertkin Timer DPC which posts the timeout expired event to the power policy state
1271*8a978a17SVictor Perevertkin machine
1272*8a978a17SVictor Perevertkin
1273*8a978a17SVictor Perevertkin Arguments:
1274*8a978a17SVictor Perevertkin Dpc - DPC
1275*8a978a17SVictor Perevertkin Context, SysArg1, SysArg2 - Unused
1276*8a978a17SVictor Perevertkin
1277*8a978a17SVictor Perevertkin Return Value:
1278*8a978a17SVictor Perevertkin None
1279*8a978a17SVictor Perevertkin
1280*8a978a17SVictor Perevertkin --*/
1281*8a978a17SVictor Perevertkin {
1282*8a978a17SVictor Perevertkin FxPowerIdleMachine* pThis;
1283*8a978a17SVictor Perevertkin
1284*8a978a17SVictor Perevertkin UNREFERENCED_PARAMETER(Dpc);
1285*8a978a17SVictor Perevertkin UNREFERENCED_PARAMETER(SystemArgument1);
1286*8a978a17SVictor Perevertkin UNREFERENCED_PARAMETER(SystemArgument2);
1287*8a978a17SVictor Perevertkin
1288*8a978a17SVictor Perevertkin pThis = (FxPowerIdleMachine*) Context;
1289*8a978a17SVictor Perevertkin
1290*8a978a17SVictor Perevertkin pThis->m_Lock.AcquireAtDpcLevel();
1291*8a978a17SVictor Perevertkin pThis->ProcessEventLocked(PowerIdleEventTimerExpired);
1292*8a978a17SVictor Perevertkin
1293*8a978a17SVictor Perevertkin #if FX_IS_KERNEL_MODE
1294*8a978a17SVictor Perevertkin PFX_DRIVER_GLOBALS pFxDriverGlobals;
1295*8a978a17SVictor Perevertkin PFN_WDF_DRIVER_DEVICE_ADD pDriverDeviceAdd;
1296*8a978a17SVictor Perevertkin
1297*8a978a17SVictor Perevertkin pFxDriverGlobals = GetPnpPkg(pThis)->GetDriverGlobals();
1298*8a978a17SVictor Perevertkin
1299*8a978a17SVictor Perevertkin //
1300*8a978a17SVictor Perevertkin // We need to provide XPerf with a symbol of the client to figure out
1301*8a978a17SVictor Perevertkin // which component this idle timer is for. Since AddDevice is always there
1302*8a978a17SVictor Perevertkin // we use that to pass the symbol along.
1303*8a978a17SVictor Perevertkin //
1304*8a978a17SVictor Perevertkin pDriverDeviceAdd = pFxDriverGlobals->Driver->GetDriverDeviceAddMethod();
1305*8a978a17SVictor Perevertkin
1306*8a978a17SVictor Perevertkin FxPerfTraceDpc(&pDriverDeviceAdd);
1307*8a978a17SVictor Perevertkin #endif
1308*8a978a17SVictor Perevertkin
1309*8a978a17SVictor Perevertkin pThis->m_Lock.ReleaseFromDpcLevel();
1310*8a978a17SVictor Perevertkin }
1311*8a978a17SVictor Perevertkin
1312*8a978a17SVictor Perevertkin VOID
Reset(VOID)1313*8a978a17SVictor Perevertkin FxPowerIdleMachine::Reset(
1314*8a978a17SVictor Perevertkin VOID
1315*8a978a17SVictor Perevertkin )
1316*8a978a17SVictor Perevertkin /*++
1317*8a978a17SVictor Perevertkin
1318*8a978a17SVictor Perevertkin Routine Description:
1319*8a978a17SVictor Perevertkin Reset the state machine to a known state on a PDO restart.
1320*8a978a17SVictor Perevertkin
1321*8a978a17SVictor Perevertkin Arguments:
1322*8a978a17SVictor Perevertkin None
1323*8a978a17SVictor Perevertkin
1324*8a978a17SVictor Perevertkin Return Value:
1325*8a978a17SVictor Perevertkin None
1326*8a978a17SVictor Perevertkin
1327*8a978a17SVictor Perevertkin --*/
1328*8a978a17SVictor Perevertkin {
1329*8a978a17SVictor Perevertkin FxPkgPnp* pPkgPnp;
1330*8a978a17SVictor Perevertkin PFX_DRIVER_GLOBALS pFxDriverGlobals;
1331*8a978a17SVictor Perevertkin
1332*8a978a17SVictor Perevertkin ASSERT(m_CurrentIdleState == FxIdleStopped);
1333*8a978a17SVictor Perevertkin
1334*8a978a17SVictor Perevertkin m_IoCount = 0;
1335*8a978a17SVictor Perevertkin m_Flags = 0x0;
1336*8a978a17SVictor Perevertkin
1337*8a978a17SVictor Perevertkin pPkgPnp = GetPnpPkg(this);
1338*8a978a17SVictor Perevertkin pFxDriverGlobals = pPkgPnp->GetDriverGlobals();
1339*8a978a17SVictor Perevertkin
1340*8a978a17SVictor Perevertkin if (pFxDriverGlobals->DebugExtension != NULL &&
1341*8a978a17SVictor Perevertkin pFxDriverGlobals->DebugExtension->TrackPower != FxTrackPowerNone) {
1342*8a978a17SVictor Perevertkin //
1343*8a978a17SVictor Perevertkin // Ignore potential failure, power ref tracking is not an essential feature.
1344*8a978a17SVictor Perevertkin //
1345*8a978a17SVictor Perevertkin (void)FxTagTracker::CreateAndInitialize(&m_TagTracker,
1346*8a978a17SVictor Perevertkin pFxDriverGlobals,
1347*8a978a17SVictor Perevertkin FxTagTrackerTypePower,
1348*8a978a17SVictor Perevertkin pFxDriverGlobals->DebugExtension->TrackPower == FxTrackPowerRefsAndStack,
1349*8a978a17SVictor Perevertkin pPkgPnp->GetDevice());
1350*8a978a17SVictor Perevertkin }
1351*8a978a17SVictor Perevertkin
1352*8a978a17SVictor Perevertkin SendD0Notification();
1353*8a978a17SVictor Perevertkin }
1354*8a978a17SVictor Perevertkin
1355*8a978a17SVictor Perevertkin VOID
EnableTimer(VOID)1356*8a978a17SVictor Perevertkin FxPowerIdleMachine::EnableTimer(
1357*8a978a17SVictor Perevertkin VOID
1358*8a978a17SVictor Perevertkin )
1359*8a978a17SVictor Perevertkin /*++
1360*8a978a17SVictor Perevertkin
1361*8a978a17SVictor Perevertkin Routine Description:
1362*8a978a17SVictor Perevertkin Public function that the power policy state machine uses to put this state
1363*8a978a17SVictor Perevertkin machine in to an enabled state and potentially start the idle timer.
1364*8a978a17SVictor Perevertkin
1365*8a978a17SVictor Perevertkin Arguments:
1366*8a978a17SVictor Perevertkin None
1367*8a978a17SVictor Perevertkin
1368*8a978a17SVictor Perevertkin Return Value:
1369*8a978a17SVictor Perevertkin None
1370*8a978a17SVictor Perevertkin
1371*8a978a17SVictor Perevertkin --*/
1372*8a978a17SVictor Perevertkin {
1373*8a978a17SVictor Perevertkin KIRQL irql;
1374*8a978a17SVictor Perevertkin
1375*8a978a17SVictor Perevertkin m_Lock.Acquire(&irql);
1376*8a978a17SVictor Perevertkin ProcessEventLocked(PowerIdleEventEnabled);
1377*8a978a17SVictor Perevertkin m_Lock.Release(irql);
1378*8a978a17SVictor Perevertkin }
1379*8a978a17SVictor Perevertkin
1380*8a978a17SVictor Perevertkin BOOLEAN
DisableTimer(VOID)1381*8a978a17SVictor Perevertkin FxPowerIdleMachine::DisableTimer(
1382*8a978a17SVictor Perevertkin VOID
1383*8a978a17SVictor Perevertkin )
1384*8a978a17SVictor Perevertkin /*++
1385*8a978a17SVictor Perevertkin
1386*8a978a17SVictor Perevertkin Routine Description:
1387*8a978a17SVictor Perevertkin Public function which the power policy state machine uses to put this state
1388*8a978a17SVictor Perevertkin machine into a disabled state. If necessary, the state machine will attempt
1389*8a978a17SVictor Perevertkin to cancel the idle timer.
1390*8a978a17SVictor Perevertkin
1391*8a978a17SVictor Perevertkin Arguments:
1392*8a978a17SVictor Perevertkin None
1393*8a978a17SVictor Perevertkin
1394*8a978a17SVictor Perevertkin Return Value:
1395*8a978a17SVictor Perevertkin TRUE if the idle timer was cancelled and the caller may proceed directly to
1396*8a978a17SVictor Perevertkin its new state
1397*8a978a17SVictor Perevertkin
1398*8a978a17SVictor Perevertkin FALSE if the idle timer was not cancelled and the caller must wait for the
1399*8a978a17SVictor Perevertkin io timeout event to be posted before proceeding.
1400*8a978a17SVictor Perevertkin
1401*8a978a17SVictor Perevertkin --*/
1402*8a978a17SVictor Perevertkin {
1403*8a978a17SVictor Perevertkin KIRQL irql;
1404*8a978a17SVictor Perevertkin BOOLEAN disabledImmediately;
1405*8a978a17SVictor Perevertkin
1406*8a978a17SVictor Perevertkin m_Lock.Acquire(&irql);
1407*8a978a17SVictor Perevertkin
1408*8a978a17SVictor Perevertkin ProcessEventLocked(PowerIdleEventDisabled);
1409*8a978a17SVictor Perevertkin
1410*8a978a17SVictor Perevertkin //
1411*8a978a17SVictor Perevertkin // If FxPowerIdleTimerStarted is still set after disabling the state machine,
1412*8a978a17SVictor Perevertkin // then we could not cancel the timer and we must wait for the timer expired
1413*8a978a17SVictor Perevertkin // event to be posted to this state machine. This state machine will then
1414*8a978a17SVictor Perevertkin // post a PwrPolIoPresent event to power policy.
1415*8a978a17SVictor Perevertkin //
1416*8a978a17SVictor Perevertkin if (m_Flags & FxPowerIdleTimerStarted) {
1417*8a978a17SVictor Perevertkin disabledImmediately = FALSE;
1418*8a978a17SVictor Perevertkin }
1419*8a978a17SVictor Perevertkin else {
1420*8a978a17SVictor Perevertkin disabledImmediately = TRUE;
1421*8a978a17SVictor Perevertkin }
1422*8a978a17SVictor Perevertkin
1423*8a978a17SVictor Perevertkin m_Lock.Release(irql);
1424*8a978a17SVictor Perevertkin
1425*8a978a17SVictor Perevertkin return disabledImmediately;
1426*8a978a17SVictor Perevertkin }
1427*8a978a17SVictor Perevertkin
1428*8a978a17SVictor Perevertkin VOID
Start(VOID)1429*8a978a17SVictor Perevertkin FxPowerIdleMachine::Start(
1430*8a978a17SVictor Perevertkin VOID
1431*8a978a17SVictor Perevertkin )
1432*8a978a17SVictor Perevertkin /*++
1433*8a978a17SVictor Perevertkin
1434*8a978a17SVictor Perevertkin Routine Description:
1435*8a978a17SVictor Perevertkin Public function that the power policy state machine uses to put this state
1436*8a978a17SVictor Perevertkin machine into a started state so that the caller can call PowerReference
1437*8a978a17SVictor Perevertkin successfully.
1438*8a978a17SVictor Perevertkin
1439*8a978a17SVictor Perevertkin Arguments:
1440*8a978a17SVictor Perevertkin None
1441*8a978a17SVictor Perevertkin
1442*8a978a17SVictor Perevertkin Return Value:
1443*8a978a17SVictor Perevertkin None
1444*8a978a17SVictor Perevertkin
1445*8a978a17SVictor Perevertkin --*/
1446*8a978a17SVictor Perevertkin {
1447*8a978a17SVictor Perevertkin KIRQL irql;
1448*8a978a17SVictor Perevertkin m_Lock.Acquire(&irql);
1449*8a978a17SVictor Perevertkin ProcessEventLocked(PowerIdleEventStart);
1450*8a978a17SVictor Perevertkin m_Lock.Release(irql);
1451*8a978a17SVictor Perevertkin }
1452*8a978a17SVictor Perevertkin
1453*8a978a17SVictor Perevertkin VOID
Stop(VOID)1454*8a978a17SVictor Perevertkin FxPowerIdleMachine::Stop(
1455*8a978a17SVictor Perevertkin VOID
1456*8a978a17SVictor Perevertkin )
1457*8a978a17SVictor Perevertkin /*++
1458*8a978a17SVictor Perevertkin
1459*8a978a17SVictor Perevertkin Routine Description:
1460*8a978a17SVictor Perevertkin Public function which the power policy state machine uses to put this state
1461*8a978a17SVictor Perevertkin machine into a state where PowerReference will no longer work.
1462*8a978a17SVictor Perevertkin
1463*8a978a17SVictor Perevertkin Arguments:
1464*8a978a17SVictor Perevertkin None
1465*8a978a17SVictor Perevertkin
1466*8a978a17SVictor Perevertkin Return Value:
1467*8a978a17SVictor Perevertkin None
1468*8a978a17SVictor Perevertkin
1469*8a978a17SVictor Perevertkin --*/
1470*8a978a17SVictor Perevertkin {
1471*8a978a17SVictor Perevertkin KIRQL irql;
1472*8a978a17SVictor Perevertkin
1473*8a978a17SVictor Perevertkin m_Lock.Acquire(&irql);
1474*8a978a17SVictor Perevertkin ProcessEventLocked(PowerIdleEventStop);
1475*8a978a17SVictor Perevertkin m_Lock.Release(irql);
1476*8a978a17SVictor Perevertkin }
1477*8a978a17SVictor Perevertkin
1478*8a978a17SVictor Perevertkin _Must_inspect_result_
1479*8a978a17SVictor Perevertkin NTSTATUS
PowerReferenceWorker(__in BOOLEAN WaitForD0,__in FxPowerReferenceFlags Flags,__in_opt PVOID Tag,__in_opt LONG Line,__in_opt PSTR File)1480*8a978a17SVictor Perevertkin FxPowerIdleMachine::PowerReferenceWorker(
1481*8a978a17SVictor Perevertkin __in BOOLEAN WaitForD0,
1482*8a978a17SVictor Perevertkin __in FxPowerReferenceFlags Flags,
1483*8a978a17SVictor Perevertkin __in_opt PVOID Tag,
1484*8a978a17SVictor Perevertkin __in_opt LONG Line,
1485*8a978a17SVictor Perevertkin __in_opt PSTR File
1486*8a978a17SVictor Perevertkin )
1487*8a978a17SVictor Perevertkin /*++
1488*8a978a17SVictor Perevertkin
1489*8a978a17SVictor Perevertkin Routine Description:
1490*8a978a17SVictor Perevertkin Caller wants to move the device into D0 manually. The caller may optionally
1491*8a978a17SVictor Perevertkin wait synchronously for the transition to occur if the device is currently in
1492*8a978a17SVictor Perevertkin Dx.
1493*8a978a17SVictor Perevertkin
1494*8a978a17SVictor Perevertkin Arguments:
1495*8a978a17SVictor Perevertkin WaitForD0 - TRUE if the caller wants to synchronously wait for the Dx to D0
1496*8a978a17SVictor Perevertkin transition
1497*8a978a17SVictor Perevertkin
1498*8a978a17SVictor Perevertkin QueryPnpPending - TRUE if we are being called to bring the device back to
1499*8a978a17SVictor Perevertkin working state when a QueryRemove or a QueryStop
1500*8a978a17SVictor Perevertkin
1501*8a978a17SVictor Perevertkin Return Value:
1502*8a978a17SVictor Perevertkin NTSTATUS
1503*8a978a17SVictor Perevertkin
1504*8a978a17SVictor Perevertkin STATUS_SUCCESS - success
1505*8a978a17SVictor Perevertkin STATUS_PENDING - transition is occurring
1506*8a978a17SVictor Perevertkin STATUS_POWER_STATE_INVALID - ower transition has failed
1507*8a978a17SVictor Perevertkin
1508*8a978a17SVictor Perevertkin --*/
1509*8a978a17SVictor Perevertkin {
1510*8a978a17SVictor Perevertkin NTSTATUS status;
1511*8a978a17SVictor Perevertkin KIRQL irql;
1512*8a978a17SVictor Perevertkin ULONG count = 0;
1513*8a978a17SVictor Perevertkin
1514*8a978a17SVictor Perevertkin
1515*8a978a17SVictor Perevertkin
1516*8a978a17SVictor Perevertkin
1517*8a978a17SVictor Perevertkin
1518*8a978a17SVictor Perevertkin
1519*8a978a17SVictor Perevertkin
1520*8a978a17SVictor Perevertkin
1521*8a978a17SVictor Perevertkin
1522*8a978a17SVictor Perevertkin
1523*8a978a17SVictor Perevertkin
1524*8a978a17SVictor Perevertkin
1525*8a978a17SVictor Perevertkin
1526*8a978a17SVictor Perevertkin
1527*8a978a17SVictor Perevertkin
1528*8a978a17SVictor Perevertkin
1529*8a978a17SVictor Perevertkin
1530*8a978a17SVictor Perevertkin
1531*8a978a17SVictor Perevertkin
1532*8a978a17SVictor Perevertkin //
1533*8a978a17SVictor Perevertkin // Poke the state machine
1534*8a978a17SVictor Perevertkin //
1535*8a978a17SVictor Perevertkin status = IoIncrementWithFlags(Flags, &count);
1536*8a978a17SVictor Perevertkin
1537*8a978a17SVictor Perevertkin //
1538*8a978a17SVictor Perevertkin // STATUS_PENDING indicates a Dx to D0 transition is occurring right now
1539*8a978a17SVictor Perevertkin //
1540*8a978a17SVictor Perevertkin if (status == STATUS_PENDING) {
1541*8a978a17SVictor Perevertkin if (WaitForD0) {
1542*8a978a17SVictor Perevertkin FxPkgPnp* pPkgPnp;
1543*8a978a17SVictor Perevertkin
1544*8a978a17SVictor Perevertkin ASSERT(Mx::MxGetCurrentIrql() <= APC_LEVEL);
1545*8a978a17SVictor Perevertkin
1546*8a978a17SVictor Perevertkin //
1547*8a978a17SVictor Perevertkin // With the current usage, if WaitForD0 is TRUE, then the only
1548*8a978a17SVictor Perevertkin // acceptable flag is FxPowerReferenceDefault.
1549*8a978a17SVictor Perevertkin //
1550*8a978a17SVictor Perevertkin // If the usage changes in the future such that it is acceptable to
1551*8a978a17SVictor Perevertkin // have WaitForD0 set to TRUE and some flag(s) set, then the ASSERT
1552*8a978a17SVictor Perevertkin // below should be updated accordingly (or removed altogether).
1553*8a978a17SVictor Perevertkin //
1554*8a978a17SVictor Perevertkin ASSERT(FxPowerReferenceDefault == Flags);
1555*8a978a17SVictor Perevertkin
1556*8a978a17SVictor Perevertkin pPkgPnp = GetPnpPkg(this);
1557*8a978a17SVictor Perevertkin
1558*8a978a17SVictor Perevertkin DoTraceLevelMessage(
1559*8a978a17SVictor Perevertkin pPkgPnp->GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGPNP,
1560*8a978a17SVictor Perevertkin "WDFDEVICE %p in thread %p waiting synchronously for Dx to D0 "
1561*8a978a17SVictor Perevertkin "transition",
1562*8a978a17SVictor Perevertkin pPkgPnp->GetDevice()->GetHandle(),
1563*8a978a17SVictor Perevertkin Mx::MxGetCurrentThread());
1564*8a978a17SVictor Perevertkin
1565*8a978a17SVictor Perevertkin //
1566*8a978a17SVictor Perevertkin // Returns success always
1567*8a978a17SVictor Perevertkin //
1568*8a978a17SVictor Perevertkin (void) FxPowerIdleMachine::WaitForD0();
1569*8a978a17SVictor Perevertkin
1570*8a978a17SVictor Perevertkin m_Lock.Acquire(&irql);
1571*8a978a17SVictor Perevertkin
1572*8a978a17SVictor Perevertkin //
1573*8a978a17SVictor Perevertkin // If WaitForD0 is TRUE, then the FxPowerIdleSendPnpPowerUpEvent
1574*8a978a17SVictor Perevertkin // flag can't be set. That flag is only used when the PnP state
1575*8a978a17SVictor Perevertkin // machine waits asynchronously for the device to power up during
1576*8a978a17SVictor Perevertkin // query-remove.
1577*8a978a17SVictor Perevertkin //
1578*8a978a17SVictor Perevertkin ASSERT(0 == (m_Flags & FxPowerIdleSendPnpPowerUpEvent));
1579*8a978a17SVictor Perevertkin
1580*8a978a17SVictor Perevertkin if ((m_Flags & FxPowerIdlePowerFailed) != 0x0 ||
1581*8a978a17SVictor Perevertkin (m_Flags & FxPowerIdleIsStarted) == 0x0) {
1582*8a978a17SVictor Perevertkin
1583*8a978a17SVictor Perevertkin //
1584*8a978a17SVictor Perevertkin // Event was set because a power up or down failure occurred
1585*8a978a17SVictor Perevertkin //
1586*8a978a17SVictor Perevertkin status = STATUS_POWER_STATE_INVALID;
1587*8a978a17SVictor Perevertkin
1588*8a978a17SVictor Perevertkin if (m_Flags & FxPowerIdlePowerFailed) {
1589*8a978a17SVictor Perevertkin DoTraceLevelMessage(
1590*8a978a17SVictor Perevertkin pPkgPnp->GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGPNP,
1591*8a978a17SVictor Perevertkin "WDFDEVICE %p waiting for D0 in thread %p failed because of "
1592*8a978a17SVictor Perevertkin "power failure, %!STATUS!",
1593*8a978a17SVictor Perevertkin pPkgPnp->GetDevice()->GetHandle(),
1594*8a978a17SVictor Perevertkin Mx::MxGetCurrentThread(),
1595*8a978a17SVictor Perevertkin status);
1596*8a978a17SVictor Perevertkin }
1597*8a978a17SVictor Perevertkin else {
1598*8a978a17SVictor Perevertkin COVERAGE_TRAP();
1599*8a978a17SVictor Perevertkin DoTraceLevelMessage(
1600*8a978a17SVictor Perevertkin pPkgPnp->GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGPNP,
1601*8a978a17SVictor Perevertkin "WDFDEVICE %p waiting for D0 in thread %p failed because of "
1602*8a978a17SVictor Perevertkin "invalid state , %!STATUS!",
1603*8a978a17SVictor Perevertkin pPkgPnp->GetDevice()->GetHandle(),
1604*8a978a17SVictor Perevertkin Mx::MxGetCurrentThread(), status);
1605*8a978a17SVictor Perevertkin }
1606*8a978a17SVictor Perevertkin
1607*8a978a17SVictor Perevertkin //
1608*8a978a17SVictor Perevertkin // Decrement the io count that was taken above
1609*8a978a17SVictor Perevertkin //
1610*8a978a17SVictor Perevertkin ASSERT(m_IoCount > 0);
1611*8a978a17SVictor Perevertkin m_IoCount--;
1612*8a978a17SVictor Perevertkin ProcessEventLocked(PowerIdleEventIoDecrement);
1613*8a978a17SVictor Perevertkin }
1614*8a978a17SVictor Perevertkin else {
1615*8a978a17SVictor Perevertkin //
1616*8a978a17SVictor Perevertkin // Successfully returned to D0
1617*8a978a17SVictor Perevertkin //
1618*8a978a17SVictor Perevertkin status = STATUS_SUCCESS;
1619*8a978a17SVictor Perevertkin }
1620*8a978a17SVictor Perevertkin m_Lock.Release(irql);
1621*8a978a17SVictor Perevertkin }
1622*8a978a17SVictor Perevertkin }
1623*8a978a17SVictor Perevertkin
1624*8a978a17SVictor Perevertkin if (m_TagTracker != NULL) {
1625*8a978a17SVictor Perevertkin //
1626*8a978a17SVictor Perevertkin // Only track the reference if the call was successful
1627*8a978a17SVictor Perevertkin // and the counter was actually incremented.
1628*8a978a17SVictor Perevertkin //
1629*8a978a17SVictor Perevertkin if (status == STATUS_SUCCESS || status == STATUS_PENDING) {
1630*8a978a17SVictor Perevertkin m_TagTracker->UpdateTagHistory(Tag, Line, File, TagAddRef, count);
1631*8a978a17SVictor Perevertkin }
1632*8a978a17SVictor Perevertkin }
1633*8a978a17SVictor Perevertkin
1634*8a978a17SVictor Perevertkin return status;
1635*8a978a17SVictor Perevertkin }
1636*8a978a17SVictor Perevertkin
1637*8a978a17SVictor Perevertkin _Must_inspect_result_
1638*8a978a17SVictor Perevertkin NTSTATUS
IoIncrement(VOID)1639*8a978a17SVictor Perevertkin FxPowerIdleMachine::IoIncrement(
1640*8a978a17SVictor Perevertkin VOID
1641*8a978a17SVictor Perevertkin )
1642*8a978a17SVictor Perevertkin /*++
1643*8a978a17SVictor Perevertkin
1644*8a978a17SVictor Perevertkin Routine Description:
1645*8a978a17SVictor Perevertkin Public function for any component to increment the io count. The increment
1646*8a978a17SVictor Perevertkin may cause the state machine to move out of the enabled state depending on
1647*8a978a17SVictor Perevertkin the current state.
1648*8a978a17SVictor Perevertkin
1649*8a978a17SVictor Perevertkin Arguments:
1650*8a978a17SVictor Perevertkin None
1651*8a978a17SVictor Perevertkin
1652*8a978a17SVictor Perevertkin Return Value:
1653*8a978a17SVictor Perevertkin STATUS_PENDING if the state machine is transition from idle to non idle
1654*8a978a17SVictor Perevertkin
1655*8a978a17SVictor Perevertkin STATUS_SUCCESS otherwise
1656*8a978a17SVictor Perevertkin
1657*8a978a17SVictor Perevertkin --*/
1658*8a978a17SVictor Perevertkin {
1659*8a978a17SVictor Perevertkin return IoIncrementWithFlags(FxPowerReferenceDefault);
1660*8a978a17SVictor Perevertkin }
1661*8a978a17SVictor Perevertkin
1662*8a978a17SVictor Perevertkin _Must_inspect_result_
1663*8a978a17SVictor Perevertkin NTSTATUS
IoIncrementWithFlags(__in FxPowerReferenceFlags Flags,__out_opt PULONG Count)1664*8a978a17SVictor Perevertkin FxPowerIdleMachine::IoIncrementWithFlags(
1665*8a978a17SVictor Perevertkin __in FxPowerReferenceFlags Flags,
1666*8a978a17SVictor Perevertkin __out_opt PULONG Count
1667*8a978a17SVictor Perevertkin )
1668*8a978a17SVictor Perevertkin /*++
1669*8a978a17SVictor Perevertkin
1670*8a978a17SVictor Perevertkin Routine Description:
1671*8a978a17SVictor Perevertkin An enchanced version of FxPowerIdleMachine::IoIncrement that has special
1672*8a978a17SVictor Perevertkin behavior based on flags passed in by the caller. Please read the routine
1673*8a978a17SVictor Perevertkin description of FxPowerIdleMachine::IoIncrement as well.
1674*8a978a17SVictor Perevertkin
1675*8a978a17SVictor Perevertkin Arguments:
1676*8a978a17SVictor Perevertkin Flags - The following flags are defined -
1677*8a978a17SVictor Perevertkin FxPowerReferenceDefault - No special behavior
1678*8a978a17SVictor Perevertkin FxPowerReferenceSendPnpPowerUpEvent - Set the
1679*8a978a17SVictor Perevertkin FxPowerIdleSendPnpPowerUpEvent flag in the idle state machine flags.
1680*8a978a17SVictor Perevertkin This will indicate to the idle state machine that when the device
1681*8a978a17SVictor Perevertkin powers up, it needs to send the PnpEventDeviceInD0 event to the PnP
1682*8a978a17SVictor Perevertkin state machine.
1683*8a978a17SVictor Perevertkin
1684*8a978a17SVictor Perevertkin Return Value:
1685*8a978a17SVictor Perevertkin STATUS_PENDING if the state machine is transition from idle to non idle
1686*8a978a17SVictor Perevertkin
1687*8a978a17SVictor Perevertkin STATUS_SUCCESS otherwise
1688*8a978a17SVictor Perevertkin
1689*8a978a17SVictor Perevertkin --*/
1690*8a978a17SVictor Perevertkin {
1691*8a978a17SVictor Perevertkin NTSTATUS status;
1692*8a978a17SVictor Perevertkin KIRQL irql;
1693*8a978a17SVictor Perevertkin
1694*8a978a17SVictor Perevertkin m_Lock.Acquire(&irql);
1695*8a978a17SVictor Perevertkin
1696*8a978a17SVictor Perevertkin if (m_Flags & FxPowerIdlePowerFailed) {
1697*8a978a17SVictor Perevertkin //
1698*8a978a17SVictor Perevertkin // fail without incrementing the count because we are in an
1699*8a978a17SVictor Perevertkin // invalid power state
1700*8a978a17SVictor Perevertkin //
1701*8a978a17SVictor Perevertkin status = STATUS_POWER_STATE_INVALID;
1702*8a978a17SVictor Perevertkin COVERAGE_TRAP();
1703*8a978a17SVictor Perevertkin }
1704*8a978a17SVictor Perevertkin else if ((m_Flags & FxPowerIdleIsStarted) == 0x0) {
1705*8a978a17SVictor Perevertkin //
1706*8a978a17SVictor Perevertkin // The state machine is not yet in a started state
1707*8a978a17SVictor Perevertkin //
1708*8a978a17SVictor Perevertkin status = STATUS_POWER_STATE_INVALID;
1709*8a978a17SVictor Perevertkin }
1710*8a978a17SVictor Perevertkin else {
1711*8a978a17SVictor Perevertkin m_IoCount++;
1712*8a978a17SVictor Perevertkin if (Count != NULL) {
1713*8a978a17SVictor Perevertkin *Count = m_IoCount;
1714*8a978a17SVictor Perevertkin }
1715*8a978a17SVictor Perevertkin
1716*8a978a17SVictor Perevertkin ProcessEventLocked(PowerIdleEventIoIncrement);
1717*8a978a17SVictor Perevertkin
1718*8a978a17SVictor Perevertkin if (InD0Locked()) {
1719*8a978a17SVictor Perevertkin status = STATUS_SUCCESS;
1720*8a978a17SVictor Perevertkin }
1721*8a978a17SVictor Perevertkin else {
1722*8a978a17SVictor Perevertkin status = STATUS_PENDING;
1723*8a978a17SVictor Perevertkin if (Flags & FxPowerReferenceSendPnpPowerUpEvent) {
1724*8a978a17SVictor Perevertkin m_Flags |= FxPowerIdleSendPnpPowerUpEvent;
1725*8a978a17SVictor Perevertkin }
1726*8a978a17SVictor Perevertkin }
1727*8a978a17SVictor Perevertkin }
1728*8a978a17SVictor Perevertkin m_Lock.Release(irql);
1729*8a978a17SVictor Perevertkin
1730*8a978a17SVictor Perevertkin return status;
1731*8a978a17SVictor Perevertkin }
1732*8a978a17SVictor Perevertkin
1733*8a978a17SVictor Perevertkin
1734*8a978a17SVictor Perevertkin VOID
IoDecrement(__in_opt PVOID Tag,__in_opt LONG Line,__in_opt PSTR File)1735*8a978a17SVictor Perevertkin FxPowerIdleMachine::IoDecrement(
1736*8a978a17SVictor Perevertkin __in_opt PVOID Tag,
1737*8a978a17SVictor Perevertkin __in_opt LONG Line,
1738*8a978a17SVictor Perevertkin __in_opt PSTR File
1739*8a978a17SVictor Perevertkin )
1740*8a978a17SVictor Perevertkin /*++
1741*8a978a17SVictor Perevertkin
1742*8a978a17SVictor Perevertkin Routine Description:
1743*8a978a17SVictor Perevertkin Public function which allows the caller decrement the pending io count on
1744*8a978a17SVictor Perevertkin this state machine. If the count goes to zero and idle is enabled, then
1745*8a978a17SVictor Perevertkin the timer is started.
1746*8a978a17SVictor Perevertkin
1747*8a978a17SVictor Perevertkin Arguments:
1748*8a978a17SVictor Perevertkin None
1749*8a978a17SVictor Perevertkin
1750*8a978a17SVictor Perevertkin Return Value:
1751*8a978a17SVictor Perevertkin None
1752*8a978a17SVictor Perevertkin
1753*8a978a17SVictor Perevertkin --*/
1754*8a978a17SVictor Perevertkin {
1755*8a978a17SVictor Perevertkin KIRQL irql;
1756*8a978a17SVictor Perevertkin FxPkgPnp* pPkgPnp;
1757*8a978a17SVictor Perevertkin PFX_DRIVER_GLOBALS pFxDriverGlobals;
1758*8a978a17SVictor Perevertkin ULONG count;
1759*8a978a17SVictor Perevertkin
1760*8a978a17SVictor Perevertkin pPkgPnp = GetPnpPkg(this);
1761*8a978a17SVictor Perevertkin pFxDriverGlobals = pPkgPnp->GetDriverGlobals();
1762*8a978a17SVictor Perevertkin
1763*8a978a17SVictor Perevertkin m_Lock.Acquire(&irql);
1764*8a978a17SVictor Perevertkin
1765*8a978a17SVictor Perevertkin if (m_IoCount == 0) {
1766*8a978a17SVictor Perevertkin //
1767*8a978a17SVictor Perevertkin // We can get here for the following reasons:
1768*8a978a17SVictor Perevertkin // 1. Driver called WdfDevicveStopIdle/WdfDeviceResumeIdle in a mismatched
1769*8a978a17SVictor Perevertkin // manner. This is a driver bug.
1770*8a978a17SVictor Perevertkin // 2. Framework did power deref without a corresponding power ref.
1771*8a978a17SVictor Perevertkin // This would be a framework bug.
1772*8a978a17SVictor Perevertkin //
1773*8a978a17SVictor Perevertkin // We will break into debugger if verifier is turned on. This will allow
1774*8a978a17SVictor Perevertkin // developers to catch this problem during develeopment.
1775*8a978a17SVictor Perevertkin // We limit this break to version 1.11+ because otherwise older drivers
1776*8a978a17SVictor Perevertkin // may hit this, and if they cannot be fixed for some reason, then
1777*8a978a17SVictor Perevertkin // verifier would need to be turned off to avoid the break which is not
1778*8a978a17SVictor Perevertkin // desirable.
1779*8a978a17SVictor Perevertkin //
1780*8a978a17SVictor Perevertkin DoTraceLevelMessage(
1781*8a978a17SVictor Perevertkin pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
1782*8a978a17SVictor Perevertkin "WDFDEVICE 0x%p !devobj 0x%p The device is being power-dereferenced"
1783*8a978a17SVictor Perevertkin " without a matching power-reference. This could occur if driver"
1784*8a978a17SVictor Perevertkin " incorrectly calls WdfDeviceResumeIdle without a matching call to"
1785*8a978a17SVictor Perevertkin " WdfDeviceStopIdle.",
1786*8a978a17SVictor Perevertkin pPkgPnp->GetDevice()->GetHandle(),
1787*8a978a17SVictor Perevertkin pPkgPnp->GetDevice()->GetDeviceObject());
1788*8a978a17SVictor Perevertkin
1789*8a978a17SVictor Perevertkin if (pFxDriverGlobals->IsVerificationEnabled(1, 11, OkForDownLevel)) {
1790*8a978a17SVictor Perevertkin FxVerifierDbgBreakPoint(pFxDriverGlobals);
1791*8a978a17SVictor Perevertkin }
1792*8a978a17SVictor Perevertkin }
1793*8a978a17SVictor Perevertkin
1794*8a978a17SVictor Perevertkin ASSERT(m_IoCount > 0);
1795*8a978a17SVictor Perevertkin count = --m_IoCount;
1796*8a978a17SVictor Perevertkin ProcessEventLocked(PowerIdleEventIoDecrement);
1797*8a978a17SVictor Perevertkin m_Lock.Release(irql);
1798*8a978a17SVictor Perevertkin
1799*8a978a17SVictor Perevertkin if (m_TagTracker != NULL) {
1800*8a978a17SVictor Perevertkin m_TagTracker->UpdateTagHistory(Tag, Line, File, TagRelease, count);
1801*8a978a17SVictor Perevertkin }
1802*8a978a17SVictor Perevertkin }
1803*8a978a17SVictor Perevertkin
1804*8a978a17SVictor Perevertkin BOOLEAN
QueryReturnToIdle(VOID)1805*8a978a17SVictor Perevertkin FxPowerIdleMachine::QueryReturnToIdle(
1806*8a978a17SVictor Perevertkin VOID
1807*8a978a17SVictor Perevertkin )
1808*8a978a17SVictor Perevertkin /*++
1809*8a978a17SVictor Perevertkin
1810*8a978a17SVictor Perevertkin Routine Description:
1811*8a978a17SVictor Perevertkin Public function which allows the caller to query the current io count on
1812*8a978a17SVictor Perevertkin this state machine. If the count non zero, the device will be brought back
1813*8a978a17SVictor Perevertkin to D0. If zero, the device will remain in Dx.
1814*8a978a17SVictor Perevertkin
1815*8a978a17SVictor Perevertkin Arguments:
1816*8a978a17SVictor Perevertkin None
1817*8a978a17SVictor Perevertkin
1818*8a978a17SVictor Perevertkin Return Value:
1819*8a978a17SVictor Perevertkin if TRUE is returned, there is an outstanding IO.
1820*8a978a17SVictor Perevertkin if FALSE is returned, the device is idle.
1821*8a978a17SVictor Perevertkin
1822*8a978a17SVictor Perevertkin --*/
1823*8a978a17SVictor Perevertkin {
1824*8a978a17SVictor Perevertkin KIRQL irql;
1825*8a978a17SVictor Perevertkin BOOLEAN result;
1826*8a978a17SVictor Perevertkin
1827*8a978a17SVictor Perevertkin //
1828*8a978a17SVictor Perevertkin // To return to idle, the following must be true
1829*8a978a17SVictor Perevertkin // 1) the device must be in Dx (FxPowerIdleInDx)
1830*8a978a17SVictor Perevertkin // 2) the timer must *NOT* be running
1831*8a978a17SVictor Perevertkin // 3) an IO count of zero
1832*8a978a17SVictor Perevertkin //
1833*8a978a17SVictor Perevertkin m_Lock.Acquire(&irql);
1834*8a978a17SVictor Perevertkin
1835*8a978a17SVictor Perevertkin // 1
1836*8a978a17SVictor Perevertkin if ((m_Flags & FxPowerIdleInDx) == FxPowerIdleInDx &&
1837*8a978a17SVictor Perevertkin // 2 3
1838*8a978a17SVictor Perevertkin (m_Flags & FxPowerIdleTimerStarted) == 0 && m_IoCount == 0x0) {
1839*8a978a17SVictor Perevertkin result = TRUE;
1840*8a978a17SVictor Perevertkin }
1841*8a978a17SVictor Perevertkin else {
1842*8a978a17SVictor Perevertkin result = FALSE;
1843*8a978a17SVictor Perevertkin }
1844*8a978a17SVictor Perevertkin
1845*8a978a17SVictor Perevertkin //
1846*8a978a17SVictor Perevertkin // If the caller is querying about returning to idle, then they have
1847*8a978a17SVictor Perevertkin // processed the io present event that we previously sent. We must clear
1848*8a978a17SVictor Perevertkin // the flag, otherwise the following can occur
1849*8a978a17SVictor Perevertkin // 1) new io arrives, send the io present message
1850*8a978a17SVictor Perevertkin // 2) return to idle (io count goes to zero)
1851*8a978a17SVictor Perevertkin // 3) get queried to return to idle, return TRUE
1852*8a978a17SVictor Perevertkin // 4) new io arrives, we do not send the new io present message because the
1853*8a978a17SVictor Perevertkin // FxPowerIdleIoPresentSent flag is set.
1854*8a978a17SVictor Perevertkin //
1855*8a978a17SVictor Perevertkin m_Flags &= ~FxPowerIdleIoPresentSent;
1856*8a978a17SVictor Perevertkin
1857*8a978a17SVictor Perevertkin m_Lock.Release(irql);
1858*8a978a17SVictor Perevertkin
1859*8a978a17SVictor Perevertkin return result;
1860*8a978a17SVictor Perevertkin }
1861*8a978a17SVictor Perevertkin
1862*8a978a17SVictor Perevertkin VOID
SendD0Notification(VOID)1863*8a978a17SVictor Perevertkin FxPowerIdleMachine::SendD0Notification(
1864*8a978a17SVictor Perevertkin VOID
1865*8a978a17SVictor Perevertkin )
1866*8a978a17SVictor Perevertkin {
1867*8a978a17SVictor Perevertkin m_D0NotificationEvent.Set();
1868*8a978a17SVictor Perevertkin
1869*8a978a17SVictor Perevertkin if (m_Flags & FxPowerIdleSendPnpPowerUpEvent) {
1870*8a978a17SVictor Perevertkin
1871*8a978a17SVictor Perevertkin m_Flags &= ~FxPowerIdleSendPnpPowerUpEvent;
1872*8a978a17SVictor Perevertkin
1873*8a978a17SVictor Perevertkin //
1874*8a978a17SVictor Perevertkin // Send an event to the Pnp state machine indicating that the device is
1875*8a978a17SVictor Perevertkin // now in D0.
1876*8a978a17SVictor Perevertkin //
1877*8a978a17SVictor Perevertkin #if (FX_CORE_MODE==FX_CORE_KERNEL_MODE)
1878*8a978a17SVictor Perevertkin GetPnpPkg(this)->PnpProcessEvent(PnpEventDeviceInD0);
1879*8a978a17SVictor Perevertkin #else
1880*8a978a17SVictor Perevertkin GetPnpPkg(this)->PnpProcessEvent(
1881*8a978a17SVictor Perevertkin PnpEventDeviceInD0,
1882*8a978a17SVictor Perevertkin TRUE // ProcessEventOnDifferentThread
1883*8a978a17SVictor Perevertkin );
1884*8a978a17SVictor Perevertkin #endif
1885*8a978a17SVictor Perevertkin
1886*8a978a17SVictor Perevertkin }
1887*8a978a17SVictor Perevertkin return;
1888*8a978a17SVictor Perevertkin }
1889*8a978a17SVictor Perevertkin
1890*8a978a17SVictor Perevertkin VOID
ProcessPowerEvent(__in FxPowerIdleEvents Event)1891*8a978a17SVictor Perevertkin FxPowerIdleMachine::ProcessPowerEvent(
1892*8a978a17SVictor Perevertkin __in FxPowerIdleEvents Event
1893*8a978a17SVictor Perevertkin )
1894*8a978a17SVictor Perevertkin /*++
1895*8a978a17SVictor Perevertkin
1896*8a978a17SVictor Perevertkin Routine Description:
1897*8a978a17SVictor Perevertkin Post a power related event to the state machine.
1898*8a978a17SVictor Perevertkin
1899*8a978a17SVictor Perevertkin Arguments:
1900*8a978a17SVictor Perevertkin Event - the event to post
1901*8a978a17SVictor Perevertkin
1902*8a978a17SVictor Perevertkin Return Value:
1903*8a978a17SVictor Perevertkin None
1904*8a978a17SVictor Perevertkin
1905*8a978a17SVictor Perevertkin --*/
1906*8a978a17SVictor Perevertkin {
1907*8a978a17SVictor Perevertkin KIRQL irql;
1908*8a978a17SVictor Perevertkin
1909*8a978a17SVictor Perevertkin //
1910*8a978a17SVictor Perevertkin // All other event types have specialized public functions
1911*8a978a17SVictor Perevertkin //
1912*8a978a17SVictor Perevertkin ASSERT(Event == PowerIdleEventPowerUpComplete ||
1913*8a978a17SVictor Perevertkin Event == PowerIdleEventPowerUpFailed ||
1914*8a978a17SVictor Perevertkin Event == PowerIdleEventPowerDown ||
1915*8a978a17SVictor Perevertkin Event == PowerIdleEventPowerDownFailed);
1916*8a978a17SVictor Perevertkin
1917*8a978a17SVictor Perevertkin m_Lock.Acquire(&irql);
1918*8a978a17SVictor Perevertkin ProcessEventLocked(Event);
1919*8a978a17SVictor Perevertkin m_Lock.Release(irql);
1920*8a978a17SVictor Perevertkin }
1921*8a978a17SVictor Perevertkin
1922*8a978a17SVictor Perevertkin VOID
ProcessEventLocked(__in FxPowerIdleEvents Event)1923*8a978a17SVictor Perevertkin FxPowerIdleMachine::ProcessEventLocked(
1924*8a978a17SVictor Perevertkin __in FxPowerIdleEvents Event
1925*8a978a17SVictor Perevertkin )
1926*8a978a17SVictor Perevertkin /*++
1927*8a978a17SVictor Perevertkin
1928*8a978a17SVictor Perevertkin Routine Description:
1929*8a978a17SVictor Perevertkin Processes an event and runs it through the state machine
1930*8a978a17SVictor Perevertkin
1931*8a978a17SVictor Perevertkin Arguments:
1932*8a978a17SVictor Perevertkin
1933*8a978a17SVictor Perevertkin
1934*8a978a17SVictor Perevertkin Return Value:
1935*8a978a17SVictor Perevertkin
1936*8a978a17SVictor Perevertkin
1937*8a978a17SVictor Perevertkin --*/
1938*8a978a17SVictor Perevertkin
1939*8a978a17SVictor Perevertkin {
1940*8a978a17SVictor Perevertkin const FxIdleStateTable* entry;
1941*8a978a17SVictor Perevertkin FxPowerIdleStates newState;
1942*8a978a17SVictor Perevertkin FxPkgPnp* pPkgPnp;
1943*8a978a17SVictor Perevertkin
1944*8a978a17SVictor Perevertkin pPkgPnp = GetPnpPkg(this);
1945*8a978a17SVictor Perevertkin
1946*8a978a17SVictor Perevertkin m_EventHistory[m_EventHistoryIndex] = Event;
1947*8a978a17SVictor Perevertkin m_EventHistoryIndex = (m_EventHistoryIndex + 1) %
1948*8a978a17SVictor Perevertkin (sizeof(m_EventHistory)/sizeof(m_EventHistory[0]));
1949*8a978a17SVictor Perevertkin
1950*8a978a17SVictor Perevertkin entry = &m_StateTable[m_CurrentIdleState-FxIdleStopped];
1951*8a978a17SVictor Perevertkin newState = FxIdleMax;
1952*8a978a17SVictor Perevertkin
1953*8a978a17SVictor Perevertkin for (ULONG i = 0; i < entry->TargetStatesCount; i++) {
1954*8a978a17SVictor Perevertkin if (entry->TargetStates[i].PowerIdleEvent == Event) {
1955*8a978a17SVictor Perevertkin DO_EVENT_TRAP(&entry->TargetStates[i]);
1956*8a978a17SVictor Perevertkin newState = entry->TargetStates[i].PowerIdleState;
1957*8a978a17SVictor Perevertkin break;
1958*8a978a17SVictor Perevertkin }
1959*8a978a17SVictor Perevertkin }
1960*8a978a17SVictor Perevertkin
1961*8a978a17SVictor Perevertkin if (newState == FxIdleMax) {
1962*8a978a17SVictor Perevertkin switch (Event) {
1963*8a978a17SVictor Perevertkin case PowerIdleEventIoIncrement:
1964*8a978a17SVictor Perevertkin case PowerIdleEventIoDecrement:
1965*8a978a17SVictor Perevertkin //
1966*8a978a17SVictor Perevertkin // We always can handle io increment, io decrement, and query return
1967*8a978a17SVictor Perevertkin // to idle from any state...
1968*8a978a17SVictor Perevertkin //
1969*8a978a17SVictor Perevertkin break;
1970*8a978a17SVictor Perevertkin
1971*8a978a17SVictor Perevertkin case PowerIdleEventEnabled:
1972*8a978a17SVictor Perevertkin if (m_Flags & FxPowerIdleTimerEnabled) {
1973*8a978a17SVictor Perevertkin //
1974*8a978a17SVictor Perevertkin // Getting an enable event while enabled is OK
1975*8a978a17SVictor Perevertkin //
1976*8a978a17SVictor Perevertkin break;
1977*8a978a17SVictor Perevertkin }
1978*8a978a17SVictor Perevertkin // || || Fall || ||
1979*8a978a17SVictor Perevertkin // \/ \/ through \/ \/
1980*8a978a17SVictor Perevertkin
1981*8a978a17SVictor Perevertkin default:
1982*8a978a17SVictor Perevertkin //
1983*8a978a17SVictor Perevertkin // ...but we should not be dropping any other events from this state.
1984*8a978a17SVictor Perevertkin //
1985*8a978a17SVictor Perevertkin
1986*8a978a17SVictor Perevertkin //
1987*8a978a17SVictor Perevertkin DoTraceLevelMessage(
1988*8a978a17SVictor Perevertkin pPkgPnp->GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGPNP,
1989*8a978a17SVictor Perevertkin "WDFDEVICE 0x%p !devobj 0x%p power idle state %!FxPowerIdleStates!"
1990*8a978a17SVictor Perevertkin " dropping event %!FxPowerIdleEvents!",
1991*8a978a17SVictor Perevertkin pPkgPnp->GetDevice()->GetHandle(),
1992*8a978a17SVictor Perevertkin pPkgPnp->GetDevice()->GetDeviceObject(),
1993*8a978a17SVictor Perevertkin m_CurrentIdleState, Event);
1994*8a978a17SVictor Perevertkin
1995*8a978a17SVictor Perevertkin COVERAGE_TRAP();
1996*8a978a17SVictor Perevertkin }
1997*8a978a17SVictor Perevertkin }
1998*8a978a17SVictor Perevertkin
1999*8a978a17SVictor Perevertkin while (newState != FxIdleMax) {
2000*8a978a17SVictor Perevertkin
2001*8a978a17SVictor Perevertkin DoTraceLevelMessage(
2002*8a978a17SVictor Perevertkin pPkgPnp->GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGPNPPOWERSTATES,
2003*8a978a17SVictor Perevertkin "WDFDEVICE 0x%p !devobj 0x%p entering power idle state "
2004*8a978a17SVictor Perevertkin "%!FxPowerIdleStates! from %!FxPowerIdleStates!",
2005*8a978a17SVictor Perevertkin pPkgPnp->GetDevice()->GetHandle(),
2006*8a978a17SVictor Perevertkin pPkgPnp->GetDevice()->GetDeviceObject(),
2007*8a978a17SVictor Perevertkin newState, m_CurrentIdleState);
2008*8a978a17SVictor Perevertkin
2009*8a978a17SVictor Perevertkin m_StateHistory[m_StateHistoryIndex] = newState;
2010*8a978a17SVictor Perevertkin m_StateHistoryIndex = (m_StateHistoryIndex + 1) %
2011*8a978a17SVictor Perevertkin (sizeof(m_StateHistory)/sizeof(m_StateHistory[0]));
2012*8a978a17SVictor Perevertkin
2013*8a978a17SVictor Perevertkin m_CurrentIdleState = newState;
2014*8a978a17SVictor Perevertkin entry = &m_StateTable[m_CurrentIdleState-FxIdleStopped];
2015*8a978a17SVictor Perevertkin
2016*8a978a17SVictor Perevertkin if (entry->StateFunc != NULL) {
2017*8a978a17SVictor Perevertkin newState = entry->StateFunc(this);
2018*8a978a17SVictor Perevertkin }
2019*8a978a17SVictor Perevertkin else {
2020*8a978a17SVictor Perevertkin newState = FxIdleMax;
2021*8a978a17SVictor Perevertkin }
2022*8a978a17SVictor Perevertkin }
2023*8a978a17SVictor Perevertkin }
2024