1/*
2 * Copyright (c) 2007 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29#ifndef _IOKIT_IOSERVICEPMPRIVATE_H
30#define _IOKIT_IOSERVICEPMPRIVATE_H
31
32/* Binary compatibility with drivers that access pm_vars */
33#define PM_VARS_SUPPORT     1
34
35/*! @class IOServicePM
36    @abstract Power management class.
37*/
38class IOServicePM : public OSObject
39{
40    friend class IOService;
41
42    OSDeclareDefaultStructors( IOServicePM )
43
44private:
45    /*! @var Owner
46        Points to object that called PMinit().  Used only for debugging.
47    */
48    IOService *             Owner;
49
50    /*! @var InterestedDrivers
51        List of interested drivers.
52    */
53    IOPMinformeeList *      InterestedDrivers;
54
55    /*! @var DriverTimer
56        How long to wait for controlling driver to acknowledge.
57    */
58    IOReturn                DriverTimer;
59
60    /*! @var AckTimer */
61    thread_call_t           AckTimer;
62
63    /*! @var SettleTimer */
64    thread_call_t           SettleTimer;
65
66    /*! @var MachineState
67        Current power management machine state.
68    */
69    unsigned long           MachineState;
70
71    /*! @var SettleTimeUS
72        Settle time after changing power state.
73    */
74    unsigned long           SettleTimeUS;
75
76    /*! @var HeadNoteFlags
77        The flags field for the current change note.
78    */
79    unsigned long           HeadNoteFlags;
80
81    /*! @var HeadNoteState
82        The newStateNumber field for the current change note.
83    */
84    unsigned long           HeadNoteState;
85
86    /*! @var HeadNoteOutputFlags
87        The outputPowerCharacter field for the current change note.
88    */
89    unsigned long           HeadNoteOutputFlags;
90
91    /*! @var HeadNoteDomainState
92        Power domain flags from parent. (only on parent change).
93    */
94    unsigned long           HeadNoteDomainState;
95
96    /*! @var HeadNoteParent
97        Pointer to initiating parent. (only on parent change).
98    */
99    IOPowerConnection *     HeadNoteParent;
100
101    /*! @var HeadNoteCapabilityFlags
102        The capabilityFlags field for the current change note.
103    */
104    unsigned long           HeadNoteCapabilityFlags;
105
106    /*! @var HeadNotePendingAcks
107        Number of acks we are waiting for.
108    */
109    unsigned long           HeadNotePendingAcks;
110
111    /*! @var PMLock
112        PM state lock.
113    */
114    IOLock	*               PMLock;
115
116    /*! @var WeAreRoot
117        True if our owner is the root of the power tree.
118    */
119    bool                    WeAreRoot;
120
121    /*! @var InitialChange
122        Initialized to true, then set to false after the initial power change.
123    */
124    bool                    InitialChange;
125
126    /*! @var NeedToBecomeUsable
127        Someone has called makeUsable before we had a controlling driver.
128    */
129    bool                    NeedToBecomeUsable;
130
131    /*! @var DeviceOverrides
132        Ignore children and driver desires if true.
133    */
134    bool                    DeviceOverrides;
135
136    /*! @var ClampOn
137        Domain is clamped on until the first power child is added.
138    */
139    bool                    ClampOn;
140
141    /*! @var DeviceActive
142        True if device was active since last idle timer expiration.
143    */
144    bool                    DeviceActive;
145
146    /*! @var DoNotPowerDown
147        Keeps track of any negative responses from notified apps and clients.
148    */
149    bool					DoNotPowerDown;
150
151    /*! @var ParentsKnowState
152        True if all our parents know the state of their power domain.
153    */
154    bool					ParentsKnowState;
155
156    /*! @var DeviceActiveTimestamp
157        Time of last device activity.
158    */
159    AbsoluteTime            DeviceActiveTimestamp;
160
161    /*! @var ActivityLock
162        Used to protect activity flag.
163    */
164    IOLock *                ActivityLock;
165
166    /*! @var IdleTimerEventSource
167        An idle timer event source.
168    */
169    IOTimerEventSource *    IdleTimerEventSource;
170
171    /*! @var IdleTimerPeriod
172        Idle timer's period in seconds.
173    */
174    unsigned long           IdleTimerPeriod;
175    unsigned long           IdleTimerMinPowerState;
176
177    /*! @var DriverDesire
178        Power state desired by our controlling driver.
179    */
180    unsigned long           DriverDesire;
181
182    /*! @var DeviceDesire
183        Power state desired by a subclassed device object.
184    */
185    unsigned long           DeviceDesire;
186
187    /*! @var ChildrenDesire
188        Power state desired by all children.
189    */
190    unsigned long           ChildrenDesire;
191
192    /*! @var DesiredPowerState
193        This is the power state we desire currently.
194    */
195    unsigned long           DesiredPowerState;
196
197    /*! @var PreviousRequest
198        This is what our parent thinks our need is.
199    */
200    unsigned long           PreviousRequest;
201
202	/*! @var Name
203		Cache result from getName(), used in logging.
204	*/
205    const char *            Name;
206
207    /*! @var Platform
208        Cache result from getPlatform(), used in logging and registering.
209    */
210    IOPlatformExpert *      Platform;
211
212    /*! @var NumberOfPowerStates
213        Number of power states in the power array.
214    */
215    unsigned long           NumberOfPowerStates;
216
217    /*! @var PowerStates
218        Power state array.
219    */
220    IOPMPowerState *		PowerStates;
221
222    /*! @var ControllingDriver
223        The controlling driver.
224    */
225    IOService *				ControllingDriver;
226
227    /*! @var AggressivenessValues
228        Array of aggressiveness values.
229    */
230    unsigned long			AggressivenessValue[ kMaxType + 1 ];
231
232    /*! @var AggressivenessValid
233        True for aggressiveness values that are currently valid.
234    */
235    bool					AggressivenessValid[ kMaxType + 1 ];
236
237    /*! @var CurrentPowerState
238        The ordinal of our current power state.
239    */
240    unsigned long			CurrentPowerState;
241
242    /*! @var ParentsCurrentPowerFlags
243        Logical OR of power flags for each power domain parent.
244    */
245    IOPMPowerFlags			ParentsCurrentPowerFlags;
246
247    /*! @var MaxCapability
248        Ordinal of highest power state we can achieve in current power domain.
249    */
250    unsigned long			MaxCapability;
251
252    /*! @var OutputPowerCharacterFlags
253        Logical OR of all output power character flags in the array.
254    */
255    IOPMPowerFlags			OutputPowerCharacterFlags;
256
257    /*! @var SerialNumber
258        Used to uniquely identify power management notification to apps and clients.
259    */
260    UInt16					SerialNumber;
261
262    /*! @var ResponseArray
263        OSArray which manages responses from notified apps and clients.
264    */
265    OSArray *				ResponseArray;
266
267    /*! @var OutOfBandParameter
268        Used to communicate desired function to tellClientsWithResponse().
269        This is used because it avoids changing the signatures of the affected virtual methods.
270    */
271    int						OutOfBandParameter;
272
273    AbsoluteTime            DriverCallStartTime;
274    IOPMPowerFlags          CurrentCapabilityFlags;
275    unsigned long           CurrentPowerConsumption;
276    unsigned long           TempClampPowerState;
277    unsigned long           TempClampCount;
278    IOPMWorkQueue *			PMWorkQueue;
279    IOPMRequest *			PMRequest;
280    OSSet *					InsertInterestSet;
281    OSSet *					RemoveInterestSet;
282    OSArray *				NotifyChildArray;
283    unsigned long			WaitReason;
284    unsigned long			NextMachineState;
285    thread_call_t			DriverCallEntry;
286    void *					DriverCallParamPtr;
287    IOItemCount				DriverCallParamCount;
288    IOItemCount				DriverCallParamSlots;
289    IOOptionBits			DriverCallReason;
290    long                    ActivityTicklePowerState;
291    bool					StrictTreeOrder;
292    bool					DriverCallBusy;
293    bool					ActivityTimerStopped;
294    bool					WillAdjustPowerState;
295    bool					WillPMStop;
296
297#if PM_VARS_SUPPORT
298    IOPMprot *				PMVars;
299#endif
300
301    /*! @function serialize
302        Serialize IOServicePM state for debug output.
303    */
304    virtual bool serialize( OSSerialize * s ) const;
305};
306
307#define fWeAreRoot                  pwrMgt->WeAreRoot
308#define fInterestedDrivers          pwrMgt->InterestedDrivers
309#define fDriverTimer                pwrMgt->DriverTimer
310#define fAckTimer                   pwrMgt->AckTimer
311#define fSettleTimer                pwrMgt->SettleTimer
312#define fMachineState               pwrMgt->MachineState
313#define fSettleTimeUS               pwrMgt->SettleTimeUS
314#define fHeadNoteFlags              pwrMgt->HeadNoteFlags
315#define fHeadNoteState              pwrMgt->HeadNoteState
316#define fHeadNoteOutputFlags        pwrMgt->HeadNoteOutputFlags
317#define fHeadNoteDomainState        pwrMgt->HeadNoteDomainState
318#define fHeadNoteParent             pwrMgt->HeadNoteParent
319#define fHeadNoteCapabilityFlags    pwrMgt->HeadNoteCapabilityFlags
320#define fHeadNotePendingAcks        pwrMgt->HeadNotePendingAcks
321#define fPMLock                     pwrMgt->PMLock
322#define fInitialChange              pwrMgt->InitialChange
323#define fNeedToBecomeUsable         pwrMgt->NeedToBecomeUsable
324#define fDeviceOverrides            pwrMgt->DeviceOverrides
325#define fClampOn                    pwrMgt->ClampOn
326#define fOwner                      pwrMgt->Owner
327#define fActivityLock               pwrMgt->ActivityLock
328#define fIdleTimerEventSource       pwrMgt->IdleTimerEventSource
329#define fIdleTimerPeriod            pwrMgt->IdleTimerPeriod
330#define fIdleTimerMinPowerState     pwrMgt->IdleTimerMinPowerState
331#define fDeviceActive               pwrMgt->DeviceActive
332#define fDeviceActiveTimestamp      pwrMgt->DeviceActiveTimestamp
333#define fDriverDesire               pwrMgt->DriverDesire
334#define fDeviceDesire               pwrMgt->DeviceDesire
335#define fChildrenDesire             pwrMgt->ChildrenDesire
336#define fDesiredPowerState          pwrMgt->DesiredPowerState
337#define fPreviousRequest            pwrMgt->PreviousRequest
338#define fName                       pwrMgt->Name
339#define fPlatform                   pwrMgt->Platform
340#define fNumberOfPowerStates        pwrMgt->NumberOfPowerStates
341#define fPowerStates                pwrMgt->PowerStates
342#define fControllingDriver          pwrMgt->ControllingDriver
343#define fAggressivenessValue        pwrMgt->AggressivenessValue
344#define fAggressivenessValid        pwrMgt->AggressivenessValid
345#define fCurrentPowerState          pwrMgt->CurrentPowerState
346#define fParentsKnowState           pwrMgt->ParentsKnowState
347#define fParentsCurrentPowerFlags   pwrMgt->ParentsCurrentPowerFlags
348#define fMaxCapability              pwrMgt->MaxCapability
349#define fOutputPowerCharacterFlags  pwrMgt->OutputPowerCharacterFlags
350#define fSerialNumber               pwrMgt->SerialNumber
351#define fResponseArray              pwrMgt->ResponseArray
352#define fDoNotPowerDown             pwrMgt->DoNotPowerDown
353#define fOutOfBandParameter         pwrMgt->OutOfBandParameter
354#define fDriverCallStartTime        pwrMgt->DriverCallStartTime
355#define fCurrentCapabilityFlags     pwrMgt->CurrentCapabilityFlags
356#define fCurrentPowerConsumption    pwrMgt->CurrentPowerConsumption
357#define fTempClampPowerState        pwrMgt->TempClampPowerState
358#define fTempClampCount             pwrMgt->TempClampCount
359#define fPMWorkQueue                pwrMgt->PMWorkQueue
360#define fPMRequest                  pwrMgt->PMRequest
361#define fWaitReason                 pwrMgt->WaitReason
362#define fNextMachineState           pwrMgt->NextMachineState
363#define fDriverCallReason           pwrMgt->DriverCallReason
364#define fDriverCallEntry            pwrMgt->DriverCallEntry
365#define fDriverCallParamPtr         pwrMgt->DriverCallParamPtr
366#define fDriverCallParamCount       pwrMgt->DriverCallParamCount
367#define fDriverCallParamSlots       pwrMgt->DriverCallParamSlots
368#define fDriverCallBusy             pwrMgt->DriverCallBusy
369#define fWillPMStop                 pwrMgt->WillPMStop
370#define fActivityTickled            pwrMgt->ActivityTickled
371#define fInsertInterestSet          pwrMgt->InsertInterestSet
372#define fRemoveInterestSet          pwrMgt->RemoveInterestSet
373#define fStrictTreeOrder            pwrMgt->StrictTreeOrder
374#define fNotifyChildArray           pwrMgt->NotifyChildArray
375#define fWillAdjustPowerState       pwrMgt->WillAdjustPowerState
376#define fActivityTimerStopped       pwrMgt->ActivityTimerStopped
377#define fActivityTicklePowerState   pwrMgt->ActivityTicklePowerState
378#define fPMVars                     pwrMgt->PMVars
379
380/*!
381@defined ACK_TIMER_PERIOD
382@discussion When an IOService is waiting for acknowledgement to a power change
383notification from an interested driver or the controlling driver its ack timer
384is ticking every tenth of a second.
385(100000000 nanoseconds are one tenth of a second).
386*/
387#define ACK_TIMER_PERIOD 100000000
388
389#define IOPMParentInitiated     1   // this power change initiated by our  parent
390#define IOPMWeInitiated         2   // this power change initiated by this device
391#define IOPMNotDone             4   // we couldn't make this change
392#define IOPMNotInUse            8   // this list element not currently in use
393#define IOPMDomainWillChange    16  // change started by PowerDomainWillChangeTo
394#define IOPMDomainDidChange     32  // change started by PowerDomainDidChangeTo
395
396struct changeNoteItem {
397    unsigned long       flags;
398    unsigned long       newStateNumber;
399    IOPMPowerFlags      outputPowerCharacter;
400    IOPMPowerFlags      inputPowerRequirement;
401    IOPMPowerFlags      domainState;
402    IOPowerConnection * parent;
403    IOPMPowerFlags      singleParentState;
404    IOPMPowerFlags      capabilityFlags;
405};
406
407enum {
408    kDriverCallInformPreChange,
409    kDriverCallInformPostChange,
410    kDriverCallSetPowerState
411};
412
413struct DriverCallParam {
414    OSObject *  Target;
415    IOReturn    Result;
416};
417
418// values of outofbandparameter
419enum {
420    kNotifyApps,
421    kNotifyPriority
422};
423
424// used for applyToInterested
425struct context {
426    OSArray *      responseFlags;
427    UInt16         serialNumber;
428    UInt16         counter;
429    UInt32         maxTimeRequested;
430    int            msgType;
431    IOService *    us;
432    unsigned long  stateNumber;
433    IOPMPowerFlags stateFlags;
434    const char * errorLog;
435};
436
437//*********************************************************************************
438// PM command types
439//*********************************************************************************
440
441enum {
442    /* Command Types */
443    kIOPMRequestTypeInvalid                = 0x00,
444    kIOPMRequestTypePMStop                 = 0x01,
445    kIOPMRequestTypeAddPowerChild1         = 0x02,
446    kIOPMRequestTypeAddPowerChild2         = 0x03,
447    kIOPMRequestTypeAddPowerChild3         = 0x04,
448    kIOPMRequestTypeRegisterPowerDriver    = 0x05,
449    kIOPMRequestTypeAdjustPowerState       = 0x06,
450    kIOPMRequestTypeMakeUsable             = 0x07,
451    kIOPMRequestTypeTemporaryPowerClamp    = 0x08,
452    kIOPMRequestTypePowerDomainWillChange  = 0x09,
453    kIOPMRequestTypePowerDomainDidChange   = 0x0A,
454    kIOPMRequestTypeChangePowerStateTo     = 0x0B,
455    kIOPMRequestTypeChangePowerStateToPriv = 0x0C,
456    kIOPMRequestTypePowerOverrideOnPriv    = 0x0D,
457    kIOPMRequestTypePowerOverrideOffPriv   = 0x0E,
458    kIOPMRequestTypeActivityTickle         = 0x0F,
459    /* Reply Types */
460    kIOPMRequestTypeReplyStart             = 0x80,
461    kIOPMRequestTypeAckPowerChange         = 0x81,
462    kIOPMRequestTypeAckSetPowerState       = 0x82,
463    kIOPMRequestTypeAllowPowerChange       = 0x83,
464    kIOPMRequestTypeCancelPowerChange      = 0x84,
465    kIOPMRequestTypeInterestChanged        = 0x85,
466    kIOPMRequestTypeIdleCancel             = 0x86
467};
468
469//*********************************************************************************
470// PM Helper Classes
471//*********************************************************************************
472
473class IOPMRequest : public IOCommand
474{
475    OSDeclareDefaultStructors( IOPMRequest )
476
477protected:
478    IOOptionBits        fType;          // request type
479    IOService *         fTarget;        // request target
480    IOPMRequest *       fParent;        // parent request
481    IOItemCount         fChildCount;    // wait if non-zero
482
483public:
484    void *              fArg0;
485    void *              fArg1;
486    void *              fArg2;
487
488    inline bool         hasChildRequest( void ) const
489    {
490        return (fChildCount != 0);
491    }
492
493    inline bool         hasParentRequest( void ) const
494    {
495        return (fParent != 0);
496    }
497
498    inline void         setParentRequest( IOPMRequest * parent )
499    {
500        if (!fParent)
501        {
502            fParent = parent;
503            fParent->fChildCount++;
504        }
505    }
506
507    inline IOOptionBits getType( void ) const
508    {
509        return fType;
510    }
511
512    inline bool         isReply( void ) const
513    {
514        return (fType > kIOPMRequestTypeReplyStart);
515    }
516
517    inline IOService *  getTarget( void ) const
518    {
519        return fTarget;
520    }
521
522    static IOPMRequest *create( void );
523
524    void    reset( void );
525
526    bool    init( IOService * owner, IOOptionBits type );
527};
528
529class IOPMRequestQueue : public IOEventSource
530{
531    OSDeclareDefaultStructors( IOPMRequestQueue )
532
533public:
534    typedef bool (*Action)( IOService *, IOPMRequest *, IOPMRequestQueue * );
535
536protected:
537    queue_head_t    fQueue;
538    IOLock *        fLock;
539
540    virtual bool checkForWork( void );
541    virtual void free( void );
542    virtual bool init( IOService * inOwner, Action inAction );
543
544public:
545    static  IOPMRequestQueue * create( IOService * inOwner, Action inAction );
546    void    queuePMRequest( IOPMRequest * request );
547    void    queuePMRequestChain( IOPMRequest ** requests, IOItemCount count );
548    void    signalWorkAvailable( void );
549};
550
551class IOPMWorkQueue : public IOEventSource
552{
553    OSDeclareDefaultStructors( IOPMWorkQueue )
554
555public:
556    typedef bool (*Action)( IOService *, IOPMRequest *, IOPMWorkQueue * );
557
558protected:
559    queue_head_t    fWorkQueue;
560    Action          fWorkAction;
561    Action          fRetireAction;
562
563    virtual bool checkForWork( void );
564    virtual bool init( IOService * inOwner, Action work, Action retire );
565
566public:
567    static IOPMWorkQueue * create( IOService * inOwner, Action work, Action retire );
568    void   queuePMRequest( IOPMRequest * request );
569};
570
571#endif /* !_IOKIT_IOSERVICEPMPRIVATE_H */
572