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