1 /*++
2 Copyright (c) Microsoft. All rights reserved.
3
4 Module Name:
5
6 PoxInterface.cpp
7
8 Abstract:
9
10 This module implements the power-framework-related logic in WDF.
11
12 --*/
13
14 #include "pnppriv.hpp"
15
16 extern "C" {
17 #if defined(EVENT_TRACING)
18 #include "PoxInterface.tmh"
19 #endif
20 }
21
FxPoxInterface(__in FxPkgPnp * PkgPnp)22 FxPoxInterface::FxPoxInterface(
23 __in FxPkgPnp* PkgPnp
24 )
25 {
26 m_PkgPnp = PkgPnp;
27 m_PoHandle = NULL;
28 m_DevicePowerRequired = TRUE;
29 m_DevicePowerRequirementMachine = NULL;
30 m_CurrentIdleTimeoutHint = 0;
31 m_NextIdleTimeoutHint = 0;
32 }
33
~FxPoxInterface(VOID)34 FxPoxInterface::~FxPoxInterface(
35 VOID
36 )
37 {
38 if (NULL != m_DevicePowerRequirementMachine) {
39 delete m_DevicePowerRequirementMachine;
40 }
41 }
42
43 NTSTATUS
CreateDevicePowerRequirementMachine(VOID)44 FxPoxInterface::CreateDevicePowerRequirementMachine(
45 VOID
46 )
47 {
48 // NTSTATUS status;
49 // FxDevicePwrRequirementMachine * fxDprMachine = NULL;
50
51 // ASSERT(NULL == m_DevicePowerRequirementMachine);
52
53 // fxDprMachine = new (m_PkgPnp->GetDriverGlobals())
54 // FxDevicePwrRequirementMachine(this);
55 // if (NULL == fxDprMachine) {
56 // status = STATUS_INSUFFICIENT_RESOURCES;
57 // DoTraceLevelMessage(
58 // m_PkgPnp->GetDriverGlobals(),
59 // TRACE_LEVEL_ERROR, TRACINGPNP,
60 // "WDFDEVICE 0x%p !devobj 0x%p failed to allocate "
61 // "FxDevicePwrRequirementMachine. %!STATUS!.",
62 // m_PkgPnp->GetDevice()->GetHandle(),
63 // m_PkgPnp->GetDevice()->GetDeviceObject(),
64 // status);
65 // goto exit;
66 // }
67
68 // status = fxDprMachine->Initialize(m_PkgPnp->GetDriverGlobals());
69 // if (FALSE == NT_SUCCESS(status)) {
70 // DoTraceLevelMessage(
71 // m_PkgPnp->GetDriverGlobals(),
72 // TRACE_LEVEL_ERROR, TRACINGPNP,
73 // "WDFDEVICE 0x%p !devobj 0x%p Device Power Requirement State Machine"
74 // " Initialize() failed, %!STATUS!",
75 // m_PkgPnp->GetDevice()->GetHandle(),
76 // m_PkgPnp->GetDevice()->GetDeviceObject(),
77 // status);
78 // goto exit;
79 // }
80
81 // status = fxDprMachine->Init(
82 // m_PkgPnp,
83 // FxDevicePwrRequirementMachine::_ProcessEventInner
84 // );
85 // if (!NT_SUCCESS(status)) {
86 // DoTraceLevelMessage(
87 // m_PkgPnp->GetDriverGlobals(),
88 // TRACE_LEVEL_ERROR, TRACINGPNP,
89 // "WDFDEVICE 0x%p !devobj 0x%p Device Power Requirement State Machine"
90 // " Init() failed, %!STATUS!",
91 // m_PkgPnp->GetDevice()->GetHandle(),
92 // m_PkgPnp->GetDevice()->GetDeviceObject(),
93 // status);
94 // goto exit;
95 // }
96
97 // m_DevicePowerRequirementMachine = fxDprMachine;
98
99 // status = STATUS_SUCCESS;
100
101 // exit:
102 // if (FALSE == NT_SUCCESS(status)) {
103 // if (NULL != fxDprMachine) {
104 // delete fxDprMachine;
105 // }
106 // }
107 // return status;
108 ROSWDFNOTIMPLEMENTED;
109 return STATUS_SUCCESS;
110 }
111
112 NTSTATUS
InitializeComponents(VOID)113 FxPoxInterface::InitializeComponents(
114 VOID
115 )
116 {
117 // NTSTATUS status;
118 // PPOX_SETTINGS poxSettings = NULL;
119 // WDFDEVICE fxDevice = NULL;
120
121
122 // if (FALSE == m_PkgPnp->m_PowerPolicyMachine.m_Owner->m_IdleSettings.
123 // m_TimeoutMgmt.UsingSystemManagedIdleTimeout()) {
124 // //
125 // // Driver-managed idle timeout. Nothing to do.
126 // //
127 // return STATUS_SUCCESS;
128 // }
129
130 // //
131 // // We create the device power requirement state machine only if system-
132 // // managed idle timeout is being used.
133 // //
134 // if (NULL == m_DevicePowerRequirementMachine) {
135 // status = CreateDevicePowerRequirementMachine();
136 // if (FALSE == NT_SUCCESS(status)) {
137 // goto exit;
138 // }
139 // }
140
141 // ASSERT(NULL != m_DevicePowerRequirementMachine);
142
143 // //
144 // // Register with the power framework
145 // //
146 // status = PoxRegisterDevice();
147
148 // if (FALSE == NT_SUCCESS(status)) {
149 // DoTraceLevelMessage(
150 // m_PkgPnp->GetDriverGlobals(),
151 // TRACE_LEVEL_ERROR, TRACINGPNP,
152 // "WDFDEVICE 0x%p !devobj 0x%p FxPox::PoxRegisterDevice failed. "
153 // "%!STATUS!.",
154 // m_PkgPnp->GetDevice()->GetHandle(),
155 // m_PkgPnp->GetDevice()->GetDeviceObject(),
156 // status);
157 // goto exit;
158 // }
159
160 // //
161 // // At the time of registration, all components are active. When we start the
162 // // power framework's device power management (see below), all components are
163 // // moved to the idle state by default. Take an extra reference on the
164 // // component to prevent this from happening. The power policy state machine
165 // // will evaluate the S0-idle policy later and ask us to drop this reference
166 // // if the policy requires it.
167 // //
168 // PoxActivateComponent();
169
170 // //
171 // // Tell the power framework to start its device power management. This will
172 // // drop a reference on the component, but the component will still remain
173 // // active because of the extra reference we took above.
174 // //
175 // PoxStartDevicePowerManagement();
176
177 // //
178 // // If the client driver has specified power framework settings, retrieve
179 // // them.
180 // //
181 // poxSettings = GetPowerFrameworkSettings();
182
183 // //
184 // // If the driver wanted to receive the POHANDLE, invoke their callback now
185 // //
186 // if ((NULL != poxSettings) &&
187 // (NULL != poxSettings->EvtDeviceWdmPostPoFxRegisterDevice)) {
188
189 // fxDevice = m_PkgPnp->GetDevice()->GetHandle();
190
191 // status = poxSettings->EvtDeviceWdmPostPoFxRegisterDevice(
192 // fxDevice,
193 // m_PoHandle
194 // );
195 // if (FALSE == NT_SUCCESS(status)) {
196
197 // DoTraceLevelMessage(
198 // m_PkgPnp->GetDriverGlobals(),
199 // TRACE_LEVEL_ERROR, TRACINGPNP,
200 // "WDFDEVICE 0x%p !devobj 0x%p. The client driver has failed the "
201 // "EvtDeviceWdmPostPoFxRegisterDevice callback with %!STATUS!.",
202 // m_PkgPnp->GetDevice()->GetHandle(),
203 // m_PkgPnp->GetDevice()->GetDeviceObject(),
204 // status);
205
206 // //
207 // // Notify the driver that the POHANDLE is about to become invalid
208 // //
209 // if (NULL != poxSettings->EvtDeviceWdmPrePoFxUnregisterDevice) {
210 // poxSettings->EvtDeviceWdmPrePoFxUnregisterDevice(
211 // fxDevice,
212 // m_PoHandle
213 // );
214 // }
215
216 // //
217 // // Unregister with the power framework
218 // //
219 // PoxUnregisterDevice();
220 // goto exit;
221 // }
222 // }
223
224 // //
225 // // Tell the device power requirement state machine that we have registered
226 // // with the power framework
227 // //
228 // m_DevicePowerRequirementMachine->ProcessEvent(DprEventRegisteredWithPox);
229
230 // exit:
231 // return status;
232 ROSWDFNOTIMPLEMENTED;
233 return STATUS_SUCCESS;
234 }
235
236 VOID
UninitializeComponents(VOID)237 FxPoxInterface::UninitializeComponents(
238 VOID
239 )
240 {
241 // PPOX_SETTINGS poxSettings = NULL;
242
243 // if (FALSE == m_PkgPnp->m_PowerPolicyMachine.m_Owner->m_IdleSettings.
244 // m_TimeoutMgmt.UsingSystemManagedIdleTimeout()) {
245 // //
246 // // Driver-managed idle timeout. Nothing to do.
247 // //
248 // return;
249 // }
250
251 // ASSERT(NULL != m_DevicePowerRequirementMachine);
252
253 // //
254 // // If the client driver has specified power framework settings, retrieve
255 // // them.
256 // //
257 // poxSettings = GetPowerFrameworkSettings();
258
259 // //
260 // // Notify the client driver that the POHANDLE is about to become invalid
261 // //
262 // if ((NULL != poxSettings) &&
263 // (NULL != poxSettings->EvtDeviceWdmPrePoFxUnregisterDevice)) {
264
265 // poxSettings->EvtDeviceWdmPrePoFxUnregisterDevice(
266 // m_PkgPnp->GetDevice()->GetHandle(),
267 // m_PoHandle
268 // );
269 // }
270
271 // //
272 // // Unregister with the power framework
273 // //
274 // PoxUnregisterDevice();
275
276 // //
277 // // Tell the device power requirement state machine that we have unregistered
278 // // with the power framework
279 // //
280 // m_DevicePowerRequirementMachine->ProcessEvent(
281 // DprEventUnregisteredWithPox
282 // );
283 // return;
284 ROSWDFNOTIMPLEMENTED;
285 }
286
287 VOID
RequestComponentActive(VOID)288 FxPoxInterface::RequestComponentActive(
289 VOID
290 )
291 {
292 // if (FALSE == m_PkgPnp->m_PowerPolicyMachine.m_Owner->m_IdleSettings.
293 // m_TimeoutMgmt.UsingSystemManagedIdleTimeout()) {
294 // //
295 // // Driver-managed idle timeout. Nothing to do.
296 // //
297 // return;
298 // }
299
300 // PoxActivateComponent();
301 // return;
302 ROSWDFNOTIMPLEMENTED;
303 }
304
305 BOOLEAN
DeclareComponentIdle(VOID)306 FxPoxInterface::DeclareComponentIdle(
307 VOID
308 )
309 {
310 // BOOLEAN canPowerDown;
311
312 // if (FALSE == m_PkgPnp->m_PowerPolicyMachine.m_Owner->m_IdleSettings.
313 // m_TimeoutMgmt.UsingSystemManagedIdleTimeout()) {
314 // //
315 // // Driver-managed idle timeout. We can power down immediately, without
316 // // waiting for device-power-not-required notification.
317 // //
318 // canPowerDown = TRUE;
319 // } else {
320 // //
321 // // System-managed idle timeout
322 // //
323 // PoxIdleComponent();
324
325 // //
326 // // We must wait for device-power-not-required notification before
327 // // powering down.
328 // //
329 // canPowerDown = FALSE;
330 // }
331
332 // return canPowerDown;
333 ROSWDFNOTIMPLEMENTED;
334 return TRUE;
335 }
336
337 VOID
UpdateIdleTimeoutHint(VOID)338 FxPoxInterface::UpdateIdleTimeoutHint(
339 VOID
340 )
341 {
342 // ULONGLONG idleTimeoutHint;
343
344 // if (FALSE == m_PkgPnp->m_PowerPolicyMachine.m_Owner->m_IdleSettings.
345 // m_TimeoutMgmt.UsingSystemManagedIdleTimeout()) {
346 // //
347 // // Driver-managed idle timeout. Nothing to do.
348 // //
349 // return;
350 // }
351
352 // if (m_NextIdleTimeoutHint != m_CurrentIdleTimeoutHint) {
353 // m_CurrentIdleTimeoutHint = m_NextIdleTimeoutHint;
354
355 // //
356 // // Convert the idle timeout from milliseconds to 100-nanosecond units
357 // //
358 // idleTimeoutHint = ((ULONGLONG) m_CurrentIdleTimeoutHint) * 10 * 1000;
359 // PoxSetDeviceIdleTimeout(idleTimeoutHint);
360 // }
361
362 // return;
363 ROSWDFNOTIMPLEMENTED;
364 }
365
366
367 NTSTATUS
NotifyDevicePowerDown(VOID)368 FxPoxInterface::NotifyDevicePowerDown(
369 VOID
370 )
371 {
372 // KIRQL irql;
373 // BOOLEAN canPowerOff;
374
375 // if (FALSE == m_PkgPnp->m_PowerPolicyMachine.m_Owner->m_IdleSettings.
376 // m_TimeoutMgmt.UsingSystemManagedIdleTimeout()) {
377 // //
378 // // Driver-managed idle timeout. We don't have to take power framework's
379 // // device power requirement into consideration. Just return success.
380 // //
381 // return STATUS_SUCCESS;
382 // }
383
384 // //
385 // // Acquire the lock to ensure that device power requirement doesn't change.
386 // //
387 // m_DevicePowerRequiredLock.Acquire(&irql);
388 // if (FALSE == m_DevicePowerRequired) {
389 // //
390 // // Send an event to the device power requirement state machine to tell
391 // // it that we are about to go to Dx.
392 // //
393 // // We send the event inside a lock in order to handle the race condition
394 // // when the power framework notifies us that device power is required at
395 // // the same time that we are about to go to Dx. By sending the event
396 // // inside the lock, we ensure that the DprEventDeviceGoingToDx event is
397 // // always queued to device power requirement state machine before the
398 // // DprEventPoxRequiresPower.
399 // //
400 // // This allows for a clean design in the device power requirement state
401 // // machine by ensuring that it does not have to handle a non-intuitive
402 // // sequence, i.e. DprEventPoxRequiresPower followed by
403 // // DprEventDeviceGoingToDx. This sequence is non-intuitive because it
404 // // doesn't make sense for a device to go to Dx after it has been
405 // // informed that device power is required. Avoiding this non-intuitive
406 // // sequence via locking enables a clean design for the device power
407 // // requirement state machine.
408 // //
409 // m_DevicePowerRequirementMachine->ProcessEvent(DprEventDeviceGoingToDx);
410 // canPowerOff = TRUE;
411
412 // } else {
413 // canPowerOff = FALSE;
414 // }
415 // m_DevicePowerRequiredLock.Release(irql);
416
417 // return canPowerOff ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
418 ROSWDFNOTIMPLEMENTED;
419 return STATUS_SUCCESS;
420 }
421
422 VOID
DeviceIsPoweredOn(VOID)423 FxPoxInterface::DeviceIsPoweredOn(
424 VOID
425 )
426 {
427 ROSWDFNOTIMPLEMENTED;
428 // if (FALSE == m_PkgPnp->m_PowerPolicyMachine.m_Owner->m_IdleSettings.
429 // m_TimeoutMgmt.UsingSystemManagedIdleTimeout()) {
430 // //
431 // // Driver-managed idle timeout. Nothing to do.
432 // //
433 // return;
434 // }
435
436 // //
437 // // System-managed idle timeout. Notify the device power requirement state
438 // // machine that we are back in D0.
439 // //
440 // m_DevicePowerRequirementMachine->ProcessEvent(
441 // DprEventDeviceReturnedToD0
442 // );
443 // return;
444 }
445
446 PPOX_SETTINGS
GetPowerFrameworkSettings(VOID)447 FxPoxInterface::GetPowerFrameworkSettings(
448 VOID
449 )
450 {
451 PPOX_SETTINGS poxSettings = NULL;
452
453 ROSWDFNOTIMPLEMENTED;
454 // if (m_PkgPnp->m_PowerPolicyMachine.m_Owner->
455 // m_IdleSettings.m_TimeoutMgmt.DriverSpecifiedPowerFrameworkSettings()) {
456
457 // poxSettings = m_PkgPnp->m_PowerPolicyMachine.m_Owner->
458 // m_IdleSettings.m_TimeoutMgmt.GetPowerFrameworkSettings();
459
460 // ASSERT(NULL != poxSettings);
461 // }
462
463 return poxSettings;
464 }
465
466 VOID
DprProcessEventFromPoxCallback(__in FxDevicePwrRequirementEvents Event)467 FxPoxInterface::DprProcessEventFromPoxCallback(
468 __in FxDevicePwrRequirementEvents Event
469 )
470 {
471 ROSWDFNOTIMPLEMENTED;
472 // KIRQL irql;
473
474 // //
475 // // We should not run the state machine from within a power framework
476 // // callback because we might end up reaching a state where we unregister
477 // // with the power framework. Unregistering from a callback leads to a
478 // // deadlock. Therefore, we raise IRQL before queueing an event to the state
479 // // machine. Raising IRQL causes the event processing to be deferred to a
480 // // worker thread.
481 // //
482
483 // //
484 // // This path should only be invoked for kernel mode. For user mode, this
485 // // condition is avoided by reflector guranteeing that it queues a worker
486 // // item to send a Pofx event corresponding to any PoFx callback
487 // //
488 // ASSERT(FX_IS_KERNEL_MODE);
489
490 // Mx::MxRaiseIrql(DISPATCH_LEVEL, &irql);
491 // m_DevicePowerRequirementMachine->ProcessEvent(Event);
492 // Mx::MxLowerIrql(irql);
493 }
494
495 VOID
SimulateDevicePowerRequired(VOID)496 FxPoxInterface::SimulateDevicePowerRequired(
497 VOID
498 )
499 {
500 ROSWDFNOTIMPLEMENTED;
501 // if (FALSE == m_PkgPnp->m_PowerPolicyMachine.m_Owner->m_IdleSettings.
502 // m_TimeoutMgmt.UsingSystemManagedIdleTimeout()) {
503 // //
504 // // Driver-managed idle timeout. Nothing to do.
505 // //
506 // return;
507 // }
508
509 // //
510 // // System-managed idle timeout. Notify the device power requirement state
511 // // machine that device power is required.
512 // //
513 // PowerRequiredCallbackWorker(FALSE /* InvokedFromPoxCallback */);
514 // return;
515 }
516
517 VOID
SimulateDevicePowerNotRequired(VOID)518 FxPoxInterface::SimulateDevicePowerNotRequired(
519 VOID
520 )
521 {
522 ROSWDFNOTIMPLEMENTED;
523 // if (FALSE == m_PkgPnp->m_PowerPolicyMachine.m_Owner->m_IdleSettings.
524 // m_TimeoutMgmt.UsingSystemManagedIdleTimeout()) {
525 // //
526 // // Driver-managed idle timeout. Nothing to do.
527 // //
528 // return;
529 // }
530
531 // //
532 // // System-managed idle timeout. Notify the device power requirement state
533 // // machine that device power is not required.
534 // //
535 // PowerNotRequiredCallbackWorker(FALSE /* InvokedFromPoxCallback */);
536 // return;
537 }
538
539 VOID
PowerRequiredCallbackWorker(__in BOOLEAN InvokedFromPoxCallback)540 FxPoxInterface::PowerRequiredCallbackWorker(
541 __in BOOLEAN InvokedFromPoxCallback
542 )
543 {
544 ROSWDFNOTIMPLEMENTED;
545 // KIRQL irql;
546
547 // //
548 // // Make a note of the fact that device power is required
549 // //
550 // m_DevicePowerRequiredLock.Acquire(&irql);
551 // m_DevicePowerRequired = TRUE;
552 // m_DevicePowerRequiredLock.Release(irql);
553
554 // //
555 // // Send the device-power-required event to the device power requirement
556 // // state machine.
557 // //
558 // if (InvokedFromPoxCallback) {
559 // DprProcessEventFromPoxCallback(DprEventPoxRequiresPower);
560 // } else {
561 // m_DevicePowerRequirementMachine->ProcessEvent(DprEventPoxRequiresPower);
562 // }
563 // return;
564 }
565
566 VOID
PowerNotRequiredCallbackWorker(__in BOOLEAN InvokedFromPoxCallback)567 FxPoxInterface::PowerNotRequiredCallbackWorker(
568 __in BOOLEAN InvokedFromPoxCallback
569 )
570 {
571 ROSWDFNOTIMPLEMENTED;
572 // KIRQL irql;
573
574 // //
575 // // Make a note of the fact that device power is not required
576 // //
577 // m_DevicePowerRequiredLock.Acquire(&irql);
578 // m_DevicePowerRequired = FALSE;
579 // m_DevicePowerRequiredLock.Release(irql);
580
581 // //
582 // // Send the device-power-not-required event to the device power
583 // // requirement state machine.
584 // //
585 // if (InvokedFromPoxCallback) {
586 // DprProcessEventFromPoxCallback(DprEventPoxDoesNotRequirePower);
587 // } else {
588 // m_DevicePowerRequirementMachine->ProcessEvent(
589 // DprEventPoxDoesNotRequirePower
590 // );
591 // }
592 // return;
593 }
594
595