1 /*++ 2 3 Copyright (c) Microsoft. All rights reserved. 4 5 Module Name: 6 7 NotPowerPolicyOwnerStateMachine.cpp 8 9 Abstract: 10 11 This module implements the Not Power Policy Owner state machine for the driver 12 framework. This code was split out from PowerPolicyStateMachine.cpp 13 14 Author: 15 16 17 18 19 Environment: 20 21 Both kernel and user mode 22 23 Revision History: 24 25 26 27 --*/ 28 29 #include "pnppriv.hpp" 30 31 extern "C" { 32 #if defined(EVENT_TRACING) 33 #include "NotPowerPolicyOwnerStateMachine.tmh" 34 #endif 35 } 36 37 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_NotPowerPolOwnerObjectCreatedStates[] = 38 { 39 { PwrPolStart, WdfDevStatePwrPolStarting DEBUGGED_EVENT }, 40 { PwrPolRemove, WdfDevStatePwrPolRemoved DEBUGGED_EVENT }, 41 }; 42 43 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_NotPowerPolOwnerStartingStates[] = 44 { 45 { PwrPolPowerUp, WdfDevStatePwrPolStarted DEBUGGED_EVENT }, 46 { PwrPolPowerUpFailed, WdfDevStatePwrPolStartingFailed DEBUGGED_EVENT }, 47 }; 48 49 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_NotPowerPolOwnerStartingSucceededStates[] = 50 { 51 { PwrPolPowerDownIoStopped, WdfDevStatePwrPolGotoDx DEBUGGED_EVENT }, 52 { PwrPolStop, WdfDevStatePwrPolStopping DEBUGGED_EVENT }, 53 { PwrPolSurpriseRemove, WdfDevStatePwrPolStopping DEBUGGED_EVENT }, 54 { PwrPolPowerUpHwStarted, WdfDevStatePwrPolGotoD0InD0 TRAP_ON_EVENT }, 55 }; 56 57 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_NotPowerPolOwnerStartingFailedStates[] = 58 { 59 { PwrPolRemove, WdfDevStatePwrPolRemoved DEBUGGED_EVENT }, 60 }; 61 62 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_NotPowerPolOwnerGotoDxStates[] = 63 { 64 { PwrPolPowerDown, WdfDevStatePwrPolDx DEBUGGED_EVENT }, 65 { PwrPolPowerDownFailed, WdfDevStatePwrPolStartingSucceeded DEBUGGED_EVENT }, 66 }; 67 68 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_NotPowerPolOwnerGotoDxInDxStates[] = 69 { 70 { PwrPolPowerDown, WdfDevStatePwrPolDx TRAP_ON_EVENT }, 71 { PwrPolPowerDownFailed, WdfDevStatePwrPolDx TRAP_ON_EVENT }, 72 }; 73 74 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_NotPowerPolOwnerDxStates[] = 75 { 76 { PwrPolPowerUpHwStarted, WdfDevStatePwrPolGotoD0 DEBUGGED_EVENT }, 77 { PwrPolStop, WdfDevStatePwrPolStopping DEBUGGED_EVENT }, 78 { PwrPolSurpriseRemove, WdfDevStatePwrPolStopping DEBUGGED_EVENT }, 79 { PwrPolPowerDownIoStopped, WdfDevStatePwrPolGotoDxInDx TRAP_ON_EVENT }, 80 }; 81 82 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_NotPowerPolOwnerGotoD0States[] = 83 { 84 { PwrPolPowerUp, WdfDevStatePwrPolStartingSucceeded DEBUGGED_EVENT }, 85 { PwrPolPowerUpFailed, WdfDevStatePwrPolStartingSucceeded TRAP_ON_EVENT }, 86 }; 87 88 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_NotPowerPolOwnerGotoD0InD0States[] = 89 { 90 { PwrPolPowerUp, WdfDevStatePwrPolStartingSucceeded TRAP_ON_EVENT }, 91 { PwrPolPowerUpFailed, WdfDevStatePwrPolStartingSucceeded TRAP_ON_EVENT }, 92 }; 93 94 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_NotPowerPolOwnerStoppedStates[] = 95 { 96 { PwrPolStart, WdfDevStatePwrPolStarting DEBUGGED_EVENT }, 97 { PwrPolRemove, WdfDevStatePwrPolRemoved DEBUGGED_EVENT }, 98 }; 99 100 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_NotPowerPolOwnerStoppingWaitForImplicitPowerDownStates[] = 101 { 102 { PwrPolImplicitPowerDown, WdfDevStatePwrPolStoppingSendStatus DEBUGGED_EVENT }, 103 { PwrPolImplicitPowerDownFailed, WdfDevStatePwrPolStoppingFailed DEBUGGED_EVENT }, 104 { PwrPolPowerDownIoStopped, WdfDevStatePwrPolStoppingPoweringDown DEBUGGED_EVENT }, 105 { PwrPolPowerUpHwStarted, WdfDevStatePwrPolStoppingPoweringUp DEBUGGED_EVENT }, 106 }; 107 108 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_NotPowerPolOwnerStoppingPoweringUpStates[] = 109 { 110 { PwrPolPowerUp, WdfDevStatePwrPolStoppingWaitingForImplicitPowerDown DEBUGGED_EVENT }, 111 { PwrPolPowerUpFailed, WdfDevStatePwrPolStoppingWaitingForImplicitPowerDown TRAP_ON_EVENT }, 112 }; 113 114 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_NotPowerPolOwnerStoppingPoweringDownStates[] = 115 { 116 { PwrPolPowerDown, WdfDevStatePwrPolStoppingWaitingForImplicitPowerDown DEBUGGED_EVENT }, 117 { PwrPolPowerDownFailed, WdfDevStatePwrPolStoppingWaitingForImplicitPowerDown DEBUGGED_EVENT }, 118 }; 119 120 const POWER_POLICY_EVENT_TARGET_STATE FxPkgPnp::m_NotPowerPolOwnerRemovedStates[] = 121 { 122 { PwrPolStart, WdfDevStatePwrPolStarting DEBUGGED_EVENT }, 123 { PwrPolRemove, WdfDevStatePwrPolRemoved DEBUGGED_EVENT }, 124 }; 125 126 const NOT_POWER_POLICY_OWNER_STATE_TABLE FxPkgPnp::m_WdfNotPowerPolicyOwnerStates[] = 127 { 128 // current state 129 // transition function, 130 // target states 131 // count of target states 132 // Queue state 133 // 134 { WdfDevStatePwrPolObjectCreated, 135 NULL, 136 FxPkgPnp::m_NotPowerPolOwnerObjectCreatedStates, 137 ARRAY_SIZE(FxPkgPnp::m_NotPowerPolOwnerObjectCreatedStates), 138 TRUE, 139 }, 140 141 { WdfDevStatePwrPolStarting, 142 FxPkgPnp::NotPowerPolOwnerStarting, 143 FxPkgPnp::m_NotPowerPolOwnerStartingStates, 144 ARRAY_SIZE(FxPkgPnp::m_NotPowerPolOwnerStartingStates), 145 FALSE, 146 }, 147 148 { WdfDevStatePwrPolStarted, 149 FxPkgPnp::NotPowerPolOwnerStarted, 150 NULL, 151 0, 152 FALSE, 153 }, 154 155 { WdfDevStatePwrPolStartingSucceeded, 156 NULL, 157 FxPkgPnp::m_NotPowerPolOwnerStartingSucceededStates, 158 ARRAY_SIZE(FxPkgPnp::m_NotPowerPolOwnerStartingSucceededStates), 159 TRUE, 160 }, 161 162 { WdfDevStatePwrPolGotoDx, 163 FxPkgPnp::NotPowerPolOwnerGotoDx, 164 FxPkgPnp::m_NotPowerPolOwnerGotoDxStates, 165 ARRAY_SIZE(FxPkgPnp::m_NotPowerPolOwnerGotoDxStates), 166 FALSE, 167 }, 168 169 { WdfDevStatePwrPolGotoDxInDx, 170 FxPkgPnp::NotPowerPolOwnerGotoDxInDx, 171 FxPkgPnp::m_NotPowerPolOwnerGotoDxInDxStates, 172 ARRAY_SIZE(FxPkgPnp::m_NotPowerPolOwnerGotoDxInDxStates), 173 FALSE, 174 }, 175 176 { WdfDevStatePwrPolDx, 177 NULL, 178 FxPkgPnp::m_NotPowerPolOwnerDxStates, 179 ARRAY_SIZE(FxPkgPnp::m_NotPowerPolOwnerDxStates), 180 TRUE, 181 }, 182 183 { WdfDevStatePwrPolGotoD0, 184 FxPkgPnp::NotPowerPolOwnerGotoD0, 185 FxPkgPnp::m_NotPowerPolOwnerGotoD0States, 186 ARRAY_SIZE(FxPkgPnp::m_NotPowerPolOwnerGotoD0States), 187 FALSE, 188 }, 189 190 { WdfDevStatePwrPolGotoD0InD0, 191 FxPkgPnp::NotPowerPolOwnerGotoD0InD0, 192 FxPkgPnp::m_NotPowerPolOwnerGotoD0InD0States, 193 ARRAY_SIZE(FxPkgPnp::m_NotPowerPolOwnerGotoD0InD0States), 194 FALSE, 195 }, 196 197 { WdfDevStatePwrPolStopping, 198 FxPkgPnp::NotPowerPolOwnerStopping, 199 NULL, 200 0, 201 FALSE, 202 }, 203 204 { WdfDevStatePwrPolStoppingSendStatus, 205 FxPkgPnp::NotPowerPolOwnerStoppingSendStatus, 206 NULL, 207 0, 208 FALSE, 209 }, 210 211 { WdfDevStatePwrPolStartingFailed, 212 FxPkgPnp::NotPowerPolOwnerStartingFailed, 213 FxPkgPnp::m_NotPowerPolOwnerStartingFailedStates, 214 ARRAY_SIZE(FxPkgPnp::m_NotPowerPolOwnerStartingFailedStates), 215 TRUE, 216 }, 217 218 { WdfDevStatePwrPolStoppingFailed, 219 FxPkgPnp::NotPowerPolOwnerStoppingFailed, 220 NULL, 221 0, 222 FALSE, 223 }, 224 225 { WdfDevStatePwrPolStopped, 226 NULL, 227 FxPkgPnp::m_NotPowerPolOwnerStoppedStates, 228 ARRAY_SIZE(FxPkgPnp::m_NotPowerPolOwnerStoppedStates), 229 TRUE, 230 }, 231 232 { WdfDevStatePwrPolStoppingWaitingForImplicitPowerDown, 233 NULL, 234 FxPkgPnp::m_NotPowerPolOwnerStoppingWaitForImplicitPowerDownStates, 235 ARRAY_SIZE(FxPkgPnp::m_NotPowerPolOwnerStoppingWaitForImplicitPowerDownStates), 236 TRUE, 237 }, 238 239 { WdfDevStatePwrPolStoppingPoweringUp, 240 FxPkgPnp::NotPowerPolOwnerStoppingPoweringUp, 241 FxPkgPnp::m_NotPowerPolOwnerStoppingPoweringUpStates, 242 ARRAY_SIZE(FxPkgPnp::m_NotPowerPolOwnerStoppingPoweringUpStates), 243 FALSE, 244 }, 245 246 { WdfDevStatePwrPolStoppingPoweringDown, 247 FxPkgPnp::NotPowerPolOwnerStoppingPoweringDown, 248 FxPkgPnp::m_NotPowerPolOwnerStoppingPoweringDownStates, 249 ARRAY_SIZE(FxPkgPnp::m_NotPowerPolOwnerStoppingPoweringDownStates), 250 FALSE, 251 }, 252 253 { WdfDevStatePwrPolRemoved, 254 FxPkgPnp::NotPowerPolOwnerRemoved, 255 FxPkgPnp::m_NotPowerPolOwnerRemovedStates, 256 ARRAY_SIZE(FxPkgPnp::m_NotPowerPolOwnerRemovedStates), 257 TRUE, 258 }, 259 260 // the last entry must have WdfDevStatePwrPolNull as the current state 261 { WdfDevStatePwrPolNull, 262 NULL, 263 NULL, 264 0, 265 FALSE, 266 }, 267 }; 268 269 VOID 270 FxPkgPnp::NotPowerPolicyOwnerEnterNewState( 271 __in WDF_DEVICE_POWER_POLICY_STATE NewState 272 ) 273 { 274 CPNOT_POWER_POLICY_OWNER_STATE_TABLE entry; 275 WDF_DEVICE_POWER_POLICY_STATE currentState, newState; 276 WDF_DEVICE_POWER_POLICY_NOTIFICATION_DATA data; 277 278 currentState = m_Device->GetDevicePowerPolicyState(); 279 newState = NewState; 280 281 while (newState != WdfDevStatePwrPolNull) { 282 DoTraceLevelMessage( 283 GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGPNPPOWERSTATES, 284 "WDFDEVICE 0x%p !devobj 0x%p entering not power policy owner state " 285 "%!WDF_DEVICE_POWER_POLICY_STATE! from " 286 "%!WDF_DEVICE_POWER_POLICY_STATE!", m_Device->GetHandle(), 287 m_Device->GetDeviceObject(), newState, currentState); 288 289 if (m_PowerPolicyStateCallbacks != NULL) { 290 // 291 // Callback for leaving the old state 292 // 293 RtlZeroMemory(&data, sizeof(data)); 294 295 data.Type = StateNotificationLeaveState; 296 data.Data.LeaveState.CurrentState = currentState; 297 data.Data.LeaveState.NewState = newState; 298 299 m_PowerPolicyStateCallbacks->Invoke(currentState, 300 StateNotificationLeaveState, 301 m_Device->GetHandle(), 302 &data); 303 } 304 305 m_PowerPolicyMachine.m_States.History[ 306 m_PowerPolicyMachine.IncrementHistoryIndex()] = (USHORT) newState; 307 308 if (m_PowerPolicyStateCallbacks != NULL) { 309 // 310 // Callback for entering the new state 311 // 312 RtlZeroMemory(&data, sizeof(data)); 313 314 data.Type = StateNotificationEnterState; 315 data.Data.EnterState.CurrentState = currentState; 316 data.Data.EnterState.NewState = newState; 317 318 m_PowerPolicyStateCallbacks->Invoke(newState, 319 StateNotificationEnterState, 320 m_Device->GetHandle(), 321 &data); 322 } 323 324 m_Device->SetDevicePowerPolicyState(newState); 325 currentState = newState; 326 327 entry = GetNotPowerPolicyOwnerTableEntry(currentState); 328 329 // 330 // Call the state handler, if there is one. 331 // 332 if (entry->StateFunc != NULL) { 333 newState = entry->StateFunc(this); 334 } 335 else { 336 newState = WdfDevStatePwrPolNull; 337 } 338 339 if (m_PowerPolicyStateCallbacks != NULL) { 340 // 341 // Callback for post processing the new state 342 // 343 RtlZeroMemory(&data, sizeof(data)); 344 345 data.Type = StateNotificationPostProcessState; 346 data.Data.PostProcessState.CurrentState = currentState; 347 348 m_PowerPolicyStateCallbacks->Invoke(currentState, 349 StateNotificationPostProcessState, 350 m_Device->GetHandle(), 351 &data); 352 } 353 } 354 } 355 356 WDF_DEVICE_POWER_POLICY_STATE 357 FxPkgPnp::NotPowerPolOwnerStarting( 358 __inout FxPkgPnp* This 359 ) 360 /*++ 361 362 Routine Description: 363 Starting the power policy state machine for a device which is not the power 364 policy owner. Tell the power state machine to start up. 365 366 Arguments: 367 This - instance of the state machine 368 369 Return Value: 370 WdfDevStatePwrPolNull 371 372 --*/ 373 { 374 This->PowerProcessEvent(PowerImplicitD0); 375 return WdfDevStatePwrPolNull; 376 } 377 378 WDF_DEVICE_POWER_POLICY_STATE 379 FxPkgPnp::NotPowerPolOwnerStarted( 380 __inout FxPkgPnp* This 381 ) 382 /*++ 383 384 Routine Description: 385 Starting the power policy state machine for a device which is not the power 386 policy owner has succeeded. Indicate status to the pnp state machine. 387 388 Arguments: 389 This - instance of the state machine 390 391 Return Value: 392 WdfDevStatePwrPolNull 393 394 --*/ 395 { 396 This->PnpProcessEvent(PnpEventPwrPolStarted); 397 return WdfDevStatePwrPolStartingSucceeded; 398 } 399 400 WDF_DEVICE_POWER_POLICY_STATE 401 FxPkgPnp::NotPowerPolOwnerGotoDx( 402 __inout FxPkgPnp* This 403 ) 404 { 405 This->PowerProcessEvent(PowerCompleteDx); 406 return WdfDevStatePwrPolNull; 407 } 408 409 WDF_DEVICE_POWER_POLICY_STATE 410 FxPkgPnp::NotPowerPolOwnerGotoDxInDx( 411 __inout FxPkgPnp* This 412 ) 413 { 414 This->PowerProcessEvent(PowerCompleteDx); 415 return WdfDevStatePwrPolNull; 416 } 417 418 WDF_DEVICE_POWER_POLICY_STATE 419 FxPkgPnp::NotPowerPolOwnerGotoD0( 420 __inout FxPkgPnp* This 421 ) 422 { 423 This->PowerProcessEvent(PowerCompleteD0); 424 return WdfDevStatePwrPolNull; 425 } 426 427 WDF_DEVICE_POWER_POLICY_STATE 428 FxPkgPnp::NotPowerPolOwnerGotoD0InD0( 429 __inout FxPkgPnp* This 430 ) 431 { 432 This->PowerProcessEvent(PowerCompleteD0); 433 return WdfDevStatePwrPolNull; 434 } 435 436 WDF_DEVICE_POWER_POLICY_STATE 437 FxPkgPnp::NotPowerPolOwnerStopping( 438 __inout FxPkgPnp* This 439 ) 440 /*++ 441 442 Routine Description: 443 Stopping the power policy state machine for a device which is not the power 444 policy owner. Tell the power state machine to power down. 445 446 Arguments: 447 This - instance of the state machine 448 449 Return Value: 450 WdfDevStatePwrPolStoppingWaitingForImplicitPowerDown 451 452 --*/ 453 { 454 This->PowerProcessEvent(PowerImplicitD3); 455 return WdfDevStatePwrPolStoppingWaitingForImplicitPowerDown; 456 } 457 458 WDF_DEVICE_POWER_POLICY_STATE 459 FxPkgPnp::NotPowerPolOwnerStoppingSendStatus( 460 __inout FxPkgPnp* This 461 ) 462 /*++ 463 464 Routine Description: 465 Stopping the power policy state machine for a device which is not the power 466 policy owner has succeeded. Inidcate status to the pnp state machine. 467 468 Arguments: 469 This - instance of the state machine 470 471 Return Value: 472 WdfDevStatePwrPolStopped 473 474 --*/ 475 { 476 This->PnpProcessEvent(PnpEventPwrPolStopped); 477 return WdfDevStatePwrPolStopped; 478 } 479 480 WDF_DEVICE_POWER_POLICY_STATE 481 FxPkgPnp::NotPowerPolOwnerStartingFailed( 482 __inout FxPkgPnp* This 483 ) 484 /*++ 485 486 Routine Description: 487 Starting the power policy state machine for a device which is not the power 488 policy owner has failed. Inidcate status to the pnp state machine. 489 490 Arguments: 491 This - instance of the state machine 492 493 Return Value: 494 WdfDevStatePwrPolNull 495 496 --*/ 497 { 498 This->PnpProcessEvent(PnpEventPwrPolStartFailed); 499 return WdfDevStatePwrPolNull; 500 } 501 502 WDF_DEVICE_POWER_POLICY_STATE 503 FxPkgPnp::NotPowerPolOwnerStoppingFailed( 504 __inout FxPkgPnp* This 505 ) 506 /*++ 507 508 Routine Description: 509 Stopping the power policy state machine for a device which is not the power 510 policy owner has failed. Inidcate status to the pnp state machine. 511 512 Arguments: 513 This - instance of the state machine 514 515 Return Value: 516 WdfDevStatePwrPolStopped 517 518 --*/ 519 { 520 This->PnpProcessEvent(PnpEventPwrPolStopFailed); 521 return WdfDevStatePwrPolStopped; 522 } 523 524 WDF_DEVICE_POWER_POLICY_STATE 525 FxPkgPnp::NotPowerPolOwnerStoppingPoweringUp( 526 __inout FxPkgPnp* This 527 ) 528 /*++ 529 530 Routine Description: 531 Right as we attempted to implicitly power down, a real D0 irp came into the 532 stack. Complete the D0 irp in the power state machine so that the power 533 state machine can process the implicit power irp 534 535 Arguments: 536 This - instance of the state machine 537 538 Return Value: 539 WdfDevStatePwrPolNull 540 541 --*/ 542 { 543 This->PowerProcessEvent(PowerCompleteD0); 544 return WdfDevStatePwrPolNull; 545 } 546 547 WDF_DEVICE_POWER_POLICY_STATE 548 FxPkgPnp::NotPowerPolOwnerStoppingPoweringDown( 549 __inout FxPkgPnp* This 550 ) 551 /*++ 552 553 Routine Description: 554 Right as we attempted to implicitly power down, a real Dx irp came into the 555 stack. Complete the Dx irp in the power state machine so that the power 556 state machine can process the implicit power irp 557 558 Arguments: 559 This - instance of the state machine 560 561 Return Value: 562 WdfDevStatePwrPolNull 563 564 --*/ 565 { 566 This->PowerProcessEvent(PowerCompleteDx); 567 return WdfDevStatePwrPolNull; 568 } 569 570 WDF_DEVICE_POWER_POLICY_STATE 571 FxPkgPnp::NotPowerPolOwnerRemoved( 572 __inout FxPkgPnp* This 573 ) 574 /*++ 575 576 Routine Description: 577 The device is being removed, so prepare for removal. 578 579 Arguments: 580 This - instance of the state machine 581 582 Return Value: 583 WdfDevStatePwrPolNull 584 585 --*/ 586 { 587 // 588 // Since we are not the power policy owner, there is nothing to be done. 589 // Indicate to the PNP state machine that we are ready for removal. 590 // 591 This->PnpProcessEvent(PnpEventPwrPolRemoved); 592 return WdfDevStatePwrPolNull; 593 } 594