X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/593a1d5fd87cdf5b46dd5fcb84467b432cea0f91..cb3231590a3c94ab4375e2228bd5e86b0cf1ad7e:/iokit/Kernel/IOServicePMPrivate.h?ds=inline diff --git a/iokit/Kernel/IOServicePMPrivate.h b/iokit/Kernel/IOServicePMPrivate.h index 21e9361ff..7d5a2bc54 100644 --- a/iokit/Kernel/IOServicePMPrivate.h +++ b/iokit/Kernel/IOServicePMPrivate.h @@ -1,8 +1,8 @@ /* - * Copyright (c) 2007 Apple Inc. All rights reserved. + * Copyright (c) 2019 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 @@ -11,10 +11,10 @@ * 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, @@ -22,550 +22,761 @@ * 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 -/* Binary compatibility with drivers that access pm_vars */ -#define PM_VARS_SUPPORT 1 +#include +#include + +//****************************************************************************** +// 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, + + /* 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, + IOPMPowerStateIndex powerState, + IOPMPowerChangeFlags * changeFlags, + IOPMRequestTag requestTag ); + +typedef void +(*IOPMActionPowerChangeDone)( + void * target, + IOService * service, + IOPMActions * actions, + IOPMPowerStateIndex powerState, + IOPMPowerChangeFlags changeFlags, + IOPMRequestTag requestTag ); + +typedef void +(*IOPMActionPowerChangeOverride)( + void * target, + IOService * service, + IOPMActions * actions, + IOPMPowerStateIndex * powerState, + IOPMPowerChangeFlags * changeFlags, + IOPMRequestTag requestTag ); + +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; + uint32_t parameter; + IOPMActionPowerChangeStart actionPowerChangeStart; + IOPMActionPowerChangeDone actionPowerChangeDone; + IOPMActionPowerChangeOverride actionPowerChangeOverride; + IOPMActionActivityTickle actionActivityTickle; + IOPMActionUpdatePowerClient actionUpdatePowerClient; +}; + +// IOPMActions parameter flags +enum { + kPMActionsFlagIsDisplayWrangler = 0x00000100, + kPMActionsFlagIsGraphicsDevice = 0x00000200, + kPMActionsFlagIsAudioDevice = 0x00000400, + kPMActionsFlagLimitPower = 0x00000800, + kPMActionsPCIBitNumberMask = 0x000000ff +}; + +//****************************************************************************** +// Internal concise representation of IOPMPowerState +struct IOPMPSEntry { + IOPMPowerFlags capabilityFlags; + IOPMPowerFlags outputPowerFlags; + IOPMPowerFlags inputPowerFlags; + uint32_t staticPower; + uint32_t settleUpTime; + uint32_t settleDownTime; + IOPMPowerStateIndex stateOrder; + IOPMPowerStateIndex stateOrderToIndex; +}; + +//****************************************************************************** +// IOServicePM +//****************************************************************************** -/*! @class IOServicePM - @abstract Power management class. -*/ class IOServicePM : public OSObject { - friend class IOService; + friend class IOService; + friend class IOPMWorkQueue; - OSDeclareDefaultStructors( IOServicePM ) + OSDeclareDefaultStructors( IOServicePM ); private: - /*! @var Owner - Points to object that called PMinit(). Used only for debugging. - */ - IOService * Owner; - - /*! @var InterestedDrivers - List of interested drivers. - */ - IOPMinformeeList * InterestedDrivers; - - /*! @var DriverTimer - How long to wait for controlling driver to acknowledge. - */ - IOReturn DriverTimer; - - /*! @var AckTimer */ - thread_call_t AckTimer; - - /*! @var SettleTimer */ - thread_call_t SettleTimer; - - /*! @var MachineState - Current power management machine state. - */ - unsigned long MachineState; - - /*! @var SettleTimeUS - Settle time after changing power state. - */ - unsigned long SettleTimeUS; - - /*! @var HeadNoteFlags - The flags field for the current change note. - */ - unsigned long HeadNoteFlags; - - /*! @var HeadNoteState - The newStateNumber field for the current change note. - */ - unsigned long HeadNoteState; - - /*! @var HeadNoteOutputFlags - The outputPowerCharacter field for the current change note. - */ - unsigned long HeadNoteOutputFlags; - - /*! @var HeadNoteDomainState - Power domain flags from parent. (only on parent change). - */ - unsigned long HeadNoteDomainState; - - /*! @var HeadNoteParent - Pointer to initiating parent. (only on parent change). - */ - IOPowerConnection * HeadNoteParent; - - /*! @var HeadNoteCapabilityFlags - The capabilityFlags field for the current change note. - */ - unsigned long HeadNoteCapabilityFlags; - - /*! @var HeadNotePendingAcks - Number of acks we are waiting for. - */ - unsigned long HeadNotePendingAcks; - - /*! @var PMLock - PM state lock. - */ - IOLock * PMLock; - - /*! @var WeAreRoot - True if our owner is the root of the power tree. - */ - bool WeAreRoot; - - /*! @var InitialChange - Initialized to true, then set to false after the initial power change. - */ - bool InitialChange; - - /*! @var NeedToBecomeUsable - Someone has called makeUsable before we had a controlling driver. - */ - bool NeedToBecomeUsable; - - /*! @var DeviceOverrides - Ignore children and driver desires if true. - */ - bool DeviceOverrides; - - /*! @var ClampOn - Domain is clamped on until the first power child is added. - */ - bool ClampOn; - - /*! @var DeviceActive - True if device was active since last idle timer expiration. - */ - bool DeviceActive; - - /*! @var DoNotPowerDown - Keeps track of any negative responses from notified apps and clients. - */ - bool DoNotPowerDown; - - /*! @var ParentsKnowState - True if all our parents know the state of their power domain. - */ - bool ParentsKnowState; - - /*! @var DeviceActiveTimestamp - Time of last device activity. - */ - AbsoluteTime DeviceActiveTimestamp; - - /*! @var ActivityLock - Used to protect activity flag. - */ - IOLock * ActivityLock; - - /*! @var IdleTimerEventSource - An idle timer event source. - */ - IOTimerEventSource * IdleTimerEventSource; - - /*! @var IdleTimerPeriod - Idle timer's period in seconds. - */ - unsigned long IdleTimerPeriod; - unsigned long IdleTimerMinPowerState; - - /*! @var DriverDesire - Power state desired by our controlling driver. - */ - unsigned long DriverDesire; - - /*! @var DeviceDesire - Power state desired by a subclassed device object. - */ - unsigned long DeviceDesire; - - /*! @var ChildrenDesire - Power state desired by all children. - */ - unsigned long ChildrenDesire; - - /*! @var DesiredPowerState - This is the power state we desire currently. - */ - unsigned long DesiredPowerState; - - /*! @var PreviousRequest - This is what our parent thinks our need is. - */ - unsigned long PreviousRequest; - - /*! @var Name - Cache result from getName(), used in logging. - */ - const char * Name; - - /*! @var Platform - Cache result from getPlatform(), used in logging and registering. - */ - IOPlatformExpert * Platform; - - /*! @var NumberOfPowerStates - Number of power states in the power array. - */ - unsigned long NumberOfPowerStates; - - /*! @var PowerStates - Power state array. - */ - IOPMPowerState * PowerStates; - - /*! @var ControllingDriver - The controlling driver. - */ - IOService * ControllingDriver; - - /*! @var AggressivenessValues - Array of aggressiveness values. - */ - unsigned long AggressivenessValue[ kMaxType + 1 ]; - - /*! @var AggressivenessValid - True for aggressiveness values that are currently valid. - */ - bool AggressivenessValid[ kMaxType + 1 ]; - - /*! @var CurrentPowerState - The ordinal of our current power state. - */ - unsigned long CurrentPowerState; - - /*! @var ParentsCurrentPowerFlags - Logical OR of power flags for each power domain parent. - */ - IOPMPowerFlags ParentsCurrentPowerFlags; - - /*! @var MaxCapability - Ordinal of highest power state we can achieve in current power domain. - */ - unsigned long MaxCapability; - - /*! @var OutputPowerCharacterFlags - Logical OR of all output power character flags in the array. - */ - IOPMPowerFlags OutputPowerCharacterFlags; - - /*! @var SerialNumber - Used to uniquely identify power management notification to apps and clients. - */ - UInt16 SerialNumber; - - /*! @var ResponseArray - OSArray which manages responses from notified apps and clients. - */ - OSArray * ResponseArray; - - /*! @var OutOfBandParameter - 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; - unsigned long TempClampPowerState; - unsigned long TempClampCount; - IOPMWorkQueue * PMWorkQueue; - IOPMRequest * PMRequest; - OSSet * InsertInterestSet; - OSSet * RemoveInterestSet; - OSArray * NotifyChildArray; - unsigned long WaitReason; - unsigned long NextMachineState; - thread_call_t DriverCallEntry; - void * DriverCallParamPtr; - IOItemCount DriverCallParamCount; - IOItemCount DriverCallParamSlots; - IOOptionBits DriverCallReason; - long ActivityTicklePowerState; - bool StrictTreeOrder; - bool DriverCallBusy; - bool ActivityTimerStopped; - bool WillAdjustPowerState; - bool WillPMStop; +// 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; + thread_call_t SettleTimer; + thread_call_t IdleTimer; + thread_call_t WatchdogTimer; + thread_call_t SpinDumpTimer; + + IOLock * WatchdogLock; + OSArray * BlockedArray; + uint64_t PendingResponseDeadline; + uint64_t WatchdogDeadline; + +// Settle time after changing power state. + uint32_t SettleTimeUS; + uint32_t 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. + unsigned long IdleTimerPeriod; + unsigned long IdleTimerMinPowerState; + unsigned long NextIdleTimerPeriod; + 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 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; + uint32_t OverrideMaxPowerState; + uint32_t DeviceUsablePowerState; + +// 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; + IOPMprot * PMVars; #endif - /*! @function serialize - Serialize IOServicePM state for debug output. - */ - virtual bool serialize( OSSerialize * s ) const; + IOPMActions PMActions; + +// 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 fWeAreRoot pwrMgt->WeAreRoot +#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 fMachineState pwrMgt->MachineState +#define fIdleTimer pwrMgt->IdleTimer +#define fWatchdogTimer pwrMgt->WatchdogTimer +#define fWatchdogDeadline pwrMgt->WatchdogDeadline +#define fWatchdogLock pwrMgt->WatchdogLock +#define fBlockedArray pwrMgt->BlockedArray +#define fPendingResponseDeadline pwrMgt->PendingResponseDeadline #define fSettleTimeUS pwrMgt->SettleTimeUS -#define fHeadNoteFlags pwrMgt->HeadNoteFlags -#define fHeadNoteState pwrMgt->HeadNoteState -#define fHeadNoteOutputFlags pwrMgt->HeadNoteOutputFlags -#define fHeadNoteDomainState pwrMgt->HeadNoteDomainState -#define fHeadNoteParent pwrMgt->HeadNoteParent -#define fHeadNoteCapabilityFlags pwrMgt->HeadNoteCapabilityFlags +#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 fInitialChange pwrMgt->InitialChange -#define fNeedToBecomeUsable pwrMgt->NeedToBecomeUsable -#define fDeviceOverrides pwrMgt->DeviceOverrides -#define fClampOn pwrMgt->ClampOn -#define fOwner pwrMgt->Owner +#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 fIdleTimerEventSource pwrMgt->IdleTimerEventSource #define fIdleTimerPeriod pwrMgt->IdleTimerPeriod #define fIdleTimerMinPowerState pwrMgt->IdleTimerMinPowerState -#define fDeviceActive pwrMgt->DeviceActive -#define fDeviceActiveTimestamp pwrMgt->DeviceActiveTimestamp -#define fDriverDesire pwrMgt->DriverDesire +#define fNextIdleTimerPeriod pwrMgt->NextIdleTimerPeriod +#define fIdleTimerStartTime pwrMgt->IdleTimerStartTime #define fDeviceDesire pwrMgt->DeviceDesire -#define fChildrenDesire pwrMgt->ChildrenDesire #define fDesiredPowerState pwrMgt->DesiredPowerState -#define fPreviousRequest pwrMgt->PreviousRequest +#define fPreviousRequestPowerFlags pwrMgt->PreviousRequestPowerFlags #define fName pwrMgt->Name -#define fPlatform pwrMgt->Platform #define fNumberOfPowerStates pwrMgt->NumberOfPowerStates +#define fHighestPowerState pwrMgt->HighestPowerState #define fPowerStates pwrMgt->PowerStates #define fControllingDriver pwrMgt->ControllingDriver -#define fAggressivenessValue pwrMgt->AggressivenessValue -#define fAggressivenessValid pwrMgt->AggressivenessValid #define fCurrentPowerState pwrMgt->CurrentPowerState -#define fParentsKnowState pwrMgt->ParentsKnowState #define fParentsCurrentPowerFlags pwrMgt->ParentsCurrentPowerFlags -#define fMaxCapability pwrMgt->MaxCapability -#define fOutputPowerCharacterFlags pwrMgt->OutputPowerCharacterFlags -#define fSerialNumber pwrMgt->SerialNumber +#define fMaxPowerState pwrMgt->MaxPowerState +#define fMergedOutputPowerFlags pwrMgt->MergedOutputPowerFlags #define fResponseArray pwrMgt->ResponseArray -#define fDoNotPowerDown pwrMgt->DoNotPowerDown +#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 fTempClampCount pwrMgt->TempClampCount -#define fPMWorkQueue pwrMgt->PMWorkQueue -#define fPMRequest pwrMgt->PMRequest -#define fWaitReason pwrMgt->WaitReason -#define fNextMachineState pwrMgt->NextMachineState -#define fDriverCallReason pwrMgt->DriverCallReason +#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 fDriverCallBusy pwrMgt->DriverCallBusy -#define fWillPMStop pwrMgt->WillPMStop -#define fActivityTickled pwrMgt->ActivityTickled +#define fDriverCallReason pwrMgt->DriverCallReason +#define fOutOfBandMessage pwrMgt->OutOfBandMessage +#define fTempClampCount pwrMgt->TempClampCount +#define fOverrideMaxPowerState pwrMgt->OverrideMaxPowerState +#define fDeviceUsablePowerState pwrMgt->DeviceUsablePowerState +#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 fStrictTreeOrder pwrMgt->StrictTreeOrder -#define fNotifyChildArray pwrMgt->NotifyChildArray -#define fWillAdjustPowerState pwrMgt->WillAdjustPowerState -#define fActivityTimerStopped pwrMgt->ActivityTimerStopped -#define fActivityTicklePowerState pwrMgt->ActivityTicklePowerState +#define fReportClientCnt pwrMgt->ReportClientCnt +#define fReportBuf pwrMgt->ReportBuf #define fPMVars pwrMgt->PMVars +#define fPMActions pwrMgt->PMActions -/*! -@defined ACK_TIMER_PERIOD -@discussion When an IOService is waiting for acknowledgement to a power change -notification from an interested driver or the controlling driver its ack timer -is ticking every tenth of a second. -(100000000 nanoseconds are one tenth of a second). -*/ -#define ACK_TIMER_PERIOD 100000000 - -#define IOPMParentInitiated 1 // this power change initiated by our parent -#define IOPMWeInitiated 2 // this power change initiated by this device -#define IOPMNotDone 4 // we couldn't make this change -#define IOPMNotInUse 8 // this list element not currently in use -#define IOPMDomainWillChange 16 // change started by PowerDomainWillChangeTo -#define IOPMDomainDidChange 32 // change started by PowerDomainDidChangeTo - -struct changeNoteItem { - unsigned long flags; - unsigned long newStateNumber; - IOPMPowerFlags outputPowerCharacter; - IOPMPowerFlags inputPowerRequirement; - IOPMPowerFlags domainState; - IOPowerConnection * parent; - IOPMPowerFlags singleParentState; - IOPMPowerFlags capabilityFlags; -}; +#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 (180) // 180 secs +#define WATCHDOG_WAKE_TIMEOUT (180) // 180 secs +#endif + +// 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 + kDriverCallInformPreChange, + kDriverCallInformPostChange, + kDriverCallSetPowerState, + kRootDomainInformPreChange }; struct DriverCallParam { - OSObject * Target; - IOReturn Result; + OSObject * Target; + IOReturn Result; }; -// values of outofbandparameter +// values of OutOfBandParameter enum { - kNotifyApps, - kNotifyPriority + kNotifyApps, + kNotifyPriority, + kNotifyCapabilityChangeApps, + kNotifyCapabilityChangePriority }; +typedef bool (*IOPMMessageFilter)( + void * target, void * object, void * arg1, void * arg2, void * arg3 ); + // used for applyToInterested -struct context { - OSArray * responseFlags; - UInt16 serialNumber; - UInt16 counter; - UInt32 maxTimeRequested; - int msgType; - IOService * us; - unsigned long stateNumber; - IOPMPowerFlags stateFlags; - const char * errorLog; +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; + const char * errorLog; + IOPMMessageFilter messageFilter; }; -//********************************************************************************* -// PM command types -//********************************************************************************* +// assertPMDriverCall() options +enum { + kIOPMDriverCallNoInactiveCheck = 1 +}; +// assertPMDriverCall() method enum { - /* Command Types */ - kIOPMRequestTypeInvalid = 0x00, - kIOPMRequestTypePMStop = 0x01, - kIOPMRequestTypeAddPowerChild1 = 0x02, - kIOPMRequestTypeAddPowerChild2 = 0x03, - kIOPMRequestTypeAddPowerChild3 = 0x04, - kIOPMRequestTypeRegisterPowerDriver = 0x05, - kIOPMRequestTypeAdjustPowerState = 0x06, - kIOPMRequestTypeMakeUsable = 0x07, - kIOPMRequestTypeTemporaryPowerClamp = 0x08, - kIOPMRequestTypePowerDomainWillChange = 0x09, - kIOPMRequestTypePowerDomainDidChange = 0x0A, - kIOPMRequestTypeChangePowerStateTo = 0x0B, - kIOPMRequestTypeChangePowerStateToPriv = 0x0C, - kIOPMRequestTypePowerOverrideOnPriv = 0x0D, - kIOPMRequestTypePowerOverrideOffPriv = 0x0E, - kIOPMRequestTypeActivityTickle = 0x0F, - /* Reply Types */ - kIOPMRequestTypeReplyStart = 0x80, - kIOPMRequestTypeAckPowerChange = 0x81, - kIOPMRequestTypeAckSetPowerState = 0x82, - kIOPMRequestTypeAllowPowerChange = 0x83, - kIOPMRequestTypeCancelPowerChange = 0x84, - kIOPMRequestTypeInterestChanged = 0x85, - kIOPMRequestTypeIdleCancel = 0x86 + kIOPMDriverCallMethodUnknown = 0, + kIOPMDriverCallMethodSetPowerState = 1, + kIOPMDriverCallMethodWillChange = 2, + kIOPMDriverCallMethodDidChange = 3, + kIOPMDriverCallMethodChangeDone = 4, + kIOPMDriverCallMethodSetAggressive = 5 }; -//********************************************************************************* -// PM Helper Classes -//********************************************************************************* +//****************************************************************************** +// PM Statistics & Diagnostics +//****************************************************************************** + +extern const OSSymbol *gIOPMStatsResponseTimedOut; +extern const OSSymbol *gIOPMStatsResponseCancel; +extern const OSSymbol *gIOPMStatsResponseSlow; +extern const OSSymbol *gIOPMStatsResponsePrompt; +extern const OSSymbol *gIOPMStatsDriverPSChangeSlow; + +//****************************************************************************** +// IOPMRequest +//****************************************************************************** class IOPMRequest : public IOCommand { - OSDeclareDefaultStructors( IOPMRequest ) + OSDeclareDefaultStructors( IOPMRequest ); protected: - IOOptionBits fType; // request type - IOService * fTarget; // request target - IOPMRequest * fParent; // parent request - IOItemCount fChildCount; // wait if non-zero + IOService * fTarget; // request target + IOPMRequest * fRequestNext; // the next request in the chain + IOPMRequest * fRequestRoot; // the root request in the call tree + IOItemCount fWorkWaitCount;// execution blocked if non-zero + IOItemCount fFreeWaitCount;// completion blocked if non-zero + uint32_t fRequestType; // request type + bool fIsQuiesceBlocker; + + IOPMCompletionAction fCompletionAction; + void * fCompletionTarget; + void * fCompletionParam; public: - void * fArg0; - void * fArg1; - void * fArg2; - - inline bool hasChildRequest( void ) const - { - return (fChildCount != 0); - } - - inline bool hasParentRequest( void ) const - { - return (fParent != 0); - } - - inline void setParentRequest( IOPMRequest * parent ) - { - if (!fParent) - { - fParent = parent; - fParent->fChildCount++; - } - } - - inline IOOptionBits getType( void ) const - { - return fType; - } - - inline bool isReply( void ) const - { - return (fType > kIOPMRequestTypeReplyStart); - } - - inline IOService * getTarget( void ) const - { - return fTarget; - } - - static IOPMRequest *create( void ); - - void reset( void ); - - bool init( IOService * owner, IOOptionBits type ); + uint32_t fRequestTag; + 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 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; + } + + 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 ) + OSDeclareDefaultStructors( IOPMRequestQueue ); public: - typedef bool (*Action)( IOService *, IOPMRequest *, IOPMRequestQueue * ); + typedef bool (*Action)( IOService *, IOPMRequest *, IOPMRequestQueue * ); protected: - queue_head_t fQueue; - IOLock * fLock; + queue_head_t fQueue; + IOLock * fLock; + + enum { kMaxDequeueCount = 256 }; - virtual bool checkForWork( void ); - virtual void free( void ); - virtual bool init( IOService * inOwner, Action inAction ); + 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( IOPMRequest * request ); - void queuePMRequestChain( IOPMRequest ** requests, IOItemCount count ); - void signalWorkAvailable( void ); + static IOPMRequestQueue * create( IOService * inOwner, Action inAction ); + void queuePMRequest( IOPMRequest * request ); + void queuePMRequestChain( IOPMRequest ** requests, IOItemCount count ); }; +//****************************************************************************** +// IOPMWorkQueue +//****************************************************************************** + +#define WORK_QUEUE_STATS 1 + class IOPMWorkQueue : public IOEventSource { - OSDeclareDefaultStructors( IOPMWorkQueue ) + 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 *, IOPMWorkQueue * ); + typedef bool (*Action)( IOService *, IOPMRequest *, IOPMCompletionQueue * ); protected: - queue_head_t fWorkQueue; - Action fWorkAction; - Action fRetireAction; + queue_head_t fQueue; - virtual bool checkForWork( void ); - virtual bool init( IOService * inOwner, Action work, Action retire ); + virtual bool checkForWork( void ) APPLE_KEXT_OVERRIDE; + virtual bool init( IOService * inOwner, Action inAction ); public: - static IOPMWorkQueue * create( IOService * inOwner, Action work, Action retire ); - void queuePMRequest( IOPMRequest * request ); + static IOPMCompletionQueue * create( IOService * inOwner, Action inAction ); + bool queuePMRequest( IOPMRequest * request ); }; #endif /* !_IOKIT_IOSERVICEPMPRIVATE_H */