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 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 34 FxPoxInterface::~FxPoxInterface( 35 VOID 36 ) 37 { 38 if (NULL != m_DevicePowerRequirementMachine) { 39 delete m_DevicePowerRequirementMachine; 40 } 41 } 42 43 NTSTATUS 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 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 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 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 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 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 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 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 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 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 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 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 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 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