]> git.saurik.com Git - apple/xnu.git/blobdiff - iokit/Kernel/IOServicePMPrivate.h
xnu-4570.71.2.tar.gz
[apple/xnu.git] / iokit / Kernel / IOServicePMPrivate.h
index 658730e05f47c9e95b21fd3eb2ba2c95c2d6a2b8..0dbc58aca37219afad96fb45dc075b9415075635 100644 (file)
 #ifndef _IOKIT_IOSERVICEPMPRIVATE_H
 #define _IOKIT_IOSERVICEPMPRIVATE_H
 
-/* Binary compatibility with drivers that access pm_vars */
-#define PM_VARS_SUPPORT     1
+#include <IOKit/IOCommand.h>
+#include <IOKit/IOEventSource.h>
+
+//******************************************************************************
+// 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 IOPMWorkQueue;
 
     OSDeclareDefaultStructors( IOServicePM )
 
 private:
-    /*! @var Owner
-        Points to object that called PMinit().  Used only for debugging.
-    */
+    // Link IOServicePM objects on IOPMWorkQueue.
+    queue_chain_t           WorkChain;
+
+    // Queue of IOPMRequest objects.
+    queue_head_t            RequestHead;
+
+    // IOService creator and owner.
     IOService *             Owner;
 
-    /*! @var InterestedDrivers
-        List of interested drivers.
-    */
+    // List of interested drivers (protected by PMLock).
     IOPMinformeeList *      InterestedDrivers;
 
-    /*! @var DriverTimer
-        How long to wait for controlling driver to acknowledge.
-    */
+    // How long to wait for controlling driver to acknowledge.
     IOReturn                DriverTimer;
 
-    /*! @var AckTimer */
-    thread_call_t           AckTimer;
+    // Current power management machine state.
+    uint32_t                MachineState;
 
-    /*! @var SettleTimer */
+    thread_call_t           AckTimer;
     thread_call_t           SettleTimer;
+    thread_call_t           IdleTimer;
+    thread_call_t           WatchdogTimer;
+    thread_call_t           SpinDumpTimer;
+
+    // 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;
 
-    /*! @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.
-    */
+    // 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;
 
-    /*! @var ActivityLock
-        Used to protect activity flag.
-    */
+    // Used to protect activity flag.
     IOLock *                ActivityLock;
 
-    /*! @var IdleTimerEventSource
-        An idle timer event source.
-    */
-    IOTimerEventSource *    IdleTimerEventSource;
-
-    /*! @var IdleTimerPeriod
-        Idle timer's period in seconds.
-    */
+    // 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;
 
-    /*! @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.
-       */
+    // 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;
+    // 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;
-    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;
+    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 fSpinDumpTimer              pwrMgt->SpinDumpTimer
 #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
+
+#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))
 
-/*!
-@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.
+#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
-
-#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 ACK_TIMER_PERIOD            100000000
+
+#if defined(__i386__) || defined(__x86_64__)
+#define WATCHDOG_TIMER_PERIOD       (300)   // 300 secs
+#else
+#define WATCHDOG_TIMER_PERIOD       (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
+    kDriverCallSetPowerState,
+    kRootDomainInformPreChange
 };
 
 struct DriverCallParam {
@@ -415,116 +511,150 @@ struct DriverCallParam {
     IOReturn    Result;
 };
 
-// values of outofbandparameter
+// values of OutOfBandParameter
 enum {
     kNotifyApps,
-    kNotifyPriority
+    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;
+    IOService *             us;
+    IOPMPowerStateIndex     stateNumber;
+    IOPMPowerFlags          stateFlags;
+    IOPMPowerChangeFlags    changeFlags;
+    const char *            errorLog;
+    IOPMMessageFilter       messageFilter;
 };
 
-//*********************************************************************************
-// PM command types
-//*********************************************************************************
-
+// assertPMDriverCall() options
 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
+    kIOPMADC_NoInactiveCheck = 1
 };
 
-//*********************************************************************************
-// 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 )
 
 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;
+    uint32_t             fRequestTag;
+    void *               fArg0;
+    void *               fArg1;
+    void *               fArg2;
 
-    inline bool         hasChildRequest( void ) const
+    inline bool          isWorkBlocked( void ) const
     {
-        return (fChildCount != 0);
+        return (fWorkWaitCount != 0);
     }
 
-    inline bool         hasParentRequest( void ) const
+    inline bool          isFreeBlocked( void ) const
     {
-        return (fParent != 0);
+        return (fFreeWaitCount != 0);
     }
 
-    inline void         setParentRequest( IOPMRequest * parent )
+    inline IOPMRequest * getNextRequest( void ) const
     {
-        if (!fParent)
-        {
-            fParent = parent;
-            fParent->fChildCount++;
-        }
+        return fRequestNext;
     }
 
-    inline IOOptionBits getType( void ) const
+    inline IOPMRequest * getRootRequest( void ) const
     {
-        return fType;
+        if (fRequestRoot) return fRequestRoot;
+#if NOT_READY
+        if (fCompletionAction) return (IOPMRequest *) this;
+#endif
+        return 0;
     }
 
-    inline bool         isReply( void ) const
+    inline uint32_t      getType( void ) const
     {
-        return (fType > kIOPMRequestTypeReplyStart);
+        return fRequestType;
     }
 
-    inline IOService *  getTarget( void ) const
+    inline bool          isReplyType( void ) const
+    {
+        return (fRequestType > kIOPMRequestTypeReplyStart);
+    }
+
+    inline IOService *   getTarget( void ) const
     {
         return fTarget;
     }
 
-    static IOPMRequest *create( void );
+    inline bool          isQuiesceBlocker( void ) const
+    {
+        return fIsQuiesceBlocker;
+    }
 
-    void    reset( void );
+    inline bool          isQuiesceType( void ) const
+    {
+        return ((kIOPMRequestTypeQuiescePowerTree == fRequestType) &&
+                (fCompletionAction != 0) && (fCompletionTarget != 0));
+    }
 
-    bool    init( IOService * owner, IOOptionBits type );
+    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 )
@@ -536,17 +666,24 @@ protected:
     queue_head_t    fQueue;
     IOLock *        fLock;
 
-    virtual bool checkForWork( void );
-    virtual void free( void );
+    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( IOPMRequest * request );
     void    queuePMRequestChain( IOPMRequest ** requests, IOItemCount count );
-    void    signalWorkAvailable( void );
 };
 
+//******************************************************************************
+// IOPMWorkQueue
+//******************************************************************************
+
+#define WORK_QUEUE_STATS    1
+
 class IOPMWorkQueue : public IOEventSource
 {
     OSDeclareDefaultStructors( IOPMWorkQueue )
@@ -554,17 +691,57 @@ class IOPMWorkQueue : public IOEventSource
 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          fWorkAction;
-    Action          fRetireAction;
+    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 );
+};
 
-    virtual bool checkForWork( void );
-    virtual bool init( IOService * inOwner, Action work, Action retire );
+//******************************************************************************
+// 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 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 */