1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839
/* * Copyright (c) 2019-2020 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. The rights granted to you under the License * may not be used to create, or enable the creation or redistribution of, * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ #ifndef _IOKIT_IOSERVICEPMPRIVATE_H #define _IOKIT_IOSERVICEPMPRIVATE_H #include <IOKit/IOCommand.h> #include <IOKit/IOEventSource.h> #include <vm/vm_compressor_xnu.h> #define USE_SETTLE_TIMER 0 //****************************************************************************** // PM command types //****************************************************************************** enum { /* Command Types */ kIOPMRequestTypeInvalid = 0x00, kIOPMRequestTypePMStop = 0x01, kIOPMRequestTypeAddPowerChild1 = 0x02, kIOPMRequestTypeAddPowerChild2 = 0x03, kIOPMRequestTypeAddPowerChild3 = 0x04, kIOPMRequestTypeRegisterPowerDriver = 0x05, kIOPMRequestTypeAdjustPowerState = 0x06, kIOPMRequestTypePowerDomainWillChange = 0x07, kIOPMRequestTypePowerDomainDidChange = 0x08, kIOPMRequestTypePowerOverrideOnPriv = 0x09, kIOPMRequestTypePowerOverrideOffPriv = 0x0A, kIOPMRequestTypeActivityTickle = 0x0B, kIOPMRequestTypeRequestPowerState = 0x0C, kIOPMRequestTypeSynchronizePowerTree = 0x0D, kIOPMRequestTypeRequestPowerStateOverride = 0x0E, kIOPMRequestTypeSetIdleTimerPeriod = 0x0F, kIOPMRequestTypeIgnoreIdleTimer = 0x10, kIOPMRequestTypeQuiescePowerTree = 0x11, kIOPMRequestTypeDeferredActivityTickle = 0x12, /* Reply Types */ kIOPMRequestTypeReplyStart = 0x80, kIOPMRequestTypeAckPowerChange = 0x81, kIOPMRequestTypeAckSetPowerState = 0x82, kIOPMRequestTypeAllowPowerChange = 0x83, kIOPMRequestTypeCancelPowerChange = 0x84, kIOPMRequestTypeInterestChanged = 0x85, kIOPMRequestTypeIdleCancel = 0x86, kIOPMRequestTypeChildNotifyDelayCancel = 0x87 }; //****************************************************************************** // PM actions - For root domain only //****************************************************************************** struct IOPMActions; typedef void (*IOPMActionPowerChangeStart)( void * target, IOService * service, IOPMActions * actions, const IOPMRequest * request, IOPMPowerStateIndex powerState, IOPMPowerChangeFlags * changeFlagsPtr ); typedef void (*IOPMActionPowerChangeDone)( void * target, IOService * service, IOPMActions * actions, const IOPMRequest * request, IOPMPowerStateIndex powerState, IOPMPowerChangeFlags changeFlags ); typedef void (*IOPMActionPowerChangeOverride)( void * target, IOService * service, IOPMActions * actions, const IOPMRequest * request, IOPMPowerStateIndex * powerStatePtr, IOPMPowerChangeFlags * changeFlagsPtr ); typedef void (*IOPMActionActivityTickle)( void * target, IOService * service, IOPMActions * actions ); typedef void (*IOPMActionUpdatePowerClient)( void * target, IOService * service, IOPMActions * actions, const OSSymbol * powerClient, IOPMPowerStateIndex oldPowerState, IOPMPowerStateIndex newPowerState ); struct IOPMActions { void * target; IOPMActionPowerChangeStart actionPowerChangeStart; IOPMActionPowerChangeDone actionPowerChangeDone; IOPMActionPowerChangeOverride actionPowerChangeOverride; IOPMActionActivityTickle actionActivityTickle; IOPMActionUpdatePowerClient actionUpdatePowerClient; uint32_t darkWakePowerState; uint16_t flags; uint16_t state; }; // IOPMActions flags enum { kPMActionsPCIBitNumberMask = 0x00ff, kPMActionsFlagIsDisplayWrangler = 0x0100, kPMActionsFlagIsGraphicsDriver = 0x0200, kPMActionsFlagIsAudioDriver = 0x0400, kPMActionsFlagHasDarkWakePowerState = 0x0800 }; // IOPMActions state enum { kPMActionsStatePowerClamped = 0x0001 }; //****************************************************************************** // Internal concise representation of IOPMPowerState struct IOPMPSEntry { IOPMPowerFlags capabilityFlags; IOPMPowerFlags outputPowerFlags; IOPMPowerFlags inputPowerFlags; unsigned long staticPower; #if USE_SETTLE_TIMER uint32_t settleUpTime; uint32_t settleDownTime; #endif IOPMPowerStateIndex stateOrder; IOPMPowerStateIndex stateOrderToIndex; }; //****************************************************************************** // IOServicePM //****************************************************************************** class IOServicePM : public OSObject { friend class IOService; friend class IOPMWorkQueue; OSDeclareDefaultStructors( IOServicePM ); private: // Link IOServicePM objects on IOPMWorkQueue. queue_chain_t WorkChain; // Queue of IOPMRequest objects. queue_head_t RequestHead; // IOService creator and owner. IOService * Owner; // List of interested drivers (protected by PMLock). IOPMinformeeList * InterestedDrivers; // How long to wait for controlling driver to acknowledge. IOReturn DriverTimer; // Current power management machine state. uint32_t MachineState; thread_call_t AckTimer; #if USE_SETTLE_TIMER thread_call_t SettleTimer; #endif thread_call_t IdleTimer; thread_call_t WatchdogTimer; thread_call_t SpinDumpTimer; IOLock * WatchdogLock; OSArray * BlockedArray; uint64_t PendingResponseDeadline; uint64_t WatchdogDeadline; uint64_t WatchdogStart; // Settle time after changing power state. #if USE_SETTLE_TIMER uint32_t SettleTimeUS; #endif IOPMPowerStateIndex IdleTimerGeneration; // The flags describing current change note. IOPMPowerChangeFlags HeadNoteChangeFlags; // The new power state number being changed to. IOPMPowerStateIndex HeadNotePowerState; // Points to the entry in the power state array. IOPMPSEntry * HeadNotePowerArrayEntry; // Power flags supplied by all parents (domain). IOPMPowerFlags HeadNoteDomainFlags; // Power flags supplied by domain accounting for parent changes. IOPMPowerFlags HeadNoteDomainTargetFlags; // Connection attached to the changing parent. IOPowerConnection * HeadNoteParentConnection; // Power flags supplied by the changing parent. IOPMPowerFlags HeadNoteParentFlags; // Number of acks still outstanding. uint32_t HeadNotePendingAcks; // PM state lock. IOLock * PMLock; unsigned int InitialPowerChange :1; unsigned int InitialSetPowerState :1; unsigned int DeviceOverrideEnabled :1; unsigned int DoNotPowerDown :1; unsigned int ParentsKnowState :1; unsigned int StrictTreeOrder :1; unsigned int IdleTimerStopped :1; unsigned int AdjustPowerScheduled :1; unsigned int IsPreChange :1; unsigned int DriverCallBusy :1; unsigned int PCDFunctionOverride :1; unsigned int IdleTimerIgnored :1; unsigned int HasAdvisoryDesire :1; unsigned int AdvisoryTickleUsed :1; unsigned int ResetPowerStateOnWake :1; // Time of last device activity. AbsoluteTime DeviceActiveTimestamp; AbsoluteTime MaxPowerStateEntryTime; AbsoluteTime MaxPowerStateExitTime; // Used to protect activity flag. IOLock * ActivityLock; // Idle timer's period in seconds. int IdleTimerPeriod; int NextIdleTimerPeriod; IOPMPowerStateIndex IdleTimerMinPowerState; AbsoluteTime IdleTimerStartTime; // Power state desired by a subclassed device object. IOPMPowerStateIndex DeviceDesire; // This is the power state we desire currently. IOPMPowerStateIndex DesiredPowerState; // This is what our parent thinks our need is. IOPMPowerFlags PreviousRequestPowerFlags; // Cache result from getName(), used in logging. const char * Name; // Number of power states in the power array. IOPMPowerStateIndex NumberOfPowerStates; // Ordered highest power state in the power array. IOPMPowerStateIndex HighestPowerState; // Power state array. IOPMPSEntry * PowerStates; // The controlling driver. IOService * ControllingDriver; // Our current power state. IOPMPowerStateIndex CurrentPowerState; // Logical OR of power flags for each power domain parent. IOPMPowerFlags ParentsCurrentPowerFlags; // The highest power state we can achieve in current power domain. IOPMPowerStateIndex MaxPowerState; // Logical OR of all output power flags in the power state array. IOPMPowerFlags MergedOutputPowerFlags; // OSArray which manages responses from notified apps and clients. OSArray * ResponseArray; OSArray * NotifyClientArray; // Used to uniquely identify power management notification to apps and clients. uint16_t SerialNumber; // Used to communicate desired function to tellClientsWithResponse(). // This is used because it avoids changing the signatures of the affected virtual methods. int OutOfBandParameter; AbsoluteTime DriverCallStartTime; IOPMPowerFlags CurrentCapabilityFlags; unsigned long CurrentPowerConsumption; IOPMPowerStateIndex TempClampPowerState; OSArray * NotifyChildArray; OSDictionary * PowerClients; thread_call_t DriverCallEntry; void * DriverCallParamPtr; IOItemCount DriverCallParamCount; IOItemCount DriverCallParamSlots; uint32_t DriverCallReason; uint32_t OutOfBandMessage; uint32_t TempClampCount; IOPMPowerStateIndex OverrideMaxPowerState; IOPMPowerStateIndex DeviceUsablePowerState; // Thread to be run alongside DriverCallEntry to provide logging. thread_call_t DriverCallTimer; // Protected by ActivityLock - BEGIN IOPMPowerStateIndex ActivityTicklePowerState; IOPMPowerStateIndex AdvisoryTicklePowerState; uint32_t ActivityTickleCount; uint32_t DeviceWasActive : 1; uint32_t AdvisoryTickled : 1; // Protected by ActivityLock - END uint32_t WaitReason; uint32_t SavedMachineState; // Protected by PMLock - BEGIN struct { uint32_t PMStop : 1; uint32_t PMDriverCallWait : 1; } LockedFlags; queue_head_t PMDriverCallQueue; OSSet * InsertInterestSet; OSSet * RemoveInterestSet; // IOReporter Data uint32_t ReportClientCnt; void * ReportBuf; // Protected by PMLock - END #if PM_VARS_SUPPORT IOPMprot * PMVars; #endif IOPMActions PMActions; uint64_t PMDriverClass; #define fPMDriverClass pwrMgt->PMDriverClass // Serialize IOServicePM state for debug output. IOReturn gatedSerialize( OSSerialize * s ) const; virtual bool serialize( OSSerialize * s ) const APPLE_KEXT_OVERRIDE; // PM log and trace void pmPrint( uint32_t event, uintptr_t param1, uintptr_t param2 ) const; void pmTrace( uint32_t event, uint32_t eventFunc, uintptr_t param1, uintptr_t param2 ) const; }; #define fOwner pwrMgt->Owner #define fInterestedDrivers pwrMgt->InterestedDrivers #define fDriverTimer pwrMgt->DriverTimer #define fMachineState pwrMgt->MachineState #define fAckTimer pwrMgt->AckTimer #define fSettleTimer pwrMgt->SettleTimer #define fIdleTimer pwrMgt->IdleTimer #define fWatchdogTimer pwrMgt->WatchdogTimer #define fWatchdogDeadline pwrMgt->WatchdogDeadline #define fWatchdogStart pwrMgt->WatchdogStart #define fWatchdogLock pwrMgt->WatchdogLock #define fBlockedArray pwrMgt->BlockedArray #define fPendingResponseDeadline pwrMgt->PendingResponseDeadline #define fSettleTimeUS pwrMgt->SettleTimeUS #define fIdleTimerGeneration pwrMgt->IdleTimerGeneration #define fHeadNoteChangeFlags pwrMgt->HeadNoteChangeFlags #define fHeadNotePowerState pwrMgt->HeadNotePowerState #define fHeadNotePowerArrayEntry pwrMgt->HeadNotePowerArrayEntry #define fHeadNoteDomainFlags pwrMgt->HeadNoteDomainFlags #define fHeadNoteDomainTargetFlags pwrMgt->HeadNoteDomainTargetFlags #define fHeadNoteParentConnection pwrMgt->HeadNoteParentConnection #define fHeadNoteParentFlags pwrMgt->HeadNoteParentFlags #define fHeadNotePendingAcks pwrMgt->HeadNotePendingAcks #define fPMLock pwrMgt->PMLock #define fInitialPowerChange pwrMgt->InitialPowerChange #define fInitialSetPowerState pwrMgt->InitialSetPowerState #define fDeviceOverrideEnabled pwrMgt->DeviceOverrideEnabled #define fDoNotPowerDown pwrMgt->DoNotPowerDown #define fParentsKnowState pwrMgt->ParentsKnowState #define fStrictTreeOrder pwrMgt->StrictTreeOrder #define fIdleTimerStopped pwrMgt->IdleTimerStopped #define fAdjustPowerScheduled pwrMgt->AdjustPowerScheduled #define fIsPreChange pwrMgt->IsPreChange #define fDriverCallBusy pwrMgt->DriverCallBusy #define fPCDFunctionOverride pwrMgt->PCDFunctionOverride #define fIdleTimerIgnored pwrMgt->IdleTimerIgnored #define fHasAdvisoryDesire pwrMgt->HasAdvisoryDesire #define fAdvisoryTickleUsed pwrMgt->AdvisoryTickleUsed #define fResetPowerStateOnWake pwrMgt->ResetPowerStateOnWake #define fDeviceActiveTimestamp pwrMgt->DeviceActiveTimestamp #define fMaxPowerStateEntryTime pwrMgt->MaxPowerStateEntryTime #define fMaxPowerStateExitTime pwrMgt->MaxPowerStateExitTime #define fActivityLock pwrMgt->ActivityLock #define fIdleTimerPeriod pwrMgt->IdleTimerPeriod #define fIdleTimerMinPowerState pwrMgt->IdleTimerMinPowerState #define fNextIdleTimerPeriod pwrMgt->NextIdleTimerPeriod #define fIdleTimerStartTime pwrMgt->IdleTimerStartTime #define fDeviceDesire pwrMgt->DeviceDesire #define fDesiredPowerState pwrMgt->DesiredPowerState #define fPreviousRequestPowerFlags pwrMgt->PreviousRequestPowerFlags #define fName pwrMgt->Name #define fNumberOfPowerStates pwrMgt->NumberOfPowerStates #define fHighestPowerState pwrMgt->HighestPowerState #define fPowerStates pwrMgt->PowerStates #define fControllingDriver pwrMgt->ControllingDriver #define fCurrentPowerState pwrMgt->CurrentPowerState #define fParentsCurrentPowerFlags pwrMgt->ParentsCurrentPowerFlags #define fMaxPowerState pwrMgt->MaxPowerState #define fMergedOutputPowerFlags pwrMgt->MergedOutputPowerFlags #define fResponseArray pwrMgt->ResponseArray #define fNotifyClientArray pwrMgt->NotifyClientArray #define fSerialNumber pwrMgt->SerialNumber #define fOutOfBandParameter pwrMgt->OutOfBandParameter #define fDriverCallStartTime pwrMgt->DriverCallStartTime #define fCurrentCapabilityFlags pwrMgt->CurrentCapabilityFlags #define fCurrentPowerConsumption pwrMgt->CurrentPowerConsumption #define fTempClampPowerState pwrMgt->TempClampPowerState #define fNotifyChildArray pwrMgt->NotifyChildArray #define fPowerClients pwrMgt->PowerClients #define fDriverCallEntry pwrMgt->DriverCallEntry #define fDriverCallParamPtr pwrMgt->DriverCallParamPtr #define fDriverCallParamCount pwrMgt->DriverCallParamCount #define fDriverCallParamSlots pwrMgt->DriverCallParamSlots #define fDriverCallReason pwrMgt->DriverCallReason #define fOutOfBandMessage pwrMgt->OutOfBandMessage #define fTempClampCount pwrMgt->TempClampCount #define fOverrideMaxPowerState pwrMgt->OverrideMaxPowerState #define fDeviceUsablePowerState pwrMgt->DeviceUsablePowerState #define fDriverCallTimer pwrMgt->DriverCallTimer #define fActivityTicklePowerState pwrMgt->ActivityTicklePowerState #define fAdvisoryTicklePowerState pwrMgt->AdvisoryTicklePowerState #define fActivityTickleCount pwrMgt->ActivityTickleCount #define fDeviceWasActive pwrMgt->DeviceWasActive #define fAdvisoryTickled pwrMgt->AdvisoryTickled #define fWaitReason pwrMgt->WaitReason #define fSavedMachineState pwrMgt->SavedMachineState #define fLockedFlags pwrMgt->LockedFlags #define fPMDriverCallQueue pwrMgt->PMDriverCallQueue #define fInsertInterestSet pwrMgt->InsertInterestSet #define fRemoveInterestSet pwrMgt->RemoveInterestSet #define fReportClientCnt pwrMgt->ReportClientCnt #define fReportBuf pwrMgt->ReportBuf #define fPMVars pwrMgt->PMVars #define fPMActions pwrMgt->PMActions #define StateOrder(state) (((state) < fNumberOfPowerStates) \ ? pwrMgt->PowerStates[(state)].stateOrder \ : (state)) #define StateMax(a, b) (StateOrder((a)) < StateOrder((b)) ? (b) : (a)) #define StateMin(a, b) (StateOrder((a)) < StateOrder((b)) ? (a) : (b)) #define kPowerStateZero (0) /* * When an IOService is waiting for acknowledgement to a power change * notification from an interested driver or the controlling driver, * the ack timer is ticking every tenth of a second. * (100000000 nanoseconds are one tenth of a second). */ #define ACK_TIMER_PERIOD 100000000 #if defined(__i386__) || defined(__x86_64__) #define WATCHDOG_SLEEP_TIMEOUT (180) // 180 secs #define WATCHDOG_WAKE_TIMEOUT (180) // 180 secs #else #define WATCHDOG_SLEEP_TIMEOUT (35) // 35 secs (kMaxTimeRequested + 5s) #define WATCHDOG_WAKE_TIMEOUT (35) // 35 secs (kMaxTimeRequested + 5s) #endif #define WATCHDOG_HIBERNATION_TIMEOUT (180) // Max wait time in microseconds for kernel priority and capability clients // with async message handlers to acknowledge. // #define kPriorityClientMaxWait (90 * 1000 * 1000) #define kCapabilityClientMaxWait (240 * 1000 * 1000) // Attributes describing a power state change. // See IOPMPowerChangeFlags data type. // #define kIOPMParentInitiated 0x0001 // power change initiated by our parent #define kIOPMSelfInitiated 0x0002 // power change initiated by this device #define kIOPMNotDone 0x0004 // we couldn't make this change #define kIOPMDomainWillChange 0x0008 // change started by PowerDomainWillChangeTo #define kIOPMDomainDidChange 0x0010 // change started by PowerDomainDidChangeTo #define kIOPMDomainPowerDrop 0x0020 // Domain is lowering power #define kIOPMIgnoreChildren 0x0040 // Ignore children and driver power desires #define kIOPMSkipAskPowerDown 0x0080 // skip the ask app phase #define kIOPMSynchronize 0x0100 // change triggered by power tree re-sync #define kIOPMSyncNoChildNotify 0x0200 // sync root domain only, not entire tree #define kIOPMSyncTellPowerDown 0x0400 // send the ask/will power off messages #define kIOPMSyncCancelPowerDown 0x0800 // sleep cancel for maintenance wake #define kIOPMInitialPowerChange 0x1000 // set for initial power change #define kIOPMRootChangeUp 0x2000 // Root power domain change up #define kIOPMRootChangeDown 0x4000 // Root power domain change down #define kIOPMExpireIdleTimer 0x8000 // Accelerate idle timer expiration #define kIOPMRootBroadcastFlags (kIOPMSynchronize | \ kIOPMRootChangeUp | kIOPMRootChangeDown) // Activity tickle request flags #define kTickleTypePowerDrop 0x01 #define kTickleTypePowerRise 0x02 #define kTickleTypeActivity 0x04 #define kTickleTypeAdvisory 0x08 enum { kDriverCallInformPreChange, kDriverCallInformPostChange, kDriverCallSetPowerState, kRootDomainInformPreChange }; struct DriverCallParam { OSObject * Target; IOReturn Result; }; // values of OutOfBandParameter enum { kNotifyApps, kNotifyPriority, kNotifyCapabilityChangeApps, kNotifyCapabilityChangePriority }; typedef bool (*IOPMMessageFilter)( void * target, void * object, void * arg1, void * arg2, void * arg3 ); // used for applyToInterested struct IOPMInterestContext { OSArray * responseArray; OSArray * notifyClients; uint16_t serialNumber; uint8_t isPreChange; uint8_t enableTracing; uint32_t maxTimeRequested; uint32_t messageType; uint32_t notifyType; uint32_t skippedInDark; uint32_t notSkippedInDark; IOService * us; IOPMPowerStateIndex stateNumber; IOPMPowerFlags stateFlags; IOPMPowerChangeFlags changeFlags; IOPMMessageFilter messageFilter; }; // track client ack requirements class IOPMClientAck : public OSObject { OSDeclareDefaultStructors( IOPMClientAck ); public: uint64_t completionTimestamp; // absolute time uint32_t maxTimeRequested; // microseconds }; // assertPMDriverCall() options enum { kIOPMDriverCallNoInactiveCheck = 1 }; // assertPMDriverCall() method enum { kIOPMDriverCallMethodUnknown = 0, kIOPMDriverCallMethodSetPowerState = 1, kIOPMDriverCallMethodWillChange = 2, kIOPMDriverCallMethodDidChange = 3, kIOPMDriverCallMethodChangeDone = 4, kIOPMDriverCallMethodSetAggressive = 5, kIOPMDriverCallMethodMaxCapabilityForDomainState = 6, kIOPMDriverCallMethodInitialPowerStateForDomainState = 7 }; extern uint64_t gLPWFlags; //****************************************************************************** // PM Statistics & Diagnostics //****************************************************************************** extern OSPtr<const OSSymbol> gIOPMStatsResponseTimedOut; extern OSPtr<const OSSymbol> gIOPMStatsResponseCancel; extern OSPtr<const OSSymbol> gIOPMStatsResponseSlow; extern OSPtr<const OSSymbol> gIOPMStatsResponsePrompt; extern OSPtr<const OSSymbol> gIOPMStatsDriverPSChangeSlow; //****************************************************************************** // IOPMRequest //****************************************************************************** class IOPMRequest : public IOCommand { OSDeclareDefaultStructors( IOPMRequest ); protected: IOService * fTarget; // request target IOPMRequest * fRequestNext; // the next request in the chain IOPMRequest * fRequestRoot; // the root request in the call tree uint32_t fWorkWaitCount; // execution blocked if non-zero uint32_t fFreeWaitCount; // completion blocked if non-zero uint64_t fTimestamp; // MCTU uint32_t fRequestType; // request type bool fIsQuiesceBlocker; IOPMCompletionAction fCompletionAction; void * fCompletionTarget; void * fCompletionParam; public: uint32_t fTag; void * fArg0; void * fArg1; void * fArg2; inline bool isWorkBlocked( void ) const { return fWorkWaitCount != 0; } inline bool isFreeBlocked( void ) const { return fFreeWaitCount != 0; } inline IOPMRequest * getNextRequest( void ) const { return fRequestNext; } inline IOPMRequest * getRootRequest( void ) const { if (fRequestRoot) { return fRequestRoot; } #if NOT_READY if (fCompletionAction) { return (IOPMRequest *) this; } #endif return NULL; } inline uint32_t getType( void ) const { return fRequestType; } inline uint32_t getTag( void ) const { return fTag; } inline bool isReplyType( void ) const { return fRequestType > kIOPMRequestTypeReplyStart; } inline IOService * getTarget( void ) const { return fTarget; } inline bool isQuiesceBlocker( void ) const { return fIsQuiesceBlocker; } inline bool isQuiesceType( void ) const { return (kIOPMRequestTypeQuiescePowerTree == fRequestType) && (fCompletionAction != NULL) && (fCompletionTarget != NULL); } inline void installCompletionAction( void * target, IOPMCompletionAction action, void * param ) { fCompletionTarget = target; fCompletionAction = action; fCompletionParam = param; } inline void setTimestamp( uint64_t time ) { fTimestamp = time; } inline uint64_t getTimestamp( void ) const { return fTimestamp; } static IOPMRequest * create( void ); bool init( IOService * owner, IOOptionBits type ); void reset( void ); bool attachNextRequest( IOPMRequest * next ); bool detachNextRequest( void ); bool attachRootRequest( IOPMRequest * root ); bool detachRootRequest( void ); }; //****************************************************************************** // IOPMRequestQueue //****************************************************************************** class IOPMRequestQueue : public IOEventSource { OSDeclareDefaultStructors( IOPMRequestQueue ); public: typedef bool (*Action)( IOService *, IOPMRequest *, IOPMRequestQueue * ); protected: queue_head_t fQueue; IOLock * fLock; enum { kMaxDequeueCount = 256 }; virtual bool checkForWork( void ) APPLE_KEXT_OVERRIDE; virtual void free( void ) APPLE_KEXT_OVERRIDE; virtual bool init( IOService * inOwner, Action inAction ); public: static IOPMRequestQueue * create( IOService * inOwner, Action inAction ); void queuePMRequest( LIBKERN_CONSUMED IOPMRequest * request ); void queuePMRequestChain( IOPMRequest ** requests, IOItemCount count ); }; //****************************************************************************** // IOPMWorkQueue //****************************************************************************** #define WORK_QUEUE_STATS 1 class IOPMWorkQueue : public IOEventSource { OSDeclareDefaultStructors( IOPMWorkQueue ); public: typedef bool (*Action)( IOService *, IOPMRequest *, IOPMWorkQueue * ); #if WORK_QUEUE_STATS uint64_t fStatCheckForWork; uint64_t fStatScanEntries; uint64_t fStatQueueEmpty; uint64_t fStatNoWorkDone; #endif protected: queue_head_t fWorkQueue; Action fInvokeAction; Action fRetireAction; uint32_t fQueueLength; uint32_t fConsumerCount; volatile uint32_t fProducerCount; IOPMRequest * fQuiesceRequest; AbsoluteTime fQuiesceStartTime; AbsoluteTime fQuiesceFinishTime; virtual bool checkForWork( void ) APPLE_KEXT_OVERRIDE; virtual bool init( IOService * inOwner, Action invoke, Action retire ); bool checkRequestQueue( queue_head_t * queue, bool * empty ); public: static IOPMWorkQueue * create( IOService * inOwner, Action invoke, Action retire ); bool queuePMRequest( IOPMRequest * request, IOServicePM * pwrMgt ); void signalWorkAvailable( void ); void incrementProducerCount( void ); void attachQuiesceRequest( IOPMRequest * quiesceRequest ); void finishQuiesceRequest( IOPMRequest * quiesceRequest ); }; //****************************************************************************** // IOPMCompletionQueue //****************************************************************************** class IOPMCompletionQueue : public IOEventSource { OSDeclareDefaultStructors( IOPMCompletionQueue ); public: typedef bool (*Action)( IOService *, IOPMRequest *, IOPMCompletionQueue * ); protected: queue_head_t fQueue; virtual bool checkForWork( void ) APPLE_KEXT_OVERRIDE; virtual bool init( IOService * inOwner, Action inAction ); public: static IOPMCompletionQueue * create( IOService * inOwner, Action inAction ); bool queuePMRequest( IOPMRequest * request ); }; #endif /* !_IOKIT_IOSERVICEPMPRIVATE_H */