This is xnu-11215.1.10. See this file in:
/*
* 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>
#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;
// 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;
// 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 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
// 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
};
//******************************************************************************
// 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 */