1/*
2 * Copyright (c) 1998-2006 Apple Computer, 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//#undef IOASSERT
30//#define IOASSERT    1
31
32#include <IOKit/assert.h>
33#include <IOKit/IOKitDebug.h>
34#include <IOKit/IOLib.h>
35#include <IOKit/IOMessage.h>
36#include <IOKit/IOPlatformExpert.h>
37#include <IOKit/IOService.h>
38#include <IOKit/IOEventSource.h>
39#include <IOKit/IOWorkLoop.h>
40#include <IOKit/IOCommand.h>
41#include <IOKit/IOTimeStamp.h>
42
43#include <IOKit/pwr_mgt/IOPMlog.h>
44#include <IOKit/pwr_mgt/IOPMinformee.h>
45#include <IOKit/pwr_mgt/IOPMinformeeList.h>
46#include <IOKit/pwr_mgt/IOPowerConnection.h>
47#include <IOKit/pwr_mgt/RootDomain.h>
48#include <IOKit/pwr_mgt/IOPMPrivate.h>
49
50#include <sys/proc.h>
51#include <sys/proc_internal.h>
52#include <libkern/OSDebug.h>
53
54// Required for notification instrumentation
55#include "IOServicePrivate.h"
56#include "IOServicePMPrivate.h"
57#include "IOKitKernelInternal.h"
58
59static void settle_timer_expired(thread_call_param_t, thread_call_param_t);
60static void idle_timer_expired(thread_call_param_t, thread_call_param_t);
61static void tellKernelClientApplier(OSObject * object, void * arg);
62static void tellAppClientApplier(OSObject * object, void * arg);
63
64static uint64_t computeTimeDeltaNS( const AbsoluteTime * start )
65{
66    AbsoluteTime    now;
67    uint64_t        nsec;
68
69    clock_get_uptime(&now);
70    SUB_ABSOLUTETIME(&now, start);
71    absolutetime_to_nanoseconds(now, &nsec);
72    return nsec;
73}
74
75#if PM_VARS_SUPPORT
76OSDefineMetaClassAndStructors(IOPMprot, OSObject)
77#endif
78
79// Container class for recording system power events
80OSDefineMetaClassAndStructors( PMEventDetails, OSObject );
81
82//******************************************************************************
83// Globals
84//******************************************************************************
85
86static bool                  gIOPMInitialized   = false;
87static uint32_t              gIOPMBusyCount     = 0;
88static uint32_t              gIOPMWorkCount     = 0;
89static IOWorkLoop *          gIOPMWorkLoop      = 0;
90static IOPMRequestQueue *    gIOPMRequestQueue  = 0;
91static IOPMRequestQueue *    gIOPMReplyQueue    = 0;
92static IOPMWorkQueue *       gIOPMWorkQueue     = 0;
93static IOPMCompletionQueue * gIOPMFreeQueue     = 0;
94static IOPMRequest *         gIOPMRequest       = 0;
95static IOService *           gIOPMRootNode      = 0;
96static IOPlatformExpert *    gPlatform          = 0;
97
98static const OSSymbol *      gIOPMPowerClientDevice     = 0;
99static const OSSymbol *      gIOPMPowerClientDriver     = 0;
100static const OSSymbol *      gIOPMPowerClientChildProxy = 0;
101static const OSSymbol *      gIOPMPowerClientChildren   = 0;
102
103static const OSSymbol *      gIOPMPowerClientAdvisoryTickle = 0;
104static bool                  gIOPMAdvisoryTickleEnabled = true;
105
106static uint32_t getPMRequestType( void )
107{
108    uint32_t type = kIOPMRequestTypeInvalid;
109	if (gIOPMRequest)
110        type = gIOPMRequest->getType();
111    return type;
112}
113
114//******************************************************************************
115// Macros
116//******************************************************************************
117
118#define PM_ERROR(x...)              do { kprintf(x); IOLog(x); } while (false)
119#define PM_LOG(x...)                do { kprintf(x); } while (false)
120
121#define PM_LOG1(x...)               do {  \
122                                    if (kIOLogDebugPower & gIOKitDebug) \
123                                        kprintf(x); } while (false)
124
125#define PM_LOG2(x...)               do {  \
126                                    if (kIOLogDebugPower & gIOKitDebug) \
127                                        kprintf(x); } while (false)
128
129#if 0
130#define PM_LOG3(x...)               do { kprintf(x); } while (false)
131#else
132#define PM_LOG3(x...)
133#endif
134
135#define RD_LOG(x...)                do { \
136                                    if ((kIOLogPMRootDomain & gIOKitDebug) && \
137                                        (getPMRootDomain() == this)) \
138                                        kprintf("PMRD: " x); } while (false)
139
140#define PM_ASSERT_IN_GATE(x)          \
141do {                                  \
142    assert(gIOPMWorkLoop->inGate());  \
143} while(false)
144
145#define PM_LOCK()                   IOLockLock(fPMLock)
146#define PM_UNLOCK()                 IOLockUnlock(fPMLock)
147#define PM_LOCK_SLEEP(event, dl)    IOLockSleepDeadline(fPMLock, event, dl, THREAD_UNINT)
148#define PM_LOCK_WAKEUP(event)       IOLockWakeup(fPMLock, event, false)
149
150#define ns_per_us                   1000
151#define k30Seconds                  (30*1000000)
152#define kMinAckTimeoutTicks         (10*1000000)
153#define kIOPMTardyAckSPSKey         "IOPMTardyAckSetPowerState"
154#define kIOPMTardyAckPSCKey         "IOPMTardyAckPowerStateChange"
155#define kPwrMgtKey                  "IOPowerManagement"
156
157#define OUR_PMLog(t, a, b) do {          \
158    if (gIOKitDebug & kIOLogPower)       \
159        pwrMgt->pmPrint(t, a, b);        \
160    if (gIOKitTrace & kIOTracePowerMgmt) \
161        pwrMgt->pmTrace(t, a, b);        \
162    } while(0)
163
164#define NS_TO_MS(nsec)              ((int)((nsec) / 1000000ULL))
165#define NS_TO_US(nsec)              ((int)((nsec) / 1000ULL))
166
167#if CONFIG_EMBEDDED
168#define SUPPORT_IDLE_CANCEL         1
169#endif
170
171#define kIOPMPowerStateMax          0xFFFFFFFF
172#define kInvalidTicklePowerState    (-1)
173
174#define kNoTickleCancelWindow       (60ULL * 1000ULL * 1000ULL * 1000ULL)
175
176#define IS_PM_ROOT                  (this == gIOPMRootNode)
177#define IS_ROOT_DOMAIN              (getPMRootDomain() == this)
178#define IS_POWER_DROP               (fHeadNotePowerState < fCurrentPowerState)
179#define IS_POWER_RISE               (fHeadNotePowerState > fCurrentPowerState)
180
181// log setPowerStates longer than (ns):
182#define LOG_SETPOWER_TIMES          (50ULL * 1000ULL * 1000ULL)
183// log app responses longer than (ns):
184#define LOG_APP_RESPONSE_TIMES      (100ULL * 1000ULL * 1000ULL)
185// use message tracer to log messages longer than (ns):
186#define LOG_APP_RESPONSE_MSG_TRACER (3 * 1000ULL * 1000ULL * 1000ULL)
187
188enum {
189    kReserveDomainPower = 1
190};
191
192#define MS_PUSH(n)  \
193    do { assert(kIOPM_BadMachineState == fSavedMachineState); \
194         assert(kIOPM_BadMachineState != n); \
195         fSavedMachineState = n; } while (false)
196
197#define MS_POP()    \
198    do { assert(kIOPM_BadMachineState != fSavedMachineState); \
199         fMachineState = fSavedMachineState; \
200         fSavedMachineState = kIOPM_BadMachineState; } while (false)
201
202#define PM_ACTION_0(a) \
203    do { if (fPMActions.a) { \
204         (fPMActions.a)(fPMActions.target, this, &fPMActions); } \
205         } while (false)
206
207#define PM_ACTION_2(a, x, y) \
208    do { if (fPMActions.a) { \
209         (fPMActions.a)(fPMActions.target, this, &fPMActions, x, y); } \
210         } while (false)
211
212static OSNumber * copyClientIDForNotification(
213    OSObject *object,
214    IOPMInterestContext *context);
215
216static void logClientIDForNotification(
217    OSObject *object,
218    IOPMInterestContext *context,
219    const char *logString);
220
221//*********************************************************************************
222// PM machine states
223//
224// Check kgmacros after modifying machine states.
225//*********************************************************************************
226
227enum {
228    kIOPM_Finished                                      = 0,
229
230    kIOPM_OurChangeTellClientsPowerDown                 = 1,
231    kIOPM_OurChangeTellPriorityClientsPowerDown         = 2,
232    kIOPM_OurChangeNotifyInterestedDriversWillChange    = 3,
233    kIOPM_OurChangeSetPowerState                        = 4,
234    kIOPM_OurChangeWaitForPowerSettle                   = 5,
235    kIOPM_OurChangeNotifyInterestedDriversDidChange     = 6,
236    kIOPM_OurChangeTellCapabilityDidChange              = 7,
237    kIOPM_OurChangeFinish                               = 8,
238
239    kIOPM_ParentChangeTellPriorityClientsPowerDown      = 10,
240    kIOPM_ParentChangeNotifyInterestedDriversWillChange = 11,
241    kIOPM_ParentChangeSetPowerState                     = 12,
242    kIOPM_ParentChangeWaitForPowerSettle                = 13,
243    kIOPM_ParentChangeNotifyInterestedDriversDidChange  = 14,
244    kIOPM_ParentChangeTellCapabilityDidChange           = 15,
245    kIOPM_ParentChangeAcknowledgePowerChange            = 16,
246
247    kIOPM_NotifyChildrenStart                           = 17,
248    kIOPM_NotifyChildrenOrdered                         = 18,
249    kIOPM_NotifyChildrenDelayed                         = 19,
250    kIOPM_SyncTellClientsPowerDown                      = 20,
251    kIOPM_SyncTellPriorityClientsPowerDown              = 21,
252    kIOPM_SyncNotifyWillChange                          = 22,
253    kIOPM_SyncNotifyDidChange                           = 23,
254    kIOPM_SyncTellCapabilityDidChange                   = 24,
255    kIOPM_SyncFinish                                    = 25,
256    kIOPM_TellCapabilityChangeDone                      = 26,
257    kIOPM_DriverThreadCallDone                          = 27,
258
259    kIOPM_BadMachineState                               = 0xFFFFFFFF
260};
261
262
263 /*
264 Power Management defines a few roles that drivers can play in their own,
265 and other drivers', power management. We briefly define those here.
266
267 Many drivers implement their policy maker and power controller within the same
268 IOService object, but that is not required.
269
270== Policy Maker ==
271 * Virtual IOService PM methods a "policy maker" may implement
272    * maxCapabilityForDomainState()
273    * initialPowerStateForDomainState()
274    * powerStateForDomainState()
275
276 * Virtual IOService PM methods a "policy maker" may CALL
277    * PMinit()
278
279== Power Controller ==
280 * Virtual IOService PM methods a "power controller" may implement
281    * setPowerState()
282
283 * Virtual IOService PM methods a "power controller" may CALL
284    * joinPMtree()
285    * registerPowerDriver()
286
287=======================
288 There are two different kinds of power state changes.
289    * One is initiated by a subclassed device object which has either decided
290      to change power state, or its controlling driver has suggested it, or
291      some other driver wants to use the idle device and has asked it to become
292      usable.
293    * The second kind of power state change is initiated by the power domain
294      parent.
295 The two are handled through different code paths.
296
297 We maintain a queue of "change notifications," or change notes.
298    * Usually the queue is empty.
299    * When it isn't, usually there is one change note in it
300    * It's possible to have more than one power state change pending at one
301        time, so a queue is implemented.
302 Example:
303    * The subclass device decides it's idle and initiates a change to a lower
304        power state. This causes interested parties to be notified, but they
305        don't all acknowledge right away.  This causes the change note to sit
306        in the queue until all the acks are received.  During this time, the
307        device decides it isn't idle anymore and wants to raise power back up
308        again.  This change can't be started, however, because the previous one
309        isn't complete yet, so the second one waits in the queue.  During this
310        time, the parent decides to lower or raise the power state of the entire
311        power domain and notifies the device, and that notification goes into
312        the queue, too, and can't be actioned until the others are.
313
314 == SelfInitiated ==
315 This is how a power change initiated by the subclass device is handled:
316    -> First, all interested parties are notified of the change via their
317       powerStateWillChangeTo method.  If they all don't acknowledge via return
318       code, then we have to wait.  If they do, or when they finally all
319       acknowledge via our acknowledgePowerChange method, then we can continue.
320    -> We call the controlling driver, instructing it to change to the new state
321    -> Then we wait for power to settle. If there is no settling-time, or after
322       it has passed,
323    -> we notify interested parties again, this time via their
324       powerStateDidChangeTo methods.
325    -> When they have all acked, we're done.
326 If we lowered power and don't need the power domain to be in its current power
327 state, we suggest to the parent that it lower the power domain state.
328
329 == PowerDomainDownInitiated ==
330How a change to a lower power domain state initiated by the parent is handled:
331    -> First, we figure out what power state we will be in when the new domain
332        state is reached.
333    -> Then all interested parties are notified that we are moving to that new
334        state.
335    -> When they have acknowledged, we call the controlling driver to assume
336        that state and we wait for power to settle.
337    -> Then we acknowledge our preparedness to our parent.  When all its
338        interested parties have acknowledged,
339    -> it lowers power and then notifies its interested parties again.
340    -> When we get this call, we notify our interested parties that the power
341        state has changed, and when they have all acknowledged, we're done.
342
343 == PowerDomainUpInitiated ==
344How a change to a higher power domain state initiated by the parent is handled:
345    -> We figure out what power state we will be in when the new domain state is
346        reached.
347    -> If it is different from our current state we acknowledge the parent.
348    -> When all the parent's interested parties have acknowledged, it raises
349        power in the domain and waits for power to settle.
350    -> Then it  notifies everyone that the new state has been reached.
351    -> When we get this call, we call the controlling driver, instructing it to
352        assume the new state, and wait for power to settle.
353    -> Then we notify our interested parties. When they all acknowledge we are
354        done.
355
356 In either of the two power domain state cases above, it is possible that we
357 will not be changing state even though the domain is.
358 Examples:
359    * A change to a lower domain state may not affect us because we are already
360        in a low enough state,
361    * We will not take advantage of a change to a higher domain state, because
362        we have no need of the higher power. In such cases, there is nothing to
363        do but acknowledge the parent.  So when the parent calls our
364        powerDomainWillChange method, and we decide that we will not be changing
365        state, we merely acknowledge the parent, via return code, and wait.
366 When the parent subsequently calls powerStateDidChange, we acknowledge again
367 via return code, and the change is complete.
368
369 == 4 Paths Through State Machine ==
370 Power state changes are processed in a state machine, and since there are four
371 varieties of power state changes, there are four major paths through the state
372 machine.
373
374 == 5. No Need To change ==
375 The fourth is nearly trivial.  In this path, the parent is changing the domain
376 state, but we are not changing the device state. The change starts when the
377 parent calls powerDomainWillChange.  All we do is acknowledge the parent. When
378 the parent calls powerStateDidChange, we acknowledge the parent again, and
379 we're done.
380
381 == 1. OurChange Down ==    XXX gvdl
382 The first is fairly simple.  It starts:
383    * when a power domain child calls requestPowerDomainState and we decide to
384        change power states to accomodate the child,
385    * or if our power-controlling driver calls changePowerStateTo,
386    * or if some other driver which is using our device calls makeUsable,
387    * or if a subclassed object calls changePowerStateToPriv.
388 These are all power changes initiated by us, not forced upon us by the parent.
389
390 -> We start by notifying interested parties.
391        -> If they all acknowledge via return code, we can go on to state
392            "msSetPowerState".
393        -> Otherwise, we start the ack timer and wait for the stragglers to
394            acknowlege by calling acknowledgePowerChange.
395            -> We move on to state "msSetPowerState" when all the
396                stragglers have acknowledged, or when the ack timer expires on
397                all those which didn't acknowledge.
398 In "msSetPowerState" we call the power-controlling driver to change the
399 power state of the hardware.
400    -> If it returns saying it has done so, we go on to state
401        "msWaitForPowerSettle".
402    -> Otherwise, we have to wait for it, so we set the ack timer and wait.
403        -> When it calls acknowledgeSetPowerState, or when the ack timer
404            expires, we go on.
405 In "msWaitForPowerSettle", we look in the power state array to see if
406 there is any settle time required when changing from our current state to the
407 new state.
408    -> If not, we go right away to "msNotifyInterestedDriversDidChange".
409    -> Otherwise, we set the settle timer and wait. When it expires, we move on.
410 In "msNotifyInterestedDriversDidChange" state, we notify all our
411 interested parties via their powerStateDidChange methods that we have finished
412 changing power state.
413    -> If they all acknowledge via return code, we move on to "msFinish".
414    -> Otherwise we set the ack timer and wait.  When they have all
415        acknowledged, or when the ack timer has expired for those that didn't,
416        we move on to "msFinish".
417 In "msFinish" we remove the used change note from the head of the queue
418 and start the next one if one exists.
419
420 == 2. Parent Change Down ==
421 Start at Stage 2 of OurChange Down    XXX gvdl
422
423 == 3. Change Up ==
424 Start at Stage 4 of OurChange Down    XXX gvdl
425
426Note all parent requested changes need to acknowledge the power has changed to the parent when done.
427 */
428
429//*********************************************************************************
430// [public] PMinit
431//
432// Initialize power management.
433//*********************************************************************************
434
435void IOService::PMinit ( void )
436{
437    if ( !initialized )
438	{
439		if ( !gIOPMInitialized )
440		{
441            gPlatform = getPlatform();
442            gIOPMWorkLoop = IOWorkLoop::workLoop();
443            if (gIOPMWorkLoop)
444            {
445                gIOPMRequestQueue = IOPMRequestQueue::create(
446                    this, OSMemberFunctionCast(IOPMRequestQueue::Action,
447                        this, &IOService::servicePMRequestQueue));
448
449                gIOPMReplyQueue = IOPMRequestQueue::create(
450                    this, OSMemberFunctionCast(IOPMRequestQueue::Action,
451                        this, &IOService::servicePMReplyQueue));
452
453                gIOPMWorkQueue = IOPMWorkQueue::create(
454                    this,
455                    OSMemberFunctionCast(IOPMWorkQueue::Action, this,
456                        &IOService::servicePMRequest),
457                    OSMemberFunctionCast(IOPMWorkQueue::Action, this,
458                        &IOService::retirePMRequest));
459
460                gIOPMFreeQueue = IOPMCompletionQueue::create(
461                    this, OSMemberFunctionCast(IOPMCompletionQueue::Action,
462                        this, &IOService::servicePMFreeQueue));
463
464                if (gIOPMWorkLoop->addEventSource(gIOPMRequestQueue) !=
465                    kIOReturnSuccess)
466                {
467                    gIOPMRequestQueue->release();
468                    gIOPMRequestQueue = 0;
469                }
470
471                if (gIOPMWorkLoop->addEventSource(gIOPMReplyQueue) !=
472                    kIOReturnSuccess)
473                {
474                    gIOPMReplyQueue->release();
475                    gIOPMReplyQueue = 0;
476                }
477
478                if (gIOPMWorkLoop->addEventSource(gIOPMWorkQueue) !=
479                    kIOReturnSuccess)
480                {
481                    gIOPMWorkQueue->release();
482                    gIOPMWorkQueue = 0;
483                }
484
485                if (gIOPMWorkLoop->addEventSource(gIOPMFreeQueue) !=
486                    kIOReturnSuccess)
487                {
488                    gIOPMFreeQueue->release();
489                    gIOPMFreeQueue = 0;
490                }
491
492                gIOPMPowerClientDevice =
493                    OSSymbol::withCStringNoCopy( "DevicePowerState" );
494
495                gIOPMPowerClientDriver =
496                    OSSymbol::withCStringNoCopy( "DriverPowerState" );
497
498                gIOPMPowerClientChildProxy =
499                    OSSymbol::withCStringNoCopy( "ChildProxyPowerState" );
500
501                gIOPMPowerClientChildren =
502                    OSSymbol::withCStringNoCopy( "ChildrenPowerState" );
503
504                gIOPMPowerClientAdvisoryTickle =
505                    OSSymbol::withCStringNoCopy( "AdvisoryTicklePowerState" );
506            }
507
508            if (gIOPMRequestQueue && gIOPMReplyQueue && gIOPMFreeQueue)
509                gIOPMInitialized = true;
510        }
511        if (!gIOPMInitialized)
512            return;
513
514        pwrMgt = new IOServicePM;
515        pwrMgt->init();
516        setProperty(kPwrMgtKey, pwrMgt);
517
518        queue_init(&pwrMgt->WorkChain);
519        queue_init(&pwrMgt->RequestHead);
520        queue_init(&pwrMgt->PMDriverCallQueue);
521
522        fOwner                      = this;
523        fPMLock                     = IOLockAlloc();
524        fInterestedDrivers          = new IOPMinformeeList;
525        fInterestedDrivers->initialize();
526        fDesiredPowerState          = 0;
527        fDeviceDesire               = 0;
528        fInitialPowerChange         = true;
529        fInitialSetPowerState       = true;
530        fPreviousRequestPowerFlags  = 0;
531        fDeviceOverrideEnabled      = false;
532        fMachineState               = kIOPM_Finished;
533        fSavedMachineState          = kIOPM_BadMachineState;
534        fIdleTimerMinPowerState     = 0;
535        fActivityLock               = IOLockAlloc();
536        fStrictTreeOrder            = false;
537        fActivityTicklePowerState   = kInvalidTicklePowerState;
538        fAdvisoryTicklePowerState   = kInvalidTicklePowerState;
539        fControllingDriver          = NULL;
540        fPowerStates                = NULL;
541        fNumberOfPowerStates        = 0;
542        fCurrentPowerState          = 0;
543        fParentsCurrentPowerFlags   = 0;
544        fMaxPowerState              = 0;
545        fName                       = getName();
546        fParentsKnowState           = false;
547        fSerialNumber               = 0;
548        fResponseArray              = NULL;
549        fNotifyClientArray          = NULL;
550        fCurrentPowerConsumption    = kIOPMUnknown;
551        fOverrideMaxPowerState      = kIOPMPowerStateMax;
552
553        if (!gIOPMRootNode && (getParentEntry(gIOPowerPlane) == getRegistryRoot()))
554        {
555            gIOPMRootNode = this;
556            fParentsKnowState = true;
557        }
558
559        fAckTimer = thread_call_allocate(
560			&IOService::ack_timer_expired, (thread_call_param_t)this);
561        fSettleTimer = thread_call_allocate(
562			&settle_timer_expired, (thread_call_param_t)this);
563        fIdleTimer = thread_call_allocate(
564            &idle_timer_expired, (thread_call_param_t)this);
565        fDriverCallEntry = thread_call_allocate(
566			(thread_call_func_t) &IOService::pmDriverCallout, this);
567        assert(fDriverCallEntry);
568
569        // Check for powerChangeDone override.
570        if (OSMemberFunctionCast(void (*)(void),
571				getResourceService(), &IOService::powerChangeDone) !=
572			  OSMemberFunctionCast(void (*)(void),
573				this, &IOService::powerChangeDone))
574        {
575            fPCDFunctionOverride = true;
576        }
577
578#if PM_VARS_SUPPORT
579        IOPMprot * prot = new IOPMprot;
580        if (prot)
581        {
582            prot->init();
583            prot->ourName = fName;
584            prot->thePlatform = gPlatform;
585            fPMVars = prot;
586            pm_vars = prot;
587		}
588#else
589        pm_vars = (void *) (uintptr_t) true;
590#endif
591
592        initialized = true;
593    }
594}
595
596//*********************************************************************************
597// [private] PMfree
598//
599// Free the data created by PMinit. Only called from IOService::free().
600//*********************************************************************************
601
602void IOService::PMfree ( void )
603{
604    initialized = false;
605    pm_vars = 0;
606
607    if ( pwrMgt )
608    {
609        assert(fMachineState == kIOPM_Finished);
610        assert(fInsertInterestSet == NULL);
611        assert(fRemoveInterestSet == NULL);
612        assert(fNotifyChildArray  == NULL);
613        assert(queue_empty(&pwrMgt->RequestHead));
614        assert(queue_empty(&fPMDriverCallQueue));
615
616        if ( fSettleTimer ) {
617            thread_call_cancel(fSettleTimer);
618            thread_call_free(fSettleTimer);
619            fSettleTimer = NULL;
620        }
621        if ( fAckTimer ) {
622            thread_call_cancel(fAckTimer);
623            thread_call_free(fAckTimer);
624            fAckTimer = NULL;
625        }
626        if ( fIdleTimer ) {
627            thread_call_cancel(fIdleTimer);
628            thread_call_free(fIdleTimer);
629            fIdleTimer = NULL;
630        }
631        if ( fDriverCallEntry ) {
632            thread_call_free(fDriverCallEntry);
633            fDriverCallEntry = NULL;
634        }
635        if ( fPMLock ) {
636            IOLockFree(fPMLock);
637            fPMLock = NULL;
638        }
639        if ( fActivityLock ) {
640            IOLockFree(fActivityLock);
641            fActivityLock = NULL;
642        }
643        if ( fInterestedDrivers ) {
644            fInterestedDrivers->release();
645            fInterestedDrivers = NULL;
646        }
647        if (fDriverCallParamSlots && fDriverCallParamPtr) {
648            IODelete(fDriverCallParamPtr, DriverCallParam, fDriverCallParamSlots);
649            fDriverCallParamPtr = 0;
650            fDriverCallParamSlots = 0;
651        }
652        if ( fResponseArray ) {
653            fResponseArray->release();
654            fResponseArray = NULL;
655        }
656        if ( fNotifyClientArray ) {
657            fNotifyClientArray->release();
658            fNotifyClientArray = NULL;
659        }
660        if (fPowerStates && fNumberOfPowerStates) {
661            IODelete(fPowerStates, IOPMPSEntry, fNumberOfPowerStates);
662            fNumberOfPowerStates = 0;
663            fPowerStates = NULL;
664        }
665        if (fPowerClients) {
666            fPowerClients->release();
667            fPowerClients = 0;
668        }
669
670#if PM_VARS_SUPPORT
671        if (fPMVars)
672        {
673            fPMVars->release();
674            fPMVars = 0;
675        }
676#endif
677
678        pwrMgt->release();
679        pwrMgt = 0;
680    }
681}
682
683void IOService::PMDebug( uint32_t event, uintptr_t param1, uintptr_t param2 )
684{
685    OUR_PMLog(event, param1, param2);
686}
687
688//*********************************************************************************
689// [public] joinPMtree
690//
691// A policy-maker calls its nub here when initializing, to be attached into
692// the power management hierarchy.  The default function is to call the
693// platform expert, which knows how to do it.  This method is overridden
694// by a nub subclass which may either know how to do it, or may need to
695// take other action.
696//
697// This may be the only "power management" method used in a nub,
698// meaning it may not be initialized for power management.
699//*********************************************************************************
700
701void IOService::joinPMtree ( IOService * driver )
702{
703    IOPlatformExpert *  platform;
704
705    platform = getPlatform();
706    assert(platform != 0);
707    platform->PMRegisterDevice(this, driver);
708}
709
710#ifndef __LP64__
711//*********************************************************************************
712// [deprecated] youAreRoot
713//
714// Power Managment is informing us that we are the root power domain.
715//*********************************************************************************
716
717IOReturn IOService::youAreRoot ( void )
718{
719    return IOPMNoErr;
720}
721#endif /* !__LP64__ */
722
723//*********************************************************************************
724// [public] PMstop
725//
726// Immediately stop driver callouts. Schedule an async stop request to detach
727// from power plane.
728//*********************************************************************************
729
730void IOService::PMstop ( void )
731{
732    IOPMRequest * request;
733
734    if (!initialized)
735        return;
736
737    PM_LOCK();
738
739    if (fLockedFlags.PMStop)
740    {
741        PM_LOG2("%s: PMstop() already stopped\n", fName);
742        PM_UNLOCK();
743        return;
744    }
745
746    // Inhibit future driver calls.
747    fLockedFlags.PMStop = true;
748
749    // Wait for all prior driver calls to finish.
750    waitForPMDriverCall();
751
752    PM_UNLOCK();
753
754    // The rest of the work is performed async.
755    request = acquirePMRequest( this, kIOPMRequestTypePMStop );
756    if (request)
757    {
758        PM_LOG2("%s: %p PMstop\n", getName(), this);
759        submitPMRequest( request );
760    }
761}
762
763//*********************************************************************************
764// [private] handlePMstop
765//
766// Disconnect the node from all parents and children in the power plane.
767//*********************************************************************************
768
769void IOService::handlePMstop ( IOPMRequest * request )
770{
771    OSIterator *        iter;
772    OSObject *			next;
773    IOPowerConnection *	connection;
774    IOService *			theChild;
775    IOService *			theParent;
776
777	PM_ASSERT_IN_GATE();
778	PM_LOG2("%s: %p %s start\n", getName(), this, __FUNCTION__);
779
780    // remove driver from prevent system sleep lists
781    getPMRootDomain()->updatePreventIdleSleepList(this, false);
782    getPMRootDomain()->updatePreventSystemSleepList(this, false);
783
784    // remove the property
785    removeProperty(kPwrMgtKey);
786
787    // detach parents
788    iter = getParentIterator(gIOPowerPlane);
789    if ( iter )
790    {
791        while ( (next = iter->getNextObject()) )
792        {
793            if ( (connection = OSDynamicCast(IOPowerConnection, next)) )
794            {
795                theParent = (IOService *)connection->copyParentEntry(gIOPowerPlane);
796                if ( theParent )
797                {
798                    theParent->removePowerChild(connection);
799                    theParent->release();
800                }
801            }
802        }
803        iter->release();
804    }
805
806    // detach IOConnections
807    detachAbove( gIOPowerPlane );
808
809    // no more power state changes
810    fParentsKnowState = false;
811
812    // detach children
813    iter = getChildIterator(gIOPowerPlane);
814    if ( iter )
815    {
816        while ( (next = iter->getNextObject()) )
817        {
818            if ( (connection = OSDynamicCast(IOPowerConnection, next)) )
819            {
820                theChild = ((IOService *)(connection->copyChildEntry(gIOPowerPlane)));
821                if ( theChild )
822                {
823                    // detach nub from child
824                    connection->detachFromChild(theChild, gIOPowerPlane);
825                    theChild->release();
826                }
827                // detach us from nub
828                detachFromChild(connection, gIOPowerPlane);
829            }
830        }
831        iter->release();
832    }
833
834    // Remove all interested drivers from the list, including the power
835    // controlling driver.
836    //
837    // Usually, the controlling driver and the policy-maker functionality
838    // are implemented by the same object, and without the deregistration,
839    // the object will be holding an extra retain on itself, and cannot
840    // be freed.
841
842    if ( fInterestedDrivers )
843    {
844        IOPMinformeeList *	list = fInterestedDrivers;
845        IOPMinformee *		item;
846
847        PM_LOCK();
848        while ((item = list->firstInList()))
849        {
850            list->removeFromList(item->whatObject);
851        }
852        PM_UNLOCK();
853    }
854
855    // Tell idleTimerExpired() to ignore idle timer.
856    fIdleTimerPeriod = 0;
857    if (fIdleTimer && thread_call_cancel(fIdleTimer))
858        release();
859
860    PM_LOG2("%s: %p %s done\n", getName(), this, __FUNCTION__);
861}
862
863//*********************************************************************************
864// [public] addPowerChild
865//
866// Power Management is informing us who our children are.
867//*********************************************************************************
868
869IOReturn IOService::addPowerChild ( IOService * child )
870{
871	IOPowerConnection *	connection  = 0;
872	IOPMRequest *		requests[3] = {0, 0, 0};
873    OSIterator *		iter;
874	bool				ok = true;
875
876	if (!child)
877		return kIOReturnBadArgument;
878
879    if (!initialized || !child->initialized)
880		return IOPMNotYetInitialized;
881
882    OUR_PMLog( kPMLogAddChild, (uintptr_t) child, 0 );
883
884	do {
885		// Is this child already one of our children?
886
887		iter = child->getParentIterator( gIOPowerPlane );
888		if ( iter )
889		{
890			IORegistryEntry *	entry;
891			OSObject *			next;
892
893			while ((next = iter->getNextObject()))
894			{
895				if ((entry = OSDynamicCast(IORegistryEntry, next)) &&
896					isChild(entry, gIOPowerPlane))
897				{
898					ok = false;
899					break;
900				}
901			}
902			iter->release();
903		}
904		if (!ok)
905		{
906			PM_LOG("%s: %s (%p) is already a child\n",
907				getName(), child->getName(), child);
908			break;
909		}
910
911		// Add the child to the power plane immediately, but the
912		// joining connection is marked as not ready.
913		// We want the child to appear in the power plane before
914		// returning to the caller, but don't want the caller to
915		// block on the PM work loop.
916
917		connection = new IOPowerConnection;
918		if (!connection)
919			break;
920
921		// Create a chain of PM requests to perform the bottom-half
922		// work from the PM work loop.
923
924		requests[0] = acquirePMRequest(
925					/* target */ this,
926					/* type */   kIOPMRequestTypeAddPowerChild1 );
927
928		requests[1] = acquirePMRequest(
929					/* target */ child,
930					/* type */   kIOPMRequestTypeAddPowerChild2 );
931
932		requests[2] = acquirePMRequest(
933					/* target */ this,
934					/* type */   kIOPMRequestTypeAddPowerChild3 );
935
936		if (!requests[0] || !requests[1] || !requests[2])
937			break;
938
939		requests[0]->attachNextRequest( requests[1] );
940		requests[1]->attachNextRequest( requests[2] );
941
942		connection->init();
943		connection->start(this);
944		connection->setAwaitingAck(false);
945		connection->setReadyFlag(false);
946
947		attachToChild( connection, gIOPowerPlane );
948		connection->attachToChild( child, gIOPowerPlane );
949
950		// connection needs to be released
951		requests[0]->fArg0 = connection;
952		requests[1]->fArg0 = connection;
953		requests[2]->fArg0 = connection;
954
955		submitPMRequest( requests, 3 );
956		return kIOReturnSuccess;
957	}
958	while (false);
959
960	if (connection)  connection->release();
961	if (requests[0]) releasePMRequest(requests[0]);
962	if (requests[1]) releasePMRequest(requests[1]);
963	if (requests[2]) releasePMRequest(requests[2]);
964
965	// Silent failure, to prevent platform drivers from adding the child
966	// to the root domain.
967
968	return kIOReturnSuccess;
969}
970
971//*********************************************************************************
972// [private] addPowerChild1
973//
974// Step 1/3 of adding a power child. Called on the power parent.
975//*********************************************************************************
976
977void IOService::addPowerChild1 ( IOPMRequest * request )
978{
979	unsigned long tempDesire = 0;
980
981	// Make us temporary usable before adding the child.
982
983	PM_ASSERT_IN_GATE();
984    OUR_PMLog( kPMLogMakeUsable, kPMLogMakeUsable, 0 );
985
986	if (fControllingDriver && inPlane(gIOPowerPlane) && fParentsKnowState)
987	{
988		tempDesire = fNumberOfPowerStates - 1;
989	}
990
991	if (tempDesire && (IS_PM_ROOT || (fMaxPowerState >= tempDesire)))
992	{
993		adjustPowerState(tempDesire);
994	}
995}
996
997//*********************************************************************************
998// [private] addPowerChild2
999//
1000// Step 2/3 of adding a power child. Called on the joining child.
1001// Execution blocked behind addPowerChild1.
1002//*********************************************************************************
1003
1004void IOService::addPowerChild2 ( IOPMRequest * request )
1005{
1006	IOPowerConnection * connection = (IOPowerConnection *) request->fArg0;
1007	IOService *         parent;
1008	IOPMPowerFlags		powerFlags;
1009	bool				knowsState;
1010	unsigned long		powerState;
1011	unsigned long		tempDesire;
1012
1013	PM_ASSERT_IN_GATE();
1014	parent = (IOService *) connection->getParentEntry(gIOPowerPlane);
1015
1016	if (!parent || !inPlane(gIOPowerPlane))
1017	{
1018		PM_LOG("%s: addPowerChild2 not in power plane\n", getName());
1019		return;
1020	}
1021
1022	// Parent will be waiting for us to complete this stage.
1023	// It is safe to directly access parent's vars.
1024
1025	knowsState = (parent->fPowerStates) && (parent->fParentsKnowState);
1026	powerState = parent->fCurrentPowerState;
1027
1028	if (knowsState)
1029		powerFlags = parent->fPowerStates[powerState].outputPowerFlags;
1030	else
1031		powerFlags = 0;
1032
1033	// Set our power parent.
1034
1035    OUR_PMLog(kPMLogSetParent, knowsState, powerFlags);
1036
1037	setParentInfo( powerFlags, connection, knowsState );
1038
1039	connection->setReadyFlag(true);
1040
1041    if ( fControllingDriver && fParentsKnowState )
1042    {
1043        fMaxPowerState = fControllingDriver->maxCapabilityForDomainState(fParentsCurrentPowerFlags);
1044        // initially change into the state we are already in
1045        tempDesire = fControllingDriver->initialPowerStateForDomainState(fParentsCurrentPowerFlags);
1046        fPreviousRequestPowerFlags = (IOPMPowerFlags)(-1);
1047        adjustPowerState(tempDesire);
1048    }
1049
1050    getPMRootDomain()->tagPowerPlaneService(this, &fPMActions);
1051}
1052
1053//*********************************************************************************
1054// [private] addPowerChild3
1055//
1056// Step 3/3 of adding a power child. Called on the parent.
1057// Execution blocked behind addPowerChild2.
1058//*********************************************************************************
1059
1060void IOService::addPowerChild3 ( IOPMRequest * request )
1061{
1062	IOPowerConnection * connection = (IOPowerConnection *) request->fArg0;
1063	IOService *         child;
1064    IOPMrootDomain *    rootDomain = getPMRootDomain();
1065
1066	PM_ASSERT_IN_GATE();
1067	child = (IOService *) connection->getChildEntry(gIOPowerPlane);
1068
1069	if (child && inPlane(gIOPowerPlane))
1070	{
1071		if ((this != rootDomain) && child->getProperty("IOPMStrictTreeOrder"))
1072		{
1073			PM_LOG1("%s: strict PM order enforced\n", getName());
1074			fStrictTreeOrder = true;
1075		}
1076
1077        if (rootDomain)
1078            rootDomain->joinAggressiveness( child );
1079	}
1080	else
1081	{
1082		PM_LOG("%s: addPowerChild3 not in power plane\n", getName());
1083	}
1084
1085	connection->release();
1086}
1087
1088#ifndef __LP64__
1089//*********************************************************************************
1090// [deprecated] setPowerParent
1091//
1092// Power Management is informing us who our parent is.
1093// If we have a controlling driver, find out, given our newly-informed
1094// power domain state, what state it would be in, and then tell it
1095// to assume that state.
1096//*********************************************************************************
1097
1098IOReturn IOService::setPowerParent (
1099	IOPowerConnection * theParent, bool stateKnown, IOPMPowerFlags powerFlags )
1100{
1101	return kIOReturnUnsupported;
1102}
1103#endif /* !__LP64__ */
1104
1105//*********************************************************************************
1106// [public] removePowerChild
1107//
1108// Called on a parent whose child is being removed by PMstop().
1109//*********************************************************************************
1110
1111IOReturn IOService::removePowerChild ( IOPowerConnection * theNub )
1112{
1113    IORegistryEntry *	theChild;
1114
1115	PM_ASSERT_IN_GATE();
1116    OUR_PMLog( kPMLogRemoveChild, 0, 0 );
1117
1118    theNub->retain();
1119
1120    // detach nub from child
1121    theChild = theNub->copyChildEntry(gIOPowerPlane);
1122    if ( theChild )
1123    {
1124        theNub->detachFromChild(theChild, gIOPowerPlane);
1125        theChild->release();
1126    }
1127    // detach from the nub
1128    detachFromChild(theNub, gIOPowerPlane);
1129
1130    // Are we awaiting an ack from this child?
1131    if ( theNub->getAwaitingAck() )
1132	{
1133		// yes, pretend we got one
1134		theNub->setAwaitingAck(false);
1135		if (fHeadNotePendingAcks != 0 )
1136		{
1137			// that's one fewer ack to worry about
1138			fHeadNotePendingAcks--;
1139
1140			// is that the last?
1141			if ( fHeadNotePendingAcks == 0 )
1142			{
1143				stop_ack_timer();
1144
1145				// Request unblocked, work queue
1146				// should re-scan all busy requests.
1147				gIOPMWorkQueue->incrementProducerCount();
1148			}
1149		}
1150	}
1151
1152	theNub->release();
1153
1154	// A child has gone away, re-scan children desires and clamp bits.
1155    // The fPendingAdjustPowerRequest helps to reduce redundant parent work.
1156
1157	if (!fAdjustPowerScheduled)
1158	{
1159		IOPMRequest * request;
1160		request = acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState );
1161		if (request)
1162		{
1163			submitPMRequest( request );
1164			fAdjustPowerScheduled = true;
1165		}
1166	}
1167
1168    return IOPMNoErr;
1169}
1170
1171//*********************************************************************************
1172// [public] registerPowerDriver
1173//
1174// A driver has called us volunteering to control power to our device.
1175//*********************************************************************************
1176
1177IOReturn IOService::registerPowerDriver (
1178	IOService *			powerDriver,
1179	IOPMPowerState *	powerStates,
1180	unsigned long		numberOfStates )
1181{
1182	IOPMRequest *   request;
1183	IOPMPSEntry *   powerStatesCopy = 0;
1184
1185    if (!initialized)
1186		return IOPMNotYetInitialized;
1187
1188	// Validate arguments.
1189	if (!powerStates || (numberOfStates < 2))
1190	{
1191		OUR_PMLog(kPMLogControllingDriverErr5, numberOfStates, 0);
1192		return kIOReturnBadArgument;
1193	}
1194
1195	if (!powerDriver || !powerDriver->initialized)
1196	{
1197		OUR_PMLog(kPMLogControllingDriverErr4, 0, 0);
1198		return kIOReturnBadArgument;
1199	}
1200
1201	if (powerStates[0].version != kIOPMPowerStateVersion1)
1202	{
1203		OUR_PMLog(kPMLogControllingDriverErr1, powerStates[0].version, 0);
1204		return kIOReturnBadArgument;
1205	}
1206
1207	do {
1208		// Make a copy of the supplied power state array.
1209		powerStatesCopy = IONew(IOPMPSEntry, numberOfStates);
1210		if (!powerStatesCopy)
1211			break;
1212
1213        for (uint32_t i = 0; i < numberOfStates; i++)
1214        {
1215            powerStatesCopy[i].capabilityFlags  = powerStates[i].capabilityFlags;
1216            powerStatesCopy[i].outputPowerFlags = powerStates[i].outputPowerCharacter;
1217            powerStatesCopy[i].inputPowerFlags  = powerStates[i].inputPowerRequirement;
1218            powerStatesCopy[i].staticPower      = powerStates[i].staticPower;
1219            powerStatesCopy[i].settleUpTime     = powerStates[i].settleUpTime;
1220            powerStatesCopy[i].settleDownTime   = powerStates[i].settleDownTime;
1221        }
1222
1223		request = acquirePMRequest( this, kIOPMRequestTypeRegisterPowerDriver );
1224		if (!request)
1225			break;
1226
1227		powerDriver->retain();
1228		request->fArg0 = (void *) powerDriver;
1229		request->fArg1 = (void *) powerStatesCopy;
1230		request->fArg2 = (void *) numberOfStates;
1231
1232		submitPMRequest( request );
1233		return kIOReturnSuccess;
1234	}
1235	while (false);
1236
1237	if (powerStatesCopy)
1238		IODelete(powerStatesCopy, IOPMPSEntry, numberOfStates);
1239	return kIOReturnNoMemory;
1240}
1241
1242//*********************************************************************************
1243// [private] handleRegisterPowerDriver
1244//*********************************************************************************
1245
1246void IOService::handleRegisterPowerDriver ( IOPMRequest * request )
1247{
1248	IOService *     powerDriver    = (IOService *)   request->fArg0;
1249	IOPMPSEntry *   powerStates    = (IOPMPSEntry *) request->fArg1;
1250	unsigned long   numberOfStates = (unsigned long) request->fArg2;
1251    unsigned long   i;
1252	IOService *     root;
1253	OSIterator *    iter;
1254
1255	PM_ASSERT_IN_GATE();
1256	assert(powerStates);
1257	assert(powerDriver);
1258	assert(numberOfStates > 1);
1259
1260    if ( !fNumberOfPowerStates )
1261    {
1262		OUR_PMLog(kPMLogControllingDriver,
1263			(unsigned long) numberOfStates,
1264			(unsigned long) kIOPMPowerStateVersion1);
1265
1266        fPowerStates            = powerStates;
1267		fNumberOfPowerStates    = numberOfStates;
1268		fControllingDriver      = powerDriver;
1269        fCurrentCapabilityFlags = fPowerStates[0].capabilityFlags;
1270
1271		// make a mask of all the character bits we know about
1272		fOutputPowerCharacterFlags = 0;
1273		for ( i = 0; i < numberOfStates; i++ ) {
1274			fOutputPowerCharacterFlags |= fPowerStates[i].outputPowerFlags;
1275            if (!fDeviceUsablePowerState &&
1276                (fPowerStates[i].capabilityFlags & IOPMDeviceUsable))
1277            {
1278                // The minimum power state that the device is usable
1279                fDeviceUsablePowerState = i;
1280            }
1281		}
1282
1283		// Register powerDriver as interested, unless already done.
1284		// We don't want to register the default implementation since
1285		// it does nothing. One ramification of not always registering
1286		// is the one fewer retain count held.
1287
1288		root = getPlatform()->getProvider();
1289		assert(root);
1290		if (!root ||
1291			((OSMemberFunctionCast(void (*)(void),
1292				root, &IOService::powerStateDidChangeTo)) !=
1293			((OSMemberFunctionCast(void (*)(void),
1294				this, &IOService::powerStateDidChangeTo)))) ||
1295			((OSMemberFunctionCast(void (*)(void),
1296				root, &IOService::powerStateWillChangeTo)) !=
1297			((OSMemberFunctionCast(void (*)(void),
1298				this, &IOService::powerStateWillChangeTo)))))
1299		{
1300			if (fInterestedDrivers->findItem(powerDriver) == NULL)
1301			{
1302				PM_LOCK();
1303				fInterestedDrivers->appendNewInformee(powerDriver);
1304				PM_UNLOCK();
1305			}
1306		}
1307
1308		// Examine all existing power clients and perform limit check.
1309
1310        if (fPowerClients)
1311        {
1312            iter = OSCollectionIterator::withCollection(fPowerClients);
1313            if (iter)
1314            {
1315                const OSSymbol * client;
1316                while ((client = (const OSSymbol *) iter->getNextObject()))
1317                {
1318                    uint32_t powerState = getPowerStateForClient(client);
1319                    if (powerState >= numberOfStates)
1320                    {
1321                        updatePowerClient(client, numberOfStates - 1);
1322                    }
1323                }
1324                iter->release();
1325            }
1326        }
1327
1328		if ( inPlane(gIOPowerPlane) && fParentsKnowState )
1329		{
1330			unsigned long tempDesire;
1331			fMaxPowerState = fControllingDriver->maxCapabilityForDomainState(fParentsCurrentPowerFlags);
1332			// initially change into the state we are already in
1333			tempDesire = fControllingDriver->initialPowerStateForDomainState(fParentsCurrentPowerFlags);
1334			adjustPowerState(tempDesire);
1335		}
1336	}
1337	else
1338	{
1339		OUR_PMLog(kPMLogControllingDriverErr2, numberOfStates, 0);
1340        IODelete(powerStates, IOPMPSEntry, numberOfStates);
1341	}
1342
1343	powerDriver->release();
1344}
1345
1346//*********************************************************************************
1347// [public] registerInterestedDriver
1348//
1349// Add the caller to our list of interested drivers and return our current
1350// power state.  If we don't have a power-controlling driver yet, we will
1351// call this interested driver again later when we do get a driver and find
1352// out what the current power state of the device is.
1353//*********************************************************************************
1354
1355IOPMPowerFlags IOService::registerInterestedDriver ( IOService * driver )
1356{
1357    IOPMRequest *	request;
1358    bool			signal;
1359
1360    if (!driver || !initialized || !fInterestedDrivers)
1361        return 0;
1362
1363    PM_LOCK();
1364    signal = (!fInsertInterestSet && !fRemoveInterestSet);
1365    if (fInsertInterestSet == NULL)
1366        fInsertInterestSet = OSSet::withCapacity(4);
1367    if (fInsertInterestSet)
1368    {
1369        fInsertInterestSet->setObject(driver);
1370        if (fRemoveInterestSet)
1371            fRemoveInterestSet->removeObject(driver);
1372    }
1373    PM_UNLOCK();
1374
1375    if (signal)
1376    {
1377        request = acquirePMRequest( this, kIOPMRequestTypeInterestChanged );
1378        if (request)
1379            submitPMRequest( request );
1380    }
1381
1382    // This return value cannot be trusted, but return a value
1383    // for those clients that care.
1384
1385    OUR_PMLog(kPMLogInterestedDriver, kIOPMDeviceUsable, 2);
1386    return kIOPMDeviceUsable;
1387}
1388
1389//*********************************************************************************
1390// [public] deRegisterInterestedDriver
1391//*********************************************************************************
1392
1393IOReturn IOService::deRegisterInterestedDriver ( IOService * driver )
1394{
1395    IOPMinformeeList *	list;
1396    IOPMinformee *		item;
1397    IOPMRequest *       request;
1398    bool                signal;
1399
1400    if (!driver)
1401        return kIOReturnBadArgument;
1402    if (!initialized || !fInterestedDrivers)
1403        return IOPMNotPowerManaged;
1404
1405    PM_LOCK();
1406    signal = (!fRemoveInterestSet && !fInsertInterestSet);
1407    if (fRemoveInterestSet == NULL)
1408        fRemoveInterestSet = OSSet::withCapacity(4);
1409    if (fRemoveInterestSet)
1410    {
1411        fRemoveInterestSet->setObject(driver);
1412        if (fInsertInterestSet)
1413            fInsertInterestSet->removeObject(driver);
1414
1415        list = fInterestedDrivers;
1416        item = list->findItem(driver);
1417        if (item && item->active)
1418        {
1419            item->active = false;
1420            waitForPMDriverCall( driver );
1421        }
1422    }
1423    PM_UNLOCK();
1424
1425    if (signal)
1426    {
1427        request = acquirePMRequest( this, kIOPMRequestTypeInterestChanged );
1428        if (request)
1429            submitPMRequest( request );
1430    }
1431
1432    return IOPMNoErr;
1433}
1434
1435//*********************************************************************************
1436// [private] handleInterestChanged
1437//
1438// Handle interest added or removed.
1439//*********************************************************************************
1440
1441void IOService::handleInterestChanged( IOPMRequest * request )
1442{
1443    IOService *			driver;
1444    IOPMinformee *		informee;
1445    IOPMinformeeList *	list = fInterestedDrivers;
1446
1447    PM_LOCK();
1448
1449    if (fInsertInterestSet)
1450    {
1451        while ((driver = (IOService *) fInsertInterestSet->getAnyObject()))
1452        {
1453            if (list->findItem(driver) == NULL)
1454            {
1455                informee = list->appendNewInformee(driver);
1456            }
1457            fInsertInterestSet->removeObject(driver);
1458        }
1459        fInsertInterestSet->release();
1460        fInsertInterestSet = 0;
1461    }
1462
1463    if (fRemoveInterestSet)
1464    {
1465        while ((driver = (IOService *) fRemoveInterestSet->getAnyObject()))
1466        {
1467            informee = list->findItem(driver);
1468            if (informee)
1469            {
1470                // Clean-up async interest acknowledgement
1471                if (fHeadNotePendingAcks && informee->timer)
1472                {
1473                    informee->timer = 0;
1474                    fHeadNotePendingAcks--;
1475                }
1476                list->removeFromList(driver);
1477            }
1478            fRemoveInterestSet->removeObject(driver);
1479        }
1480        fRemoveInterestSet->release();
1481        fRemoveInterestSet = 0;
1482    }
1483
1484    PM_UNLOCK();
1485}
1486
1487//*********************************************************************************
1488// [public] acknowledgePowerChange
1489//
1490// After we notified one of the interested drivers or a power-domain child
1491// of an impending change in power, it has called to say it is now
1492// prepared for the change.  If this object is the last to
1493// acknowledge this change, we take whatever action we have been waiting
1494// for.
1495// That may include acknowledging to our parent.  In this case, we do it
1496// last of all to insure that this doesn't cause the parent to call us some-
1497// where else and alter data we are relying on here (like the very existance
1498// of a "current change note".)
1499//*********************************************************************************
1500
1501IOReturn IOService::acknowledgePowerChange ( IOService * whichObject )
1502{
1503	IOPMRequest * request;
1504
1505    if (!initialized)
1506		return IOPMNotYetInitialized;
1507	if (!whichObject)
1508		return kIOReturnBadArgument;
1509
1510	request = acquirePMRequest( this, kIOPMRequestTypeAckPowerChange );
1511	if (!request)
1512		return kIOReturnNoMemory;
1513
1514	whichObject->retain();
1515	request->fArg0 = whichObject;
1516
1517	submitPMRequest( request );
1518    return IOPMNoErr;
1519}
1520
1521//*********************************************************************************
1522// [private] handleAcknowledgePowerChange
1523//*********************************************************************************
1524
1525bool IOService::handleAcknowledgePowerChange ( IOPMRequest * request )
1526{
1527    IOPMinformee *		informee;
1528    unsigned long		childPower = kIOPMUnknown;
1529    IOService *			theChild;
1530	IOService *			whichObject;
1531	bool				all_acked  = false;
1532
1533	PM_ASSERT_IN_GATE();
1534	whichObject = (IOService *) request->fArg0;
1535	assert(whichObject);
1536
1537    // one of our interested drivers?
1538	informee = fInterestedDrivers->findItem( whichObject );
1539    if ( informee == NULL )
1540    {
1541        if ( !isChild(whichObject, gIOPowerPlane) )
1542        {
1543			OUR_PMLog(kPMLogAcknowledgeErr1, 0, 0);
1544			goto no_err;
1545        } else {
1546            OUR_PMLog(kPMLogChildAcknowledge, fHeadNotePendingAcks, 0);
1547        }
1548    } else {
1549        OUR_PMLog(kPMLogDriverAcknowledge, fHeadNotePendingAcks, 0);
1550    }
1551
1552    if ( fHeadNotePendingAcks != 0 )
1553    {
1554        assert(fPowerStates != NULL);
1555
1556         // yes, make sure we're expecting acks
1557        if ( informee != NULL )
1558        {
1559            // it's an interested driver
1560            // make sure we're expecting this ack
1561            if ( informee->timer != 0 )
1562            {
1563#if LOG_SETPOWER_TIMES
1564                if (informee->timer > 0)
1565                {
1566                    uint64_t nsec = computeTimeDeltaNS(&informee->startTime);
1567                    if (nsec > LOG_SETPOWER_TIMES)
1568                        PM_LOG("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) async took %d ms\n",
1569                            informee->whatObject->getName(),
1570                            (fDriverCallReason == kDriverCallInformPreChange) ? "Will" : "Did",
1571                            informee->whatObject,
1572                            fName, fCurrentPowerState, fHeadNotePowerState, NS_TO_US(nsec));
1573
1574                    uint16_t logType = (fDriverCallReason == kDriverCallInformPreChange)
1575                                            ? kIOPMEventTypePSWillChangeTo
1576                                             : kIOPMEventTypePSDidChangeTo;
1577
1578                    PMEventDetails *details = PMEventDetails::eventDetails(
1579                                                logType,
1580                                                fName,
1581                                                (uintptr_t)this,
1582                                                informee->whatObject->getName(),
1583                                                0, 0, 0,
1584                                                NS_TO_MS(nsec));
1585
1586                    getPMRootDomain()->recordAndReleasePMEventGated( details );
1587                }
1588#endif
1589                // mark it acked
1590                informee->timer = 0;
1591                // that's one fewer to worry about
1592                fHeadNotePendingAcks--;
1593            } else {
1594                // this driver has already acked
1595                OUR_PMLog(kPMLogAcknowledgeErr2, 0, 0);
1596            }
1597        } else {
1598            // it's a child
1599            // make sure we're expecting this ack
1600            if ( ((IOPowerConnection *)whichObject)->getAwaitingAck() )
1601            {
1602                // that's one fewer to worry about
1603                fHeadNotePendingAcks--;
1604                ((IOPowerConnection *)whichObject)->setAwaitingAck(false);
1605                theChild = (IOService *)whichObject->copyChildEntry(gIOPowerPlane);
1606                if ( theChild )
1607                {
1608                    childPower = theChild->currentPowerConsumption();
1609                    theChild->release();
1610                }
1611                if ( childPower == kIOPMUnknown )
1612                {
1613                    fHeadNotePowerArrayEntry->staticPower = kIOPMUnknown;
1614                } else {
1615                    if (fHeadNotePowerArrayEntry->staticPower != kIOPMUnknown)
1616                    {
1617                        fHeadNotePowerArrayEntry->staticPower += childPower;
1618                    }
1619                }
1620            }
1621	    }
1622
1623		if ( fHeadNotePendingAcks == 0 ) {
1624			// yes, stop the timer
1625			stop_ack_timer();
1626			// and now we can continue
1627			all_acked = true;
1628		}
1629    } else {
1630        OUR_PMLog(kPMLogAcknowledgeErr3, 0, 0);	// not expecting anybody to ack
1631    }
1632
1633no_err:
1634	if (whichObject)
1635		whichObject->release();
1636
1637    return all_acked;
1638}
1639
1640//*********************************************************************************
1641// [public] acknowledgeSetPowerState
1642//
1643// After we instructed our controlling driver to change power states,
1644// it has called to say it has finished doing so.
1645// We continue to process the power state change.
1646//*********************************************************************************
1647
1648IOReturn IOService::acknowledgeSetPowerState ( void )
1649{
1650	IOPMRequest * request;
1651
1652    if (!initialized)
1653		return IOPMNotYetInitialized;
1654
1655	request = acquirePMRequest( this, kIOPMRequestTypeAckSetPowerState );
1656	if (!request)
1657		return kIOReturnNoMemory;
1658
1659	submitPMRequest( request );
1660	return kIOReturnSuccess;
1661}
1662
1663//*********************************************************************************
1664// [private] adjustPowerState
1665//*********************************************************************************
1666
1667void IOService::adjustPowerState ( uint32_t clamp )
1668{
1669	PM_ASSERT_IN_GATE();
1670	computeDesiredState(clamp);
1671	if (fControllingDriver && fParentsKnowState && inPlane(gIOPowerPlane))
1672	{
1673        IOPMPowerChangeFlags changeFlags = kIOPMSelfInitiated;
1674
1675        // Indicate that children desires were ignored, and do not ask
1676        // apps for permission to drop power. This is used by root domain
1677        // for demand sleep.
1678
1679        if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride)
1680            changeFlags |= (kIOPMIgnoreChildren | kIOPMSkipAskPowerDown);
1681
1682		startPowerChange(
1683			 /* flags        */	changeFlags,
1684			 /* power state  */	fDesiredPowerState,
1685			 /* domain flags */	0,
1686			 /* connection   */	0,
1687			 /* parent flags */	0);
1688	}
1689}
1690
1691//*********************************************************************************
1692// [public] synchronizePowerTree
1693//*********************************************************************************
1694
1695IOReturn IOService::synchronizePowerTree (
1696    IOOptionBits    options,
1697    IOService *     notifyRoot )
1698{
1699	IOPMRequest *   request_c = 0;
1700    IOPMRequest *   request_s;
1701
1702    if (this != getPMRootDomain())
1703        return kIOReturnBadArgument;
1704	if (!initialized)
1705		return kIOPMNotYetInitialized;
1706
1707    if (notifyRoot)
1708    {
1709        IOPMRequest * nr;
1710
1711        // Cancels don't need to be synchronized.
1712        nr = acquirePMRequest(notifyRoot, kIOPMRequestTypeChildNotifyDelayCancel);
1713        if (nr) submitPMRequest(nr);
1714        nr = acquirePMRequest(getPMRootDomain(), kIOPMRequestTypeChildNotifyDelayCancel);
1715        if (nr) submitPMRequest(nr);
1716    }
1717
1718    request_s = acquirePMRequest( this, kIOPMRequestTypeSynchronizePowerTree );
1719    if (!request_s)
1720        goto error_no_memory;
1721
1722    if (options & kIOPMSyncCancelPowerDown)
1723        request_c = acquirePMRequest( this, kIOPMRequestTypeIdleCancel );
1724    if (request_c)
1725    {
1726        request_c->attachNextRequest( request_s );
1727        submitPMRequest(request_c);
1728    }
1729
1730    request_s->fArg0 = (void *)(uintptr_t) options;
1731    submitPMRequest(request_s);
1732
1733    return kIOReturnSuccess;
1734
1735error_no_memory:
1736	if (request_c) releasePMRequest(request_c);
1737	if (request_s) releasePMRequest(request_s);
1738    return kIOReturnNoMemory;
1739}
1740
1741//*********************************************************************************
1742// [private] handleSynchronizePowerTree
1743//*********************************************************************************
1744
1745void IOService::handleSynchronizePowerTree ( IOPMRequest * request )
1746{
1747	PM_ASSERT_IN_GATE();
1748	if (fControllingDriver && fParentsKnowState && inPlane(gIOPowerPlane) &&
1749        (fCurrentPowerState == fNumberOfPowerStates - 1))
1750	{
1751        IOOptionBits options = (uintptr_t) request->fArg0;
1752
1753		startPowerChange(
1754			 /* flags        */	kIOPMSelfInitiated | kIOPMSynchronize |
1755                                (options & kIOPMSyncNoChildNotify),
1756			 /* power state  */	fCurrentPowerState,
1757			 /* domain flags */	0,
1758			 /* connection   */	0,
1759			 /* parent flags */	0);
1760	}
1761}
1762
1763#ifndef __LP64__
1764//*********************************************************************************
1765// [deprecated] powerDomainWillChangeTo
1766//
1767// Called by the power-hierarchy parent notifying of a new power state
1768// in the power domain.
1769// We enqueue a parent power-change to our queue of power changes.
1770// This may or may not cause us to change power, depending on what
1771// kind of change is occuring in the domain.
1772//*********************************************************************************
1773
1774IOReturn IOService::powerDomainWillChangeTo (
1775	IOPMPowerFlags		newPowerFlags,
1776	IOPowerConnection *	whichParent )
1777{
1778	assert(false);
1779	return kIOReturnUnsupported;
1780}
1781#endif /* !__LP64__ */
1782
1783//*********************************************************************************
1784// [private] handlePowerDomainWillChangeTo
1785//*********************************************************************************
1786
1787void IOService::handlePowerDomainWillChangeTo ( IOPMRequest * request )
1788{
1789	IOPMPowerFlags		 parentPowerFlags = (IOPMPowerFlags) request->fArg0;
1790	IOPowerConnection *	 whichParent = (IOPowerConnection *) request->fArg1;
1791    IOPMPowerChangeFlags parentChangeFlags = (IOPMPowerChangeFlags)(uintptr_t) request->fArg2;
1792    IOPMPowerChangeFlags myChangeFlags;
1793    OSIterator *		 iter;
1794    OSObject *			 next;
1795    IOPowerConnection *	 connection;
1796    IOPMPowerStateIndex  newPowerState;
1797    IOPMPowerFlags		 combinedPowerFlags;
1798	bool				 savedParentsKnowState;
1799	IOReturn			 result = IOPMAckImplied;
1800
1801	PM_ASSERT_IN_GATE();
1802    OUR_PMLog(kPMLogWillChange, parentPowerFlags, 0);
1803
1804	if (!inPlane(gIOPowerPlane) || !whichParent || !whichParent->getAwaitingAck())
1805	{
1806		PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__);
1807        goto exit_no_ack;
1808	}
1809
1810	savedParentsKnowState = fParentsKnowState;
1811
1812    // Combine parents' output power flags.
1813
1814	combinedPowerFlags = 0;
1815
1816    iter = getParentIterator(gIOPowerPlane);
1817    if ( iter )
1818    {
1819        while ( (next = iter->getNextObject()) )
1820        {
1821            if ( (connection = OSDynamicCast(IOPowerConnection, next)) )
1822            {
1823                if ( connection == whichParent )
1824                    combinedPowerFlags |= parentPowerFlags;
1825                else
1826                    combinedPowerFlags |= connection->parentCurrentPowerFlags();
1827            }
1828        }
1829        iter->release();
1830    }
1831
1832    // If our initial change has yet to occur, then defer the power change
1833    // until after the power domain has completed its power transition.
1834
1835    if ( fControllingDriver && !fInitialPowerChange )
1836    {
1837		newPowerState = fControllingDriver->maxCapabilityForDomainState(
1838							combinedPowerFlags);
1839
1840        // Absorb parent's kIOPMSynchronize flag.
1841        myChangeFlags = kIOPMParentInitiated | kIOPMDomainWillChange |
1842                        (parentChangeFlags & kIOPMSynchronize);
1843
1844		result = startPowerChange(
1845                 /* flags        */	myChangeFlags,
1846                 /* power state  */	newPowerState,
1847				 /* domain flags */	combinedPowerFlags,
1848				 /* connection   */	whichParent,
1849				 /* parent flags */	parentPowerFlags);
1850	}
1851
1852	// If parent is dropping power, immediately update the parent's
1853	// capability flags. Any future merging of parent(s) combined
1854	// power flags should account for this power drop.
1855
1856	if (parentChangeFlags & kIOPMDomainPowerDrop)
1857	{
1858		setParentInfo(parentPowerFlags, whichParent, true);
1859	}
1860
1861	// Parent is expecting an ACK from us. If we did not embark on a state
1862	// transition, i.e. startPowerChange() returned IOPMAckImplied. We are
1863	// still required to issue an ACK to our parent.
1864
1865	if (IOPMAckImplied == result)
1866	{
1867		IOService * parent;
1868		parent = (IOService *) whichParent->copyParentEntry(gIOPowerPlane);
1869		assert(parent);
1870		if ( parent )
1871		{
1872			parent->acknowledgePowerChange( whichParent );
1873			parent->release();
1874		}
1875	}
1876
1877exit_no_ack:
1878    // Drop the retain from notifyChild().
1879    if (whichParent) whichParent->release();
1880}
1881
1882#ifndef __LP64__
1883//*********************************************************************************
1884// [deprecated] powerDomainDidChangeTo
1885//
1886// Called by the power-hierarchy parent after the power state of the power domain
1887// has settled at a new level.
1888// We enqueue a parent power-change to our queue of power changes.
1889// This may or may not cause us to change power, depending on what
1890// kind of change is occuring in the domain.
1891//*********************************************************************************
1892
1893IOReturn IOService::powerDomainDidChangeTo (
1894	IOPMPowerFlags		newPowerFlags,
1895	IOPowerConnection *	whichParent )
1896{
1897	assert(false);
1898	return kIOReturnUnsupported;
1899}
1900#endif /* !__LP64__ */
1901
1902//*********************************************************************************
1903// [private] handlePowerDomainDidChangeTo
1904//*********************************************************************************
1905
1906void IOService::handlePowerDomainDidChangeTo ( IOPMRequest * request )
1907{
1908	IOPMPowerFlags		 parentPowerFlags = (IOPMPowerFlags) request->fArg0;
1909	IOPowerConnection *	 whichParent = (IOPowerConnection *) request->fArg1;
1910    IOPMPowerChangeFlags parentChangeFlags = (IOPMPowerChangeFlags)(uintptr_t) request->fArg2;
1911    IOPMPowerChangeFlags myChangeFlags;
1912    IOPMPowerStateIndex  newPowerState;
1913    IOPMPowerStateIndex  initialDesire;
1914	bool				 savedParentsKnowState;
1915	IOReturn			 result = IOPMAckImplied;
1916
1917	PM_ASSERT_IN_GATE();
1918    OUR_PMLog(kPMLogDidChange, parentPowerFlags, 0);
1919
1920	if (!inPlane(gIOPowerPlane) || !whichParent || !whichParent->getAwaitingAck())
1921	{
1922		PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__);
1923        goto exit_no_ack;
1924	}
1925
1926	savedParentsKnowState = fParentsKnowState;
1927
1928    setParentInfo(parentPowerFlags, whichParent, true);
1929
1930    if ( fControllingDriver )
1931	{
1932		newPowerState = fControllingDriver->maxCapabilityForDomainState(
1933							fParentsCurrentPowerFlags);
1934
1935        if (fInitialPowerChange)
1936        {
1937            initialDesire = fControllingDriver->initialPowerStateForDomainState(
1938                            fParentsCurrentPowerFlags);
1939            computeDesiredState(initialDesire);
1940        }
1941        else if (fAdvisoryTickleUsed && (newPowerState > 0) &&
1942                 ((parentChangeFlags & kIOPMSynchronize) == 0))
1943        {
1944            // re-compute desired state in case advisory tickle was enabled
1945            computeDesiredState();
1946        }
1947
1948        // Absorb parent's kIOPMSynchronize flag.
1949        myChangeFlags = kIOPMParentInitiated | kIOPMDomainDidChange |
1950                        (parentChangeFlags & kIOPMSynchronize);
1951
1952		result = startPowerChange(
1953				 /* flags        */	myChangeFlags,
1954                 /* power state  */	newPowerState,
1955				 /* domain flags */	fParentsCurrentPowerFlags,
1956				 /* connection   */	whichParent,
1957				 /* parent flags */	0);
1958	}
1959
1960	// Parent is expecting an ACK from us. If we did not embark on a state
1961	// transition, i.e. startPowerChange() returned IOPMAckImplied. We are
1962	// still required to issue an ACK to our parent.
1963
1964	if (IOPMAckImplied == result)
1965	{
1966		IOService * parent;
1967		parent = (IOService *) whichParent->copyParentEntry(gIOPowerPlane);
1968		assert(parent);
1969		if ( parent )
1970		{
1971			parent->acknowledgePowerChange( whichParent );
1972			parent->release();
1973		}
1974	}
1975
1976	// If the parent registers its power driver late, then this is the
1977	// first opportunity to tell our parent about our desire.
1978
1979	if (!savedParentsKnowState && fParentsKnowState)
1980	{
1981		PM_LOG1("%s::powerDomainDidChangeTo parentsKnowState = true\n",
1982			getName());
1983		requestDomainPower( fDesiredPowerState );
1984	}
1985
1986exit_no_ack:
1987    // Drop the retain from notifyChild().
1988    if (whichParent) whichParent->release();
1989}
1990
1991//*********************************************************************************
1992// [private] setParentInfo
1993//
1994// Set our connection data for one specific parent, and then combine all the parent
1995// data together.
1996//*********************************************************************************
1997
1998void IOService::setParentInfo (
1999	IOPMPowerFlags		newPowerFlags,
2000	IOPowerConnection * whichParent,
2001	bool				knowsState )
2002{
2003    OSIterator *		iter;
2004    OSObject *			next;
2005    IOPowerConnection *	conn;
2006
2007	PM_ASSERT_IN_GATE();
2008
2009    // set our connection data
2010    whichParent->setParentCurrentPowerFlags(newPowerFlags);
2011    whichParent->setParentKnowsState(knowsState);
2012
2013    // recompute our parent info
2014    fParentsCurrentPowerFlags = 0;
2015    fParentsKnowState = true;
2016
2017    iter = getParentIterator(gIOPowerPlane);
2018    if ( iter )
2019    {
2020        while ( (next = iter->getNextObject()) )
2021        {
2022            if ( (conn = OSDynamicCast(IOPowerConnection, next)) )
2023            {
2024                fParentsKnowState &= conn->parentKnowsState();
2025                fParentsCurrentPowerFlags |= conn->parentCurrentPowerFlags();
2026            }
2027        }
2028        iter->release();
2029    }
2030}
2031
2032//******************************************************************************
2033// [private] trackSystemSleepPreventers
2034//******************************************************************************
2035
2036void IOService::trackSystemSleepPreventers(
2037    IOPMPowerStateIndex     oldPowerState,
2038    IOPMPowerStateIndex     newPowerState,
2039    IOPMPowerChangeFlags    changeFlags __unused )
2040{
2041    IOPMPowerFlags  oldCapability, newCapability;
2042
2043    oldCapability = fPowerStates[oldPowerState].capabilityFlags &
2044                    (kIOPMPreventIdleSleep | kIOPMPreventSystemSleep);
2045    newCapability = fPowerStates[newPowerState].capabilityFlags &
2046                    (kIOPMPreventIdleSleep | kIOPMPreventSystemSleep);
2047
2048    if (fHeadNoteChangeFlags & kIOPMInitialPowerChange)
2049        oldCapability = 0;
2050    if (oldCapability == newCapability)
2051        return;
2052
2053    if ((oldCapability ^ newCapability) & kIOPMPreventIdleSleep)
2054    {
2055#if SUPPORT_IDLE_CANCEL
2056        if ((oldCapability & kIOPMPreventIdleSleep) == 0)
2057        {
2058            IOPMRequest *   cancelRequest;
2059
2060            cancelRequest = acquirePMRequest( this, kIOPMRequestTypeIdleCancel );
2061            if (cancelRequest)
2062            {
2063                getPMRootDomain()->submitPMRequest( cancelRequest );
2064            }
2065        }
2066#endif
2067
2068        getPMRootDomain()->updatePreventIdleSleepList(this,
2069            ((oldCapability & kIOPMPreventIdleSleep) == 0));
2070    }
2071
2072    if ((oldCapability ^ newCapability) & kIOPMPreventSystemSleep)
2073    {
2074
2075        getPMRootDomain()->updatePreventSystemSleepList(this,
2076            ((oldCapability & kIOPMPreventSystemSleep) == 0));
2077    }
2078}
2079
2080//*********************************************************************************
2081// [public] requestPowerDomainState
2082//
2083// Called on a power parent when a child's power requirement changes.
2084//*********************************************************************************
2085
2086IOReturn IOService::requestPowerDomainState(
2087    IOPMPowerFlags      childRequestPowerFlags,
2088    IOPowerConnection * childConnection,
2089    unsigned long		specification )
2090{
2091    IOPMPowerStateIndex ps;
2092	IOPMPowerFlags		outputPowerFlags;
2093    IOService *         child;
2094	IOPMRequest *       subRequest;
2095    bool                adjustPower = false;
2096
2097    if (!initialized)
2098		return IOPMNotYetInitialized;
2099
2100	if (gIOPMWorkLoop->onThread() == false)
2101	{
2102		PM_LOG("%s::requestPowerDomainState\n", getName());
2103		return kIOReturnSuccess;
2104	}
2105
2106    OUR_PMLog(kPMLogRequestDomain, childRequestPowerFlags, specification);
2107
2108	if (!isChild(childConnection, gIOPowerPlane))
2109		return kIOReturnNotAttached;
2110
2111    if (!fControllingDriver || !fNumberOfPowerStates)
2112        return kIOReturnNotReady;
2113
2114	child = (IOService *) childConnection->getChildEntry(gIOPowerPlane);
2115	assert(child);
2116
2117    // Merge in the power flags contributed by this power parent
2118    // at its current or impending power state.
2119
2120    outputPowerFlags = fPowerStates[fCurrentPowerState].outputPowerFlags;
2121	if (fMachineState != kIOPM_Finished)
2122	{
2123		if (IS_POWER_DROP && !IS_ROOT_DOMAIN)
2124		{
2125			// Use the lower power state when dropping power.
2126			// Must be careful since a power drop can be canceled
2127			// from the following states:
2128			// - kIOPM_OurChangeTellClientsPowerDown
2129			// - kIOPM_OurChangeTellPriorityClientsPowerDown
2130			//
2131			// The child must not wait for this parent to raise power
2132			// if the power drop was cancelled. The solution is to cancel
2133			// the power drop if possible, then schedule an adjustment to
2134			// re-evaluate the parent's power state.
2135			//
2136			// Root domain is excluded to avoid idle sleep issues. And permit
2137			// root domain children to pop up when system is going to sleep.
2138
2139			if ((fMachineState == kIOPM_OurChangeTellClientsPowerDown) ||
2140				(fMachineState == kIOPM_OurChangeTellPriorityClientsPowerDown))
2141			{
2142				fDoNotPowerDown = true;     // cancel power drop
2143				adjustPower     = true;     // schedule an adjustment
2144				PM_LOG1("%s: power drop cancelled in state %u by %s\n",
2145					getName(), fMachineState, child->getName());
2146			}
2147			else
2148			{
2149				// Beyond cancellation point, report the impending state.
2150				outputPowerFlags =
2151					fPowerStates[fHeadNotePowerState].outputPowerFlags;
2152			}
2153		}
2154		else if (IS_POWER_RISE)
2155		{
2156			// When raising power, must report the output power flags from
2157			// child's perspective. A child power request may arrive while
2158			// parent is transitioning upwards. If a request arrives after
2159			// setParentInfo() has already recorded the output power flags
2160			// for the next power state, then using the power supplied by
2161			// fCurrentPowerState is incorrect, and might cause the child
2162			// to wait when it should not.
2163
2164			outputPowerFlags = childConnection->parentCurrentPowerFlags();
2165		}
2166    }
2167    child->fHeadNoteDomainTargetFlags |= outputPowerFlags;
2168
2169    // Map child's requested power flags to one of our power state.
2170
2171    for (ps = 0; ps < fNumberOfPowerStates; ps++)
2172    {
2173        if ((fPowerStates[ps].outputPowerFlags & childRequestPowerFlags) ==
2174            (fOutputPowerCharacterFlags & childRequestPowerFlags))
2175            break;
2176    }
2177    if (ps >= fNumberOfPowerStates)
2178    {
2179        ps = 0;  // should never happen
2180    }
2181
2182    // Conditions that warrants a power adjustment on this parent.
2183    // Adjust power will also propagate any changes to the child's
2184    // prevent idle/sleep flags towards the root domain.
2185
2186    if (!childConnection->childHasRequestedPower() ||
2187        (ps != childConnection->getDesiredDomainState()))
2188        adjustPower = true;
2189
2190#if ENABLE_DEBUG_LOGS
2191    if (adjustPower)
2192    {
2193        PM_LOG("requestPowerDomainState[%s]: %s, init %d, %u->%u\n",
2194            getName(), child->getName(),
2195            !childConnection->childHasRequestedPower(),
2196            (uint32_t) childConnection->getDesiredDomainState(),
2197            (uint32_t) ps);
2198    }
2199#endif
2200
2201	// Record the child's desires on the connection.
2202	childConnection->setChildHasRequestedPower();
2203	childConnection->setDesiredDomainState( ps );
2204
2205	// Schedule a request to re-evaluate all children desires and
2206	// adjust power state. Submit a request if one wasn't pending,
2207	// or if the current request is part of a call tree.
2208
2209    if (adjustPower && !fDeviceOverrideEnabled &&
2210        (!fAdjustPowerScheduled || gIOPMRequest->getRootRequest()))
2211    {
2212		subRequest = acquirePMRequest(
2213            this, kIOPMRequestTypeAdjustPowerState, gIOPMRequest );
2214		if (subRequest)
2215		{
2216			submitPMRequest( subRequest );
2217			fAdjustPowerScheduled = true;
2218		}
2219    }
2220
2221    return kIOReturnSuccess;
2222}
2223
2224//*********************************************************************************
2225// [public] temporaryPowerClampOn
2226//
2227// A power domain wants to clamp its power on till it has children which
2228// will thendetermine the power domain state.
2229//
2230// We enter the highest state until addPowerChild is called.
2231//*********************************************************************************
2232
2233IOReturn IOService::temporaryPowerClampOn ( void )
2234{
2235    return requestPowerState( gIOPMPowerClientChildProxy, kIOPMPowerStateMax );
2236}
2237
2238//*********************************************************************************
2239// [public] makeUsable
2240//
2241// Some client of our device is asking that we become usable.  Although
2242// this has not come from a subclassed device object, treat it exactly
2243// as if it had.  In this way, subsequent requests for lower power from
2244// a subclassed device object will pre-empt this request.
2245//
2246// We treat this as a subclass object request to switch to the
2247// highest power state.
2248//*********************************************************************************
2249
2250IOReturn IOService::makeUsable ( void )
2251{
2252    OUR_PMLog(kPMLogMakeUsable, 0, 0);
2253    return requestPowerState( gIOPMPowerClientDevice, kIOPMPowerStateMax );
2254}
2255
2256//*********************************************************************************
2257// [public] currentCapability
2258//*********************************************************************************
2259
2260IOPMPowerFlags IOService::currentCapability ( void )
2261{
2262	if (!initialized)
2263		return IOPMNotPowerManaged;
2264
2265    return fCurrentCapabilityFlags;
2266}
2267
2268//*********************************************************************************
2269// [public] changePowerStateTo
2270//
2271// Called by our power-controlling driver to change power state. The new desired
2272// power state is computed and compared against the current power state. If those
2273// power states differ, then a power state change is initiated.
2274//*********************************************************************************
2275
2276IOReturn IOService::changePowerStateTo ( unsigned long ordinal )
2277{
2278    OUR_PMLog(kPMLogChangeStateTo, ordinal, 0);
2279    return requestPowerState( gIOPMPowerClientDriver, ordinal );
2280}
2281
2282//*********************************************************************************
2283// [protected] changePowerStateToPriv
2284//
2285// Called by our driver subclass to change power state. The new desired power
2286// state is computed and compared against the current power state. If those
2287// power states differ, then a power state change is initiated.
2288//*********************************************************************************
2289
2290IOReturn IOService::changePowerStateToPriv ( unsigned long ordinal )
2291{
2292    OUR_PMLog(kPMLogChangeStateToPriv, ordinal, 0);
2293    return requestPowerState( gIOPMPowerClientDevice, ordinal );
2294}
2295
2296//*********************************************************************************
2297// [protected] changePowerStateWithOverrideTo
2298//
2299// Called by our driver subclass to change power state. The new desired power
2300// state is computed and compared against the current power state. If those
2301// power states differ, then a power state change is initiated.
2302// Override enforced - Children and Driver desires are ignored.
2303//*********************************************************************************
2304
2305IOReturn IOService::changePowerStateWithOverrideTo ( unsigned long ordinal )
2306{
2307	IOPMRequest * request;
2308
2309	if (!initialized)
2310		return kIOPMNotYetInitialized;
2311
2312    OUR_PMLog(kPMLogChangeStateToPriv, ordinal, 0);
2313
2314	request = acquirePMRequest( this, kIOPMRequestTypeRequestPowerStateOverride );
2315	if (!request)
2316		return kIOReturnNoMemory;
2317
2318    gIOPMPowerClientDevice->retain();
2319    request->fArg0 = (void *) ordinal;
2320    request->fArg1 = (void *) gIOPMPowerClientDevice;
2321    request->fArg2 = 0;
2322#if NOT_READY
2323    if (action)
2324        request->installCompletionAction( action, target, param );
2325#endif
2326
2327	// Prevent needless downwards power transitions by clamping power
2328	// until the scheduled request is executed.
2329
2330	if (gIOPMWorkLoop->inGate() && (ordinal < fNumberOfPowerStates))
2331	{
2332		fTempClampPowerState = max(fTempClampPowerState, ordinal);
2333		fTempClampCount++;
2334		fOverrideMaxPowerState = ordinal;
2335		request->fArg2 = (void *) (uintptr_t) true;
2336	}
2337
2338	submitPMRequest( request );
2339    return IOPMNoErr;
2340}
2341
2342//*********************************************************************************
2343// [private] requestPowerState
2344//*********************************************************************************
2345
2346IOReturn IOService::requestPowerState (
2347    const OSSymbol *      client,
2348    uint32_t              state )
2349{
2350	IOPMRequest * request;
2351
2352    if (!client)
2353        return kIOReturnBadArgument;
2354	if (!initialized)
2355		return kIOPMNotYetInitialized;
2356
2357	request = acquirePMRequest( this, kIOPMRequestTypeRequestPowerState );
2358	if (!request)
2359		return kIOReturnNoMemory;
2360
2361    client->retain();
2362    request->fArg0 = (void *) state;
2363    request->fArg1 = (void *) client;
2364    request->fArg2 = 0;
2365#if NOT_READY
2366    if (action)
2367        request->installCompletionAction( action, target, param );
2368#endif
2369
2370	// Prevent needless downwards power transitions by clamping power
2371	// until the scheduled request is executed.
2372
2373	if (gIOPMWorkLoop->inGate() && (state < fNumberOfPowerStates))
2374	{
2375		fTempClampPowerState = max(fTempClampPowerState, state);
2376		fTempClampCount++;
2377		request->fArg2 = (void *) (uintptr_t) true;
2378	}
2379
2380	submitPMRequest( request );
2381    return IOPMNoErr;
2382}
2383
2384//*********************************************************************************
2385// [private] handleRequestPowerState
2386//*********************************************************************************
2387
2388void IOService::handleRequestPowerState ( IOPMRequest * request )
2389{
2390    const OSSymbol * client = (const OSSymbol *)    request->fArg1;
2391    uint32_t         state  = (uint32_t)(uintptr_t) request->fArg0;
2392
2393	PM_ASSERT_IN_GATE();
2394	if (request->fArg2)
2395	{
2396		assert(fTempClampCount != 0);
2397		if (fTempClampCount)  fTempClampCount--;
2398		if (!fTempClampCount) fTempClampPowerState = 0;
2399	}
2400
2401	if (fNumberOfPowerStates && (state >= fNumberOfPowerStates))
2402		state = fNumberOfPowerStates - 1;
2403
2404    // The power suppression due to changePowerStateWithOverrideTo() expires
2405    // upon the next "device" power request - changePowerStateToPriv().
2406
2407    if ((getPMRequestType() != kIOPMRequestTypeRequestPowerStateOverride) &&
2408        (client == gIOPMPowerClientDevice))
2409        fOverrideMaxPowerState = kIOPMPowerStateMax;
2410
2411    if ((state == 0) &&
2412		(client != gIOPMPowerClientDevice) &&
2413		(client != gIOPMPowerClientDriver) &&
2414		(client != gIOPMPowerClientChildProxy))
2415		removePowerClient(client);
2416	else
2417		updatePowerClient(client, state);
2418
2419	adjustPowerState();
2420    client->release();
2421}
2422
2423//*********************************************************************************
2424// [private] Helper functions to update/remove power clients.
2425//*********************************************************************************
2426
2427void IOService::updatePowerClient( const OSSymbol * client, uint32_t powerState )
2428{
2429    if (!fPowerClients)
2430        fPowerClients = OSDictionary::withCapacity(4);
2431    if (fPowerClients && client)
2432    {
2433        OSNumber * num = (OSNumber *) fPowerClients->getObject(client);
2434        if (num)
2435            num->setValue(powerState);
2436        else
2437        {
2438            num = OSNumber::withNumber(powerState, 32);
2439            if (num)
2440            {
2441                fPowerClients->setObject(client, num);
2442                num->release();
2443            }
2444        }
2445    }
2446}
2447
2448void IOService::removePowerClient( const OSSymbol * client )
2449{
2450    if (fPowerClients && client)
2451        fPowerClients->removeObject(client);
2452}
2453
2454uint32_t IOService::getPowerStateForClient( const OSSymbol * client )
2455{
2456    uint32_t powerState = 0;
2457
2458    if (fPowerClients && client)
2459    {
2460        OSNumber * num = (OSNumber *) fPowerClients->getObject(client);
2461        if (num) powerState = num->unsigned32BitValue();
2462    }
2463    return powerState;
2464}
2465
2466//*********************************************************************************
2467// [protected] powerOverrideOnPriv
2468//*********************************************************************************
2469
2470IOReturn IOService::powerOverrideOnPriv ( void )
2471{
2472	IOPMRequest * request;
2473
2474    if (!initialized)
2475		return IOPMNotYetInitialized;
2476
2477	if (gIOPMWorkLoop->inGate())
2478	{
2479		fDeviceOverrideEnabled = true;
2480		return IOPMNoErr;
2481	}
2482
2483	request = acquirePMRequest( this, kIOPMRequestTypePowerOverrideOnPriv );
2484	if (!request)
2485		return kIOReturnNoMemory;
2486
2487	submitPMRequest( request );
2488    return IOPMNoErr;
2489}
2490
2491//*********************************************************************************
2492// [protected] powerOverrideOffPriv
2493//*********************************************************************************
2494
2495IOReturn IOService::powerOverrideOffPriv ( void )
2496{
2497	IOPMRequest * request;
2498
2499    if (!initialized)
2500		return IOPMNotYetInitialized;
2501
2502	if (gIOPMWorkLoop->inGate())
2503	{
2504		fDeviceOverrideEnabled = false;
2505		return IOPMNoErr;
2506	}
2507
2508	request = acquirePMRequest( this, kIOPMRequestTypePowerOverrideOffPriv );
2509	if (!request)
2510		return kIOReturnNoMemory;
2511
2512	submitPMRequest( request );
2513    return IOPMNoErr;
2514}
2515
2516//*********************************************************************************
2517// [private] handlePowerOverrideChanged
2518//*********************************************************************************
2519
2520void IOService::handlePowerOverrideChanged ( IOPMRequest * request )
2521{
2522	PM_ASSERT_IN_GATE();
2523	if (request->getType() == kIOPMRequestTypePowerOverrideOnPriv)
2524	{
2525		OUR_PMLog(kPMLogOverrideOn, 0, 0);
2526		fDeviceOverrideEnabled = true;
2527    }
2528	else
2529	{
2530		OUR_PMLog(kPMLogOverrideOff, 0, 0);
2531		fDeviceOverrideEnabled = false;
2532	}
2533
2534	adjustPowerState();
2535}
2536
2537//*********************************************************************************
2538// [private] computeDesiredState
2539//*********************************************************************************
2540
2541void IOService::computeDesiredState ( unsigned long localClamp )
2542{
2543    OSIterator *		iter;
2544    OSObject *			next;
2545    IOPowerConnection *	connection;
2546	uint32_t            desiredState  = 0;
2547    uint32_t            newPowerState = 0;
2548    bool                hasChildren   = false;
2549
2550	// Desired power state is always 0 without a controlling driver.
2551
2552	if (!fNumberOfPowerStates)
2553	{
2554        fDesiredPowerState = 0;
2555		//PM_LOG("%s::%s no controlling driver\n", getName(), __FUNCTION__);
2556		return;
2557	}
2558
2559    // Examine the children's desired power state.
2560
2561    iter = getChildIterator(gIOPowerPlane);
2562    if (iter)
2563    {
2564        while ((next = iter->getNextObject()))
2565        {
2566            if ((connection = OSDynamicCast(IOPowerConnection, next)))
2567            {
2568                if (connection->getReadyFlag() == false)
2569                {
2570                    PM_LOG3("[%s] %s: connection not ready\n",
2571                        getName(), __FUNCTION__);
2572                    continue;
2573                }
2574                if (connection->childHasRequestedPower())
2575                    hasChildren = true;
2576                if (connection->getDesiredDomainState() > desiredState)
2577                    desiredState = connection->getDesiredDomainState();
2578            }
2579        }
2580        iter->release();
2581    }
2582    if (hasChildren)
2583        updatePowerClient(gIOPMPowerClientChildren, desiredState);
2584    else
2585        removePowerClient(gIOPMPowerClientChildren);
2586
2587    // Iterate through all power clients to determine the min power state.
2588
2589    iter = OSCollectionIterator::withCollection(fPowerClients);
2590    if (iter)
2591    {
2592        const OSSymbol * client;
2593        while ((client = (const OSSymbol *) iter->getNextObject()))
2594        {
2595			// Ignore child and driver when override is in effect.
2596            if ((fDeviceOverrideEnabled ||
2597                (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride)) &&
2598                ((client == gIOPMPowerClientChildren) ||
2599                 (client == gIOPMPowerClientDriver)))
2600                continue;
2601
2602			// Ignore child proxy when children are present.
2603            if (hasChildren && (client == gIOPMPowerClientChildProxy))
2604                continue;
2605
2606            if (client == gIOPMPowerClientAdvisoryTickle &&
2607                !gIOPMAdvisoryTickleEnabled)
2608                continue;
2609
2610            desiredState = getPowerStateForClient(client);
2611            assert(desiredState < fNumberOfPowerStates);
2612			PM_LOG1("  %u %s\n",
2613				desiredState, client->getCStringNoCopy());
2614
2615            newPowerState = max(newPowerState, desiredState);
2616
2617            if (client == gIOPMPowerClientDevice)
2618                fDeviceDesire = desiredState;
2619        }
2620        iter->release();
2621    }
2622
2623    // Factor in the temporary power desires.
2624
2625    newPowerState = max(newPowerState, localClamp);
2626    newPowerState = max(newPowerState, fTempClampPowerState);
2627
2628    // Limit check against max power override.
2629
2630    newPowerState = min(newPowerState, fOverrideMaxPowerState);
2631
2632    // Limit check against number of power states.
2633
2634    if (newPowerState >= fNumberOfPowerStates)
2635        newPowerState = fNumberOfPowerStates - 1;
2636
2637    fDesiredPowerState = newPowerState;
2638
2639    PM_LOG1("  temp %u, clamp %u, current %u, new %u\n",
2640        (uint32_t) localClamp, (uint32_t) fTempClampPowerState,
2641		(uint32_t) fCurrentPowerState, newPowerState);
2642
2643    // Restart idle timer if stopped and device desire has increased.
2644    // Or if advisory desire exists.
2645
2646    if (fIdleTimerStopped)
2647    {
2648        if (fDeviceDesire > 0)
2649        {
2650            fIdleTimerStopped = false;
2651            fActivityTickleCount = 0;
2652            clock_get_uptime(&fIdleTimerStartTime);
2653            start_PM_idle_timer();
2654        }
2655        else if (fHasAdvisoryDesire)
2656        {
2657            fIdleTimerStopped = false;
2658            start_PM_idle_timer();
2659        }
2660    }
2661
2662    // Invalidate cached tickle power state when desires change, and not
2663    // due to a tickle request.  This invalidation must occur before the
2664    // power state change to minimize races.  We want to err on the side
2665    // of servicing more activity tickles rather than dropping one when
2666    // the device is in a low power state.
2667
2668    if ((getPMRequestType() != kIOPMRequestTypeActivityTickle) &&
2669        (fActivityTicklePowerState != kInvalidTicklePowerState))
2670    {
2671        IOLockLock(fActivityLock);
2672        fActivityTicklePowerState = kInvalidTicklePowerState;
2673        IOLockUnlock(fActivityLock);
2674    }
2675}
2676
2677//*********************************************************************************
2678// [public] currentPowerConsumption
2679//
2680//*********************************************************************************
2681
2682unsigned long IOService::currentPowerConsumption ( void )
2683{
2684    if (!initialized)
2685        return kIOPMUnknown;
2686
2687    return fCurrentPowerConsumption;
2688}
2689
2690//*********************************************************************************
2691// [deprecated] getPMworkloop
2692//*********************************************************************************
2693
2694IOWorkLoop * IOService::getPMworkloop ( void )
2695{
2696	return gIOPMWorkLoop;
2697}
2698
2699#if NOT_YET
2700
2701//*********************************************************************************
2702// Power Parent/Children Applier
2703//*********************************************************************************
2704
2705static void
2706applyToPowerChildren(
2707    IOService *               service,
2708    IOServiceApplierFunction  applier,
2709    void *                    context,
2710    IOOptionBits              options )
2711{
2712	PM_ASSERT_IN_GATE();
2713
2714    IORegistryEntry *       entry;
2715    IORegistryIterator *    iter;
2716    IOPowerConnection *     connection;
2717    IOService *             child;
2718
2719    iter = IORegistryIterator::iterateOver(service, gIOPowerPlane, options);
2720    if (iter)
2721    {
2722        while ((entry = iter->getNextObject()))
2723        {
2724            // Get child of IOPowerConnection objects
2725            if ((connection = OSDynamicCast(IOPowerConnection, entry)))
2726            {
2727                child = (IOService *) connection->copyChildEntry(gIOPowerPlane);
2728                if (child)
2729                {
2730                    (*applier)(child, context);
2731                    child->release();
2732                }
2733            }
2734        }
2735        iter->release();
2736    }
2737}
2738
2739static void
2740applyToPowerParent(
2741    IOService *               service,
2742    IOServiceApplierFunction  applier,
2743    void *                    context,
2744    IOOptionBits              options )
2745{
2746	PM_ASSERT_IN_GATE();
2747
2748    IORegistryEntry *       entry;
2749    IORegistryIterator *    iter;
2750    IOPowerConnection *     connection;
2751    IOService *             parent;
2752
2753    iter = IORegistryIterator::iterateOver(service, gIOPowerPlane,
2754            options | kIORegistryIterateParents);
2755    if (iter)
2756    {
2757        while ((entry = iter->getNextObject()))
2758        {
2759            // Get child of IOPowerConnection objects
2760            if ((connection = OSDynamicCast(IOPowerConnection, entry)))
2761            {
2762                parent = (IOService *) connection->copyParentEntry(gIOPowerPlane);
2763                if (parent)
2764                {
2765                    (*applier)(parent, context);
2766                    parent->release();
2767                }
2768            }
2769        }
2770        iter->release();
2771    }
2772}
2773
2774#endif /* NOT_YET */
2775
2776// MARK: -
2777// MARK: Activity Tickle & Idle Timer
2778
2779void IOService::setAdvisoryTickleEnable( bool enable )
2780{
2781    gIOPMAdvisoryTickleEnabled = enable;
2782}
2783
2784//*********************************************************************************
2785// [public] activityTickle
2786//
2787// The tickle with parameter kIOPMSuperclassPolicy1 causes the activity
2788// flag to be set, and the device state checked.  If the device has been
2789// powered down, it is powered up again.
2790// The tickle with parameter kIOPMSubclassPolicy is ignored here and
2791// should be intercepted by a subclass.
2792//*********************************************************************************
2793
2794bool IOService::activityTickle ( unsigned long type, unsigned long stateNumber )
2795{
2796	IOPMRequest *	request;
2797	bool			noPowerChange = true;
2798
2799    if (!initialized)
2800        return true;    // no power change
2801
2802    if ((type == kIOPMSuperclassPolicy1) && stateNumber)
2803	{
2804        IOLockLock(fActivityLock);
2805
2806		// Record device activity for the idle timer handler.
2807
2808        fDeviceWasActive = true;
2809        fActivityTickleCount++;
2810        clock_get_uptime(&fDeviceActiveTimestamp);
2811
2812        PM_ACTION_0(actionActivityTickle);
2813
2814		// Record the last tickle power state.
2815		// This helps to filter out redundant tickles as
2816		// this function may be called from the data path.
2817
2818		if (fActivityTicklePowerState < (int)stateNumber)
2819		{
2820			fActivityTicklePowerState = stateNumber;
2821			noPowerChange = false;
2822
2823			request = acquirePMRequest( this, kIOPMRequestTypeActivityTickle );
2824			if (request)
2825			{
2826				request->fArg0 = (void *) stateNumber;  // power state
2827				request->fArg1 = (void *) true;         // power rise
2828                request->fArg2 = (void *) false;        // regular tickle
2829				submitPMRequest(request);
2830			}
2831		}
2832
2833		IOLockUnlock(fActivityLock);
2834	}
2835
2836    else if ((type == kIOPMActivityTickleTypeAdvisory) &&
2837             ((stateNumber = fDeviceUsablePowerState)))
2838    {
2839        IOLockLock(fActivityLock);
2840
2841        fAdvisoryTickled = true;
2842
2843		if (fAdvisoryTicklePowerState != (int)stateNumber)
2844		{
2845			fAdvisoryTicklePowerState = stateNumber;
2846			noPowerChange = false;
2847
2848			request = acquirePMRequest( this, kIOPMRequestTypeActivityTickle );
2849			if (request)
2850			{
2851				request->fArg0 = (void *) stateNumber;  // power state
2852				request->fArg1 = (void *) true;         // power rise
2853                request->fArg2 = (void *) true;         // advisory tickle
2854				submitPMRequest(request);
2855			}
2856		}
2857
2858		IOLockUnlock(fActivityLock);
2859    }
2860
2861	// Returns false if the activityTickle might cause a transition to a
2862	// higher powered state, true otherwise.
2863
2864    return noPowerChange;
2865}
2866
2867//*********************************************************************************
2868// [private] handleActivityTickle
2869//*********************************************************************************
2870
2871void IOService::handleActivityTickle ( IOPMRequest * request )
2872{
2873	uint32_t ticklePowerState   = (uint32_t)(uintptr_t) request->fArg0;
2874    bool     deviceWasActive    = (request->fArg1 == (void *) true);
2875    bool     isRegularTickle    = (request->fArg2 == (void *) false);
2876    bool     adjustPower        = false;
2877
2878	PM_ASSERT_IN_GATE();
2879    if (isRegularTickle)
2880    {
2881        if (deviceWasActive)
2882        {
2883            if ((ticklePowerState > fDeviceDesire) &&
2884                (ticklePowerState < fNumberOfPowerStates))
2885            {
2886                fIdleTimerMinPowerState = ticklePowerState;
2887                updatePowerClient(gIOPMPowerClientDevice, ticklePowerState);
2888                adjustPower = true;
2889            }
2890        }
2891        else if (fDeviceDesire > fIdleTimerMinPowerState)
2892        {
2893            // Power drop due to idle timer expiration.
2894            // Do not allow idle timer to reduce power below tickle power.
2895            // This prevents the idle timer from decreasing the device desire
2896            // to zero and cancelling the effect of a pre-sleep tickle when
2897            // system wakes up to doze state, while the device is unable to
2898            // raise its power state to satisfy the tickle.
2899
2900            ticklePowerState = fDeviceDesire - 1;
2901            updatePowerClient(gIOPMPowerClientDevice, ticklePowerState);
2902            adjustPower = true;
2903        }
2904    }
2905    else    // advisory tickle
2906    {
2907        if (deviceWasActive)
2908        {
2909            if ((ticklePowerState == fDeviceUsablePowerState) &&
2910                (ticklePowerState < fNumberOfPowerStates))
2911            {
2912                updatePowerClient(gIOPMPowerClientAdvisoryTickle, ticklePowerState);
2913                fHasAdvisoryDesire = true;
2914                fAdvisoryTickleUsed = true;
2915                adjustPower = true;
2916            }
2917            else
2918            {
2919                IOLockLock(fActivityLock);
2920                fAdvisoryTicklePowerState = kInvalidTicklePowerState;
2921                IOLockUnlock(fActivityLock);
2922            }
2923        }
2924        else if (fHasAdvisoryDesire)
2925        {
2926            removePowerClient(gIOPMPowerClientAdvisoryTickle);
2927            fHasAdvisoryDesire = false;
2928            adjustPower = true;
2929        }
2930    }
2931
2932	if (adjustPower)
2933	{
2934		adjustPowerState();
2935	}
2936}
2937
2938//******************************************************************************
2939// [public] setIdleTimerPeriod
2940//
2941// A subclass policy-maker is using our standard idleness detection service.
2942// Start the idle timer. Period is in seconds.
2943//******************************************************************************
2944
2945IOReturn IOService::setIdleTimerPeriod ( unsigned long period )
2946{
2947    if (!initialized)
2948		return IOPMNotYetInitialized;
2949
2950    OUR_PMLog(kPMLogSetIdleTimerPeriod, period, fIdleTimerPeriod);
2951
2952    IOPMRequest * request =
2953        acquirePMRequest( this, kIOPMRequestTypeSetIdleTimerPeriod );
2954    if (!request)
2955        return kIOReturnNoMemory;
2956
2957    request->fArg0 = (void *) period;
2958    submitPMRequest( request );
2959
2960    return kIOReturnSuccess;
2961}
2962
2963IOReturn IOService::setIgnoreIdleTimer( bool ignore )
2964{
2965    if (!initialized)
2966		return IOPMNotYetInitialized;
2967
2968    OUR_PMLog(kIOPMRequestTypeIgnoreIdleTimer, ignore, 0);
2969
2970    IOPMRequest * request =
2971        acquirePMRequest( this, kIOPMRequestTypeIgnoreIdleTimer );
2972    if (!request)
2973        return kIOReturnNoMemory;
2974
2975    request->fArg0 = (void *) ignore;
2976    submitPMRequest( request );
2977
2978    return kIOReturnSuccess;
2979}
2980
2981//******************************************************************************
2982// [public] nextIdleTimeout
2983//
2984// Returns how many "seconds from now" the device should idle into its
2985// next lowest power state.
2986//******************************************************************************
2987
2988SInt32 IOService::nextIdleTimeout(
2989    AbsoluteTime currentTime,
2990    AbsoluteTime lastActivity,
2991    unsigned int powerState)
2992{
2993    AbsoluteTime        delta;
2994    UInt64              delta_ns;
2995    SInt32              delta_secs;
2996    SInt32              delay_secs;
2997
2998    // Calculate time difference using funky macro from clock.h.
2999    delta = currentTime;
3000    SUB_ABSOLUTETIME(&delta, &lastActivity);
3001
3002    // Figure it in seconds.
3003    absolutetime_to_nanoseconds(delta, &delta_ns);
3004    delta_secs = (SInt32)(delta_ns / NSEC_PER_SEC);
3005
3006    // Be paranoid about delta somehow exceeding timer period.
3007    if (delta_secs < (int) fIdleTimerPeriod)
3008        delay_secs = (int) fIdleTimerPeriod - delta_secs;
3009    else
3010        delay_secs = (int) fIdleTimerPeriod;
3011
3012    return (SInt32)delay_secs;
3013}
3014
3015//*********************************************************************************
3016// [public] start_PM_idle_timer
3017//*********************************************************************************
3018
3019void IOService::start_PM_idle_timer ( void )
3020{
3021    static const int    maxTimeout = 100000;
3022    static const int    minTimeout = 1;
3023    AbsoluteTime        uptime, deadline;
3024    SInt32              idle_in = 0;
3025	boolean_t           pending;
3026
3027	if (!initialized || !fIdleTimerPeriod)
3028		return;
3029
3030    IOLockLock(fActivityLock);
3031
3032    clock_get_uptime(&uptime);
3033
3034    // Subclasses may modify idle sleep algorithm
3035    idle_in = nextIdleTimeout(uptime, fDeviceActiveTimestamp, fCurrentPowerState);
3036
3037    // Check for out-of range responses
3038    if (idle_in > maxTimeout)
3039    {
3040        // use standard implementation
3041        idle_in = IOService::nextIdleTimeout(uptime,
3042                        fDeviceActiveTimestamp,
3043                        fCurrentPowerState);
3044    } else if (idle_in < minTimeout) {
3045        idle_in = fIdleTimerPeriod;
3046    }
3047
3048    IOLockUnlock(fActivityLock);
3049
3050    retain();
3051    clock_interval_to_absolutetime_interval(idle_in, kSecondScale, &deadline);
3052    ADD_ABSOLUTETIME(&deadline, &uptime);
3053    pending = thread_call_enter_delayed(fIdleTimer, deadline);
3054    if (pending) release();
3055}
3056
3057//*********************************************************************************
3058// idle_timer_expired
3059//*********************************************************************************
3060
3061static void
3062idle_timer_expired (
3063    thread_call_param_t arg0, thread_call_param_t arg1 )
3064{
3065	IOService * me = (IOService *) arg0;
3066
3067	if (gIOPMWorkLoop)
3068		gIOPMWorkLoop->runAction(
3069            OSMemberFunctionCast(IOWorkLoop::Action, me,
3070                &IOService::idleTimerExpired),
3071            me);
3072
3073	me->release();
3074}
3075
3076//*********************************************************************************
3077// [private] idleTimerExpired
3078//
3079// The idle timer has expired. If there has been activity since the last
3080// expiration, just restart the timer and return.  If there has not been
3081// activity, switch to the next lower power state and restart the timer.
3082//*********************************************************************************
3083
3084void IOService::idleTimerExpired( void )
3085{
3086	IOPMRequest *	request;
3087	bool			restartTimer = true;
3088
3089    if ( !initialized || !fIdleTimerPeriod || fLockedFlags.PMStop )
3090        return;
3091
3092	IOLockLock(fActivityLock);
3093
3094	// Check for device activity (tickles) over last timer period.
3095
3096	if (fDeviceWasActive)
3097	{
3098		// Device was active - do not drop power, restart timer.
3099		fDeviceWasActive = false;
3100	}
3101	else if (!fIdleTimerIgnored)
3102	{
3103		// No device activity - drop power state by one level.
3104		// Decrement the cached tickle power state when possible.
3105		// This value may be (-1) before activityTickle() is called,
3106		// but the power drop request must be issued regardless.
3107
3108		if (fActivityTicklePowerState > 0)
3109			fActivityTicklePowerState--;
3110
3111		request = acquirePMRequest( this, kIOPMRequestTypeActivityTickle );
3112		if (request)
3113		{
3114			request->fArg0 = (void *) 0;		// power state (irrelevant)
3115			request->fArg1 = (void *) false;	// timer expiration (not tickle)
3116            request->fArg2 = (void *) false;    // regular tickle
3117			submitPMRequest( request );
3118
3119			// Do not restart timer until after the tickle request has been
3120			// processed.
3121
3122			restartTimer = false;
3123		}
3124    }
3125
3126    if (fAdvisoryTickled)
3127    {
3128        fAdvisoryTickled = false;
3129    }
3130    else if (fHasAdvisoryDesire)
3131    {
3132        // Want new tickles to turn into pm request after we drop the lock
3133        fAdvisoryTicklePowerState = kInvalidTicklePowerState;
3134
3135		request = acquirePMRequest( this, kIOPMRequestTypeActivityTickle );
3136		if (request)
3137		{
3138			request->fArg0 = (void *) 0;		// power state (irrelevant)
3139			request->fArg1 = (void *) false;	// timer expiration (not tickle)
3140            request->fArg2 = (void *) true;     // advisory tickle
3141			submitPMRequest( request );
3142
3143			// Do not restart timer until after the tickle request has been
3144			// processed.
3145
3146			restartTimer = false;
3147		}
3148    }
3149
3150	IOLockUnlock(fActivityLock);
3151
3152	if (restartTimer)
3153		start_PM_idle_timer();
3154}
3155
3156#ifndef __LP64__
3157//*********************************************************************************
3158// [deprecated] PM_idle_timer_expiration
3159//*********************************************************************************
3160
3161void IOService::PM_idle_timer_expiration ( void )
3162{
3163}
3164
3165//*********************************************************************************
3166// [deprecated] command_received
3167//*********************************************************************************
3168
3169void IOService::command_received ( void *statePtr , void *, void * , void * )
3170{
3171}
3172#endif /* !__LP64__ */
3173
3174//*********************************************************************************
3175// [public] setAggressiveness
3176//
3177// Pass on the input parameters to all power domain children. All those which are
3178// power domains will pass it on to their children, etc.
3179//*********************************************************************************
3180
3181IOReturn IOService::setAggressiveness ( unsigned long type, unsigned long newLevel )
3182{
3183    return kIOReturnSuccess;
3184}
3185
3186//*********************************************************************************
3187// [public] getAggressiveness
3188//
3189// Called by the user client.
3190//*********************************************************************************
3191
3192IOReturn IOService::getAggressiveness ( unsigned long type, unsigned long * currentLevel )
3193{
3194    IOPMrootDomain *    rootDomain = getPMRootDomain();
3195
3196    if (!rootDomain)
3197        return kIOReturnNotReady;
3198
3199    return rootDomain->getAggressiveness( type, currentLevel );
3200}
3201
3202//*********************************************************************************
3203// [public] getPowerState
3204//
3205//*********************************************************************************
3206
3207UInt32 IOService::getPowerState ( void )
3208{
3209    if (!initialized)
3210        return 0;
3211
3212    return fCurrentPowerState;
3213}
3214
3215#ifndef __LP64__
3216//*********************************************************************************
3217// [deprecated] systemWake
3218//
3219// Pass this to all power domain children. All those which are
3220// power domains will pass it on to their children, etc.
3221//*********************************************************************************
3222
3223IOReturn IOService::systemWake ( void )
3224{
3225    OSIterator *		iter;
3226    OSObject *			next;
3227    IOPowerConnection *	connection;
3228    IOService *			theChild;
3229
3230    iter = getChildIterator(gIOPowerPlane);
3231    if ( iter )
3232    {
3233        while ( (next = iter->getNextObject()) )
3234        {
3235            if ( (connection = OSDynamicCast(IOPowerConnection, next)) )
3236            {
3237				if (connection->getReadyFlag() == false)
3238				{
3239					PM_LOG3("[%s] %s: connection not ready\n",
3240						getName(), __FUNCTION__);
3241					continue;
3242				}
3243
3244                theChild = (IOService *)connection->copyChildEntry(gIOPowerPlane);
3245                if ( theChild )
3246                {
3247                	theChild->systemWake();
3248                    theChild->release();
3249                }
3250            }
3251        }
3252        iter->release();
3253    }
3254
3255    if ( fControllingDriver != NULL )
3256    {
3257        if ( fControllingDriver->didYouWakeSystem() )
3258        {
3259            makeUsable();
3260        }
3261    }
3262
3263    return IOPMNoErr;
3264}
3265
3266//*********************************************************************************
3267// [deprecated] temperatureCriticalForZone
3268//*********************************************************************************
3269
3270IOReturn IOService::temperatureCriticalForZone ( IOService * whichZone )
3271{
3272    IOService *	theParent;
3273    IOService *	theNub;
3274
3275    OUR_PMLog(kPMLogCriticalTemp, 0, 0);
3276
3277    if ( inPlane(gIOPowerPlane) && !IS_PM_ROOT )
3278    {
3279        theNub = (IOService *)copyParentEntry(gIOPowerPlane);
3280        if ( theNub )
3281        {
3282            theParent = (IOService *)theNub->copyParentEntry(gIOPowerPlane);
3283            theNub->release();
3284            if ( theParent )
3285            {
3286                theParent->temperatureCriticalForZone(whichZone);
3287                theParent->release();
3288            }
3289        }
3290    }
3291    return IOPMNoErr;
3292}
3293#endif /* !__LP64__ */
3294
3295// MARK: -
3296// MARK: Power Change (Common)
3297
3298//*********************************************************************************
3299// [private] startPowerChange
3300//
3301// All power state changes starts here.
3302//*********************************************************************************
3303
3304IOReturn IOService::startPowerChange(
3305    IOPMPowerChangeFlags    changeFlags,
3306    IOPMPowerStateIndex     powerState,
3307    IOPMPowerFlags          domainFlags,
3308    IOPowerConnection *     parentConnection,
3309    IOPMPowerFlags          parentFlags )
3310{
3311	PM_ASSERT_IN_GATE();
3312	assert( fMachineState == kIOPM_Finished );
3313    assert( powerState < fNumberOfPowerStates );
3314
3315    if (powerState >= fNumberOfPowerStates)
3316        return IOPMAckImplied;
3317
3318    fIsPreChange = true;
3319    PM_ACTION_2(actionPowerChangeOverride, &powerState, &changeFlags);
3320
3321	// Forks to either Driver or Parent initiated power change paths.
3322
3323    fHeadNoteChangeFlags      = changeFlags;
3324    fHeadNotePowerState       = powerState;
3325	fHeadNotePowerArrayEntry  = &fPowerStates[ powerState ];
3326	fHeadNoteParentConnection = NULL;
3327
3328	if (changeFlags & kIOPMSelfInitiated)
3329	{
3330        if (changeFlags & kIOPMSynchronize)
3331            OurSyncStart();
3332        else
3333            OurChangeStart();
3334		return 0;
3335	}
3336	else
3337	{
3338		assert(changeFlags & kIOPMParentInitiated);
3339        fHeadNoteDomainFlags = domainFlags;
3340		fHeadNoteParentFlags = parentFlags;
3341        fHeadNoteParentConnection = parentConnection;
3342		return ParentChangeStart();
3343	}
3344}
3345
3346//*********************************************************************************
3347// [private] notifyInterestedDrivers
3348//*********************************************************************************
3349
3350bool IOService::notifyInterestedDrivers ( void )
3351{
3352    IOPMinformee *		informee;
3353    IOPMinformeeList *	list = fInterestedDrivers;
3354    DriverCallParam *	param;
3355    IOItemCount			count;
3356
3357    PM_ASSERT_IN_GATE();
3358    assert( fDriverCallParamCount == 0 );
3359    assert( fHeadNotePendingAcks == 0 );
3360
3361    fHeadNotePendingAcks = 0;
3362
3363    count = list->numberOfItems();
3364    if (!count)
3365        goto done;	// no interested drivers
3366
3367    // Allocate an array of interested drivers and their return values
3368    // for the callout thread. Everything else is still "owned" by the
3369    // PM work loop, which can run to process acknowledgePowerChange()
3370    // responses.
3371
3372    param = (DriverCallParam *) fDriverCallParamPtr;
3373    if (count > fDriverCallParamSlots)
3374    {
3375        if (fDriverCallParamSlots)
3376        {
3377            assert(fDriverCallParamPtr);
3378            IODelete(fDriverCallParamPtr, DriverCallParam, fDriverCallParamSlots);
3379            fDriverCallParamPtr = 0;
3380            fDriverCallParamSlots = 0;
3381        }
3382
3383        param = IONew(DriverCallParam, count);
3384        if (!param)
3385            goto done;	// no memory
3386
3387        fDriverCallParamPtr   = (void *) param;
3388        fDriverCallParamSlots = count;
3389    }
3390
3391    informee = list->firstInList();
3392    assert(informee);
3393    for (IOItemCount i = 0; i < count; i++)
3394    {
3395        informee->timer = -1;
3396        param[i].Target = informee;
3397        informee->retain();
3398        informee = list->nextInList( informee );
3399    }
3400
3401    fDriverCallParamCount = count;
3402    fHeadNotePendingAcks  = count;
3403
3404    // Block state machine and wait for callout completion.
3405    assert(!fDriverCallBusy);
3406    fDriverCallBusy = true;
3407    thread_call_enter( fDriverCallEntry );
3408    return true;
3409
3410done:
3411    // Return false if there are no interested drivers or could not schedule
3412    // callout thread due to error.
3413    return false;
3414}
3415
3416//*********************************************************************************
3417// [private] notifyInterestedDriversDone
3418//*********************************************************************************
3419
3420void IOService::notifyInterestedDriversDone ( void )
3421{
3422    IOPMinformee *		informee;
3423    IOItemCount			count;
3424    DriverCallParam *   param;
3425    IOReturn            result;
3426
3427	PM_ASSERT_IN_GATE();
3428	assert( fDriverCallBusy == false );
3429	assert( fMachineState == kIOPM_DriverThreadCallDone );
3430
3431	param = (DriverCallParam *) fDriverCallParamPtr;
3432	count = fDriverCallParamCount;
3433
3434	if (param && count)
3435	{
3436		for (IOItemCount i = 0; i < count; i++, param++)
3437		{
3438			informee = (IOPMinformee *) param->Target;
3439			result   = param->Result;
3440
3441			if ((result == IOPMAckImplied) || (result < 0))
3442			{
3443				// Interested driver return IOPMAckImplied.
3444                // If informee timer is zero, it must have de-registered
3445                // interest during the thread callout. That also drops
3446                // the pending ack count.
3447
3448				if (fHeadNotePendingAcks && informee->timer)
3449                    fHeadNotePendingAcks--;
3450
3451                informee->timer = 0;
3452			}
3453			else if (informee->timer)
3454			{
3455                assert(informee->timer == -1);
3456
3457                // Driver has not acked, and has returned a positive result.
3458                // Enforce a minimum permissible timeout value.
3459                // Make the min value large enough so timeout is less likely
3460                // to occur if a driver misinterpreted that the return value
3461                // should be in microsecond units.  And make it large enough
3462                // to be noticeable if a driver neglects to ack.
3463
3464                if (result < kMinAckTimeoutTicks)
3465                    result = kMinAckTimeoutTicks;
3466
3467                informee->timer = (result / (ACK_TIMER_PERIOD / ns_per_us)) + 1;
3468			}
3469			// else, child has already acked or driver has removed interest,
3470            // and head_note_pendingAcks decremented.
3471			// informee may have been removed from the interested drivers list,
3472            // thus the informee must be retained across the callout.
3473
3474			informee->release();
3475		}
3476
3477		fDriverCallParamCount = 0;
3478
3479		if ( fHeadNotePendingAcks )
3480		{
3481			OUR_PMLog(kPMLogStartAckTimer, 0, 0);
3482			start_ack_timer();
3483		}
3484	}
3485
3486    MS_POP();  // pushed by notifyAll()
3487
3488    // If interest acks are outstanding, wait for fHeadNotePendingAcks to become
3489    // zero before notifying children. This enforces the children after interest
3490    // ordering even for async interest clients.
3491
3492    if (!fHeadNotePendingAcks)
3493    {
3494        notifyChildren();
3495    }
3496    else
3497    {
3498        MS_PUSH(fMachineState);
3499        fMachineState = kIOPM_NotifyChildrenStart;
3500        PM_LOG2("%s: %u outstanding async interest\n",
3501            getName(), fHeadNotePendingAcks);
3502    }
3503}
3504
3505//*********************************************************************************
3506// [private] notifyChildren
3507//*********************************************************************************
3508
3509void IOService::notifyChildren ( void )
3510{
3511    OSIterator *		iter;
3512    OSObject *			next;
3513    IOPowerConnection *	connection;
3514	OSArray *			children = 0;
3515    IOPMrootDomain *    rootDomain;
3516    bool                delayNotify = false;
3517
3518    if ((fHeadNotePowerState != fCurrentPowerState) &&
3519        (IS_POWER_DROP == fIsPreChange) &&
3520        ((rootDomain = getPMRootDomain()) == this))
3521    {
3522        rootDomain->tracePoint( IS_POWER_DROP ?
3523            kIOPMTracePointSleepPowerPlaneDrivers :
3524            kIOPMTracePointWakePowerPlaneDrivers  );
3525    }
3526
3527	if (fStrictTreeOrder)
3528		children = OSArray::withCapacity(8);
3529
3530    // Sum child power consumption in notifyChild()
3531    fHeadNotePowerArrayEntry->staticPower = 0;
3532
3533    iter = getChildIterator(gIOPowerPlane);
3534    if ( iter )
3535    {
3536        while ((next = iter->getNextObject()))
3537        {
3538            if ((connection = OSDynamicCast(IOPowerConnection, next)))
3539            {
3540				if (connection->getReadyFlag() == false)
3541				{
3542					PM_LOG3("[%s] %s: connection not ready\n",
3543						getName(), __FUNCTION__);
3544					continue;
3545				}
3546
3547                // Mechanism to postpone the did-change notification to
3548                // certain power children to order those children last.
3549                // Cannot be used together with strict tree ordering.
3550
3551                if (!fIsPreChange &&
3552                    (connection->delayChildNotification) &&
3553                    getPMRootDomain()->shouldDelayChildNotification(this))
3554                {
3555                    if (!children)
3556                    {
3557                        children = OSArray::withCapacity(8);
3558                        if (children)
3559                            delayNotify = true;
3560                    }
3561                    if (delayNotify)
3562                    {
3563                        children->setObject( connection );
3564                        continue;
3565                    }
3566                }
3567
3568				if (!delayNotify && children)
3569					children->setObject( connection );
3570				else
3571					notifyChild( connection );
3572			}
3573        }
3574        iter->release();
3575    }
3576
3577    if (children && (children->getCount() == 0))
3578    {
3579        children->release();
3580        children = 0;
3581    }
3582	if (children)
3583	{
3584        assert(fNotifyChildArray == 0);
3585        fNotifyChildArray = children;
3586        MS_PUSH(fMachineState);
3587
3588        if (delayNotify)
3589        {
3590            // Wait for exiting child notifications to complete,
3591            // before notifying the children in the array.
3592            fMachineState = kIOPM_NotifyChildrenDelayed;
3593            PM_LOG2("%s: %d children in delayed array\n",
3594                getName(), children->getCount());
3595        }
3596        else
3597        {
3598            // Notify children in the array one at a time.
3599            fMachineState = kIOPM_NotifyChildrenOrdered;
3600        }
3601	}
3602}
3603
3604//*********************************************************************************
3605// [private] notifyChildrenOrdered
3606//*********************************************************************************
3607
3608void IOService::notifyChildrenOrdered ( void )
3609{
3610	PM_ASSERT_IN_GATE();
3611	assert(fNotifyChildArray);
3612	assert(fMachineState == kIOPM_NotifyChildrenOrdered);
3613
3614	// Notify one child, wait for it to ack, then repeat for next child.
3615	// This is a workaround for some drivers with multiple instances at
3616	// the same branch in the power tree, but the driver is slow to power
3617	// up unless the tree ordering is observed. Problem observed only on
3618	// system wake, not on system sleep.
3619	//
3620	// We have the ability to power off in reverse child index order.
3621	// That works nicely on some machines, but not on all HW configs.
3622
3623	if (fNotifyChildArray->getCount())
3624	{
3625		IOPowerConnection *	connection;
3626		connection = (IOPowerConnection *) fNotifyChildArray->getObject(0);
3627		notifyChild( connection );
3628		fNotifyChildArray->removeObject(0);
3629	}
3630	else
3631	{
3632		fNotifyChildArray->release();
3633		fNotifyChildArray = 0;
3634
3635        MS_POP();   // pushed by notifyChildren()
3636	}
3637}
3638
3639//*********************************************************************************
3640// [private] notifyChildrenDelayed
3641//*********************************************************************************
3642
3643void IOService::notifyChildrenDelayed ( void )
3644{
3645    IOPowerConnection *	connection;
3646
3647	PM_ASSERT_IN_GATE();
3648	assert(fNotifyChildArray);
3649	assert(fMachineState == kIOPM_NotifyChildrenDelayed);
3650
3651    // Wait after all non-delayed children and interested drivers have ack'ed,
3652    // then notify all delayed children. When explicitly cancelled, interest
3653    // acks (and ack timer) may still be outstanding.
3654
3655    for (int i = 0; ; i++)
3656    {
3657		connection = (IOPowerConnection *) fNotifyChildArray->getObject(i);
3658        if (!connection)
3659            break;
3660
3661		notifyChild( connection );
3662    }
3663
3664    PM_LOG2("%s: notified delayed children\n", getName());
3665    fNotifyChildArray->release();
3666    fNotifyChildArray = 0;
3667
3668    MS_POP();   // pushed by notifyChildren()
3669}
3670
3671//*********************************************************************************
3672// [private] notifyAll
3673//*********************************************************************************
3674
3675IOReturn IOService::notifyAll ( uint32_t nextMS )
3676{
3677	// Save the next machine_state to be restored by notifyInterestedDriversDone()
3678
3679	PM_ASSERT_IN_GATE();
3680    MS_PUSH(nextMS);
3681	fMachineState     = kIOPM_DriverThreadCallDone;
3682	fDriverCallReason = fIsPreChange ?
3683						kDriverCallInformPreChange : kDriverCallInformPostChange;
3684
3685	if (!notifyInterestedDrivers())
3686		notifyInterestedDriversDone();
3687
3688	return IOPMWillAckLater;
3689}
3690
3691//*********************************************************************************
3692// [private, static] pmDriverCallout
3693//
3694// Thread call context
3695//*********************************************************************************
3696
3697IOReturn IOService::actionDriverCalloutDone (
3698	OSObject * target,
3699	void * arg0, void * arg1,
3700	void * arg2, void * arg3 )
3701{
3702    IOServicePM * pwrMgt = (IOServicePM *) arg0;
3703
3704    assert( fDriverCallBusy );
3705    fDriverCallBusy = false;
3706
3707    assert(gIOPMWorkQueue);
3708    gIOPMWorkQueue->signalWorkAvailable();
3709
3710    return kIOReturnSuccess;
3711}
3712
3713void IOService::pmDriverCallout ( IOService * from )
3714{
3715	assert(from);
3716	switch (from->fDriverCallReason)
3717	{
3718		case kDriverCallSetPowerState:
3719			from->driverSetPowerState();
3720			break;
3721
3722		case kDriverCallInformPreChange:
3723		case kDriverCallInformPostChange:
3724			from->driverInformPowerChange();
3725			break;
3726
3727		default:
3728			panic("IOService::pmDriverCallout bad machine state %x",
3729                from->fDriverCallReason);
3730	}
3731
3732	gIOPMWorkLoop->runAction(actionDriverCalloutDone,
3733		/* target */ from,
3734		/* arg0   */ (void *) from->pwrMgt );
3735}
3736
3737//*********************************************************************************
3738// [private] driverSetPowerState
3739//
3740// Thread call context
3741//*********************************************************************************
3742
3743void IOService::driverSetPowerState ( void )
3744{
3745    IOPMPowerStateIndex powerState;
3746    DriverCallParam *	param;
3747    IOPMDriverCallEntry callEntry;
3748    AbsoluteTime        end;
3749    IOReturn            result;
3750    uint32_t            oldPowerState = getPowerState();
3751
3752    assert( fDriverCallBusy );
3753    assert( fDriverCallParamPtr );
3754    assert( fDriverCallParamCount == 1 );
3755
3756    param = (DriverCallParam *) fDriverCallParamPtr;
3757    powerState = fHeadNotePowerState;
3758
3759    if (assertPMDriverCall(&callEntry))
3760    {
3761        OUR_PMLog(          kPMLogProgramHardware, (uintptr_t) this, powerState);
3762        clock_get_uptime(&fDriverCallStartTime);
3763        result = fControllingDriver->setPowerState( powerState, this );
3764        clock_get_uptime(&end);
3765        OUR_PMLog((UInt32) -kPMLogProgramHardware, (uintptr_t) this, (UInt32) result);
3766
3767        deassertPMDriverCall(&callEntry);
3768
3769        if (result < 0)
3770        {
3771            PM_LOG("%s::setPowerState(%p, %lu -> %lu) returned 0x%x\n",
3772                fName, this, fCurrentPowerState, powerState, result);
3773        }
3774
3775#if LOG_SETPOWER_TIMES
3776        if ((result == IOPMAckImplied) || (result < 0))
3777        {
3778            uint64_t    nsec;
3779
3780            SUB_ABSOLUTETIME(&end, &fDriverCallStartTime);
3781            absolutetime_to_nanoseconds(end, &nsec);
3782            if (nsec > LOG_SETPOWER_TIMES)
3783                PM_LOG("%s::setPowerState(%p, %lu -> %lu) took %d ms\n",
3784                    fName, this, fCurrentPowerState, powerState, NS_TO_MS(nsec));
3785
3786            PMEventDetails *details = PMEventDetails::eventDetails(
3787                                        kIOPMEventTypeSetPowerStateImmediate, // type
3788                                        fName,								  // who
3789                                        (uintptr_t)this,					  // owner unique
3790                                        NULL,								  // interest name
3791                                        (uint8_t)oldPowerState,				  // old
3792                                        (uint8_t)powerState,				  // new
3793                                        0,									  // result
3794                                        NS_TO_US(nsec));					  // usec completion time
3795
3796            getPMRootDomain()->recordAndReleasePMEventGated( details );
3797        }
3798#endif
3799    }
3800    else
3801        result = kIOPMAckImplied;
3802
3803    param->Result = result;
3804}
3805
3806//*********************************************************************************
3807// [private] driverInformPowerChange
3808//
3809// Thread call context
3810//*********************************************************************************
3811
3812void IOService::driverInformPowerChange ( void )
3813{
3814    IOPMinformee *		informee;
3815    IOService *			driver;
3816    DriverCallParam *	param;
3817    IOPMDriverCallEntry callEntry;
3818    IOPMPowerFlags		powerFlags;
3819    IOPMPowerStateIndex powerState;
3820    AbsoluteTime        end;
3821    IOReturn            result;
3822    IOItemCount			count;
3823
3824    assert( fDriverCallBusy );
3825    assert( fDriverCallParamPtr );
3826    assert( fDriverCallParamCount );
3827
3828    param = (DriverCallParam *) fDriverCallParamPtr;
3829    count = fDriverCallParamCount;
3830
3831    powerFlags = fHeadNotePowerArrayEntry->capabilityFlags;
3832    powerState = fHeadNotePowerState;
3833
3834    for (IOItemCount i = 0; i < count; i++)
3835    {
3836        informee = (IOPMinformee *) param->Target;
3837        driver   = informee->whatObject;
3838
3839        if (assertPMDriverCall(&callEntry, 0, informee))
3840        {
3841            if (fDriverCallReason == kDriverCallInformPreChange)
3842            {
3843                OUR_PMLog(kPMLogInformDriverPreChange, (uintptr_t) this, powerState);
3844                clock_get_uptime(&informee->startTime);
3845                result = driver->powerStateWillChangeTo(powerFlags, powerState, this);
3846                clock_get_uptime(&end);
3847                OUR_PMLog((UInt32)-kPMLogInformDriverPreChange, (uintptr_t) this, result);
3848            }
3849            else
3850            {
3851                OUR_PMLog(kPMLogInformDriverPostChange, (uintptr_t) this, powerState);
3852                clock_get_uptime(&informee->startTime);
3853                result = driver->powerStateDidChangeTo(powerFlags, powerState, this);
3854                clock_get_uptime(&end);
3855                OUR_PMLog((UInt32)-kPMLogInformDriverPostChange, (uintptr_t) this, result);
3856            }
3857
3858            deassertPMDriverCall(&callEntry);
3859
3860#if LOG_SETPOWER_TIMES
3861            if ((result == IOPMAckImplied) || (result < 0))
3862            {
3863                uint64_t nsec;
3864
3865                SUB_ABSOLUTETIME(&end, &informee->startTime);
3866                absolutetime_to_nanoseconds(end, &nsec);
3867                if (nsec > LOG_SETPOWER_TIMES)
3868                    PM_LOG("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) took %d ms\n",
3869                        driver->getName(),
3870                        (fDriverCallReason == kDriverCallInformPreChange) ? "Will" : "Did",
3871                        driver, fName, fCurrentPowerState, powerState, NS_TO_MS(nsec));
3872
3873                uint16_t logType = (fDriverCallReason == kDriverCallInformPreChange)
3874                                    ? kIOPMEventTypePSWillChangeTo
3875                                    : kIOPMEventTypePSDidChangeTo;
3876
3877                PMEventDetails *details = PMEventDetails::eventDetails(
3878                                            logType,						// type
3879                                            fName,							// who
3880                                            (uintptr_t)this,				// owner unique
3881                                            driver->getName(),				// interest name
3882                                            (uint8_t)fCurrentPowerState,	// old
3883                                            (uint8_t)fHeadNotePowerState,	// new
3884                                            0,								// result
3885                                            NS_TO_US(nsec));				// usec completion time
3886
3887                getPMRootDomain()->recordAndReleasePMEventGated( details );
3888            }
3889#endif
3890        }
3891        else
3892            result = kIOPMAckImplied;
3893
3894        param->Result = result;
3895        param++;
3896    }
3897}
3898
3899//*********************************************************************************
3900// [private] notifyChild
3901//
3902// Notify a power domain child of an upcoming power change.
3903// If the object acknowledges the current change, we return TRUE.
3904//*********************************************************************************
3905
3906bool IOService::notifyChild ( IOPowerConnection * theNub )
3907{
3908    IOReturn                ret = IOPMAckImplied;
3909    unsigned long           childPower;
3910    IOService *             theChild;
3911	IOPMRequest *           childRequest;
3912    IOPMPowerChangeFlags    requestArg2;
3913	int                     requestType;
3914
3915	PM_ASSERT_IN_GATE();
3916    theChild = (IOService *)(theNub->copyChildEntry(gIOPowerPlane));
3917    if (!theChild)
3918    {
3919        return true;
3920    }
3921
3922    // Unless the child handles the notification immediately and returns
3923    // kIOPMAckImplied, we'll be awaiting their acknowledgement later.
3924	fHeadNotePendingAcks++;
3925    theNub->setAwaitingAck(true);
3926
3927    requestArg2 = fHeadNoteChangeFlags;
3928    if (fHeadNotePowerState < fCurrentPowerState)
3929        requestArg2 |= kIOPMDomainPowerDrop;
3930
3931    requestType = fIsPreChange ?
3932        kIOPMRequestTypePowerDomainWillChange :
3933        kIOPMRequestTypePowerDomainDidChange;
3934
3935	childRequest = acquirePMRequest( theChild, requestType );
3936	if (childRequest)
3937	{
3938        theNub->retain();
3939		childRequest->fArg0 = (void *) fHeadNotePowerArrayEntry->outputPowerFlags;
3940		childRequest->fArg1 = (void *) theNub;
3941		childRequest->fArg2 = (void *) requestArg2;
3942		theChild->submitPMRequest( childRequest );
3943		ret = IOPMWillAckLater;
3944	}
3945	else
3946	{
3947		ret = IOPMAckImplied;
3948		fHeadNotePendingAcks--;
3949		theNub->setAwaitingAck(false);
3950        childPower = theChild->currentPowerConsumption();
3951        if ( childPower == kIOPMUnknown )
3952        {
3953            fHeadNotePowerArrayEntry->staticPower = kIOPMUnknown;
3954        } else {
3955            if (fHeadNotePowerArrayEntry->staticPower != kIOPMUnknown )
3956                fHeadNotePowerArrayEntry->staticPower += childPower;
3957        }
3958    }
3959
3960    theChild->release();
3961	return (IOPMAckImplied == ret);
3962}
3963
3964//*********************************************************************************
3965// [private] notifyControllingDriver
3966//*********************************************************************************
3967
3968bool IOService::notifyControllingDriver ( void )
3969{
3970    DriverCallParam *	param;
3971
3972    PM_ASSERT_IN_GATE();
3973    assert( fDriverCallParamCount == 0  );
3974    assert( fControllingDriver );
3975
3976    if (fInitialSetPowerState)
3977    {
3978        fInitialSetPowerState = false;
3979        fHeadNoteChangeFlags |= kIOPMInitialPowerChange;
3980
3981        // Driver specified flag to skip the inital setPowerState()
3982        if (fHeadNotePowerArrayEntry->capabilityFlags & kIOPMInitialDeviceState)
3983        {
3984            return false;
3985        }
3986    }
3987
3988    param = (DriverCallParam *) fDriverCallParamPtr;
3989    if (!param)
3990    {
3991        param = IONew(DriverCallParam, 1);
3992        if (!param)
3993            return false;	// no memory
3994
3995        fDriverCallParamPtr   = (void *) param;
3996        fDriverCallParamSlots = 1;
3997    }
3998
3999    param->Target = fControllingDriver;
4000    fDriverCallParamCount = 1;
4001    fDriverTimer = -1;
4002
4003    // Block state machine and wait for callout completion.
4004    assert(!fDriverCallBusy);
4005    fDriverCallBusy = true;
4006    thread_call_enter( fDriverCallEntry );
4007
4008    return true;
4009}
4010
4011//*********************************************************************************
4012// [private] notifyControllingDriverDone
4013//*********************************************************************************
4014
4015void IOService::notifyControllingDriverDone( void )
4016{
4017	DriverCallParam *	param;
4018	IOReturn			result;
4019
4020	PM_ASSERT_IN_GATE();
4021	param = (DriverCallParam *) fDriverCallParamPtr;
4022
4023	assert( fDriverCallBusy == false );
4024	assert( fMachineState == kIOPM_DriverThreadCallDone );
4025
4026	if (param && fDriverCallParamCount)
4027	{
4028		assert(fDriverCallParamCount == 1);
4029
4030		// the return value from setPowerState()
4031		result = param->Result;
4032
4033		if ((result == IOPMAckImplied) || (result < 0))
4034		{
4035            fDriverTimer = 0;
4036		}
4037		else if (fDriverTimer)
4038		{
4039            assert(fDriverTimer == -1);
4040
4041            // Driver has not acked, and has returned a positive result.
4042            // Enforce a minimum permissible timeout value.
4043            // Make the min value large enough so timeout is less likely
4044            // to occur if a driver misinterpreted that the return value
4045            // should be in microsecond units.  And make it large enough
4046            // to be noticeable if a driver neglects to ack.
4047
4048            if (result < kMinAckTimeoutTicks)
4049                result = kMinAckTimeoutTicks;
4050
4051            fDriverTimer = (result / (ACK_TIMER_PERIOD / ns_per_us)) + 1;
4052		}
4053		// else, child has already acked and driver_timer reset to 0.
4054
4055		fDriverCallParamCount = 0;
4056
4057		if ( fDriverTimer )
4058		{
4059			OUR_PMLog(kPMLogStartAckTimer, 0, 0);
4060			start_ack_timer();
4061		}
4062	}
4063
4064    MS_POP();   // pushed by OurChangeSetPowerState()
4065    fIsPreChange  = false;
4066}
4067
4068//*********************************************************************************
4069// [private] all_done
4070//
4071// A power change is done.
4072//*********************************************************************************
4073
4074void IOService::all_done ( void )
4075{
4076    IOPMPowerStateIndex     prevPowerState;
4077    const IOPMPSEntry *     powerStatePtr;
4078    IOPMDriverCallEntry     callEntry;
4079    uint32_t                prevMachineState = fMachineState;
4080    bool                    callAction = false;
4081
4082    fMachineState = kIOPM_Finished;
4083
4084    if ((fHeadNoteChangeFlags & kIOPMSynchronize) &&
4085        ((prevMachineState == kIOPM_Finished) ||
4086         (prevMachineState == kIOPM_SyncFinish)))
4087    {
4088        // Sync operation and no power change occurred.
4089        // Do not inform driver and clients about this request completion,
4090        // except for the originator (root domain).
4091
4092        PM_ACTION_2(actionPowerChangeDone,
4093            fHeadNotePowerState, fHeadNoteChangeFlags);
4094
4095        if (getPMRequestType() == kIOPMRequestTypeSynchronizePowerTree)
4096        {
4097            powerChangeDone(fCurrentPowerState);
4098        }
4099        else if (fAdvisoryTickleUsed)
4100        {
4101            // Not root domain and advisory tickle target
4102            // Re-adjust power after power tree sync at the 'did' pass
4103            if (!fAdjustPowerScheduled &&
4104                (fHeadNoteChangeFlags & kIOPMDomainDidChange))
4105            {
4106                IOPMRequest * request;
4107                request = acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState );
4108                if (request)
4109                {
4110                    submitPMRequest( request );
4111                    fAdjustPowerScheduled = true;
4112                }
4113            }
4114        }
4115
4116        return;
4117    }
4118
4119    // our power change
4120    if ( fHeadNoteChangeFlags & kIOPMSelfInitiated )
4121    {
4122        // could our driver switch to the new state?
4123        if ( !( fHeadNoteChangeFlags & kIOPMNotDone) )
4124        {
4125            trackSystemSleepPreventers(
4126                fCurrentPowerState, fHeadNotePowerState, fHeadNoteChangeFlags);
4127
4128			// we changed, tell our parent
4129            requestDomainPower(fHeadNotePowerState);
4130
4131            // yes, did power raise?
4132            if ( fCurrentPowerState < fHeadNotePowerState )
4133            {
4134                // yes, inform clients and apps
4135                tellChangeUp (fHeadNotePowerState);
4136            }
4137            prevPowerState = fCurrentPowerState;
4138            // either way
4139            fCurrentPowerState = fHeadNotePowerState;
4140#if PM_VARS_SUPPORT
4141            fPMVars->myCurrentState = fCurrentPowerState;
4142#endif
4143            OUR_PMLog(kPMLogChangeDone, fCurrentPowerState, prevPowerState);
4144            PM_ACTION_2(actionPowerChangeDone,
4145                fHeadNotePowerState, fHeadNoteChangeFlags);
4146            callAction = true;
4147
4148            powerStatePtr = &fPowerStates[fCurrentPowerState];
4149            fCurrentCapabilityFlags = powerStatePtr->capabilityFlags;
4150            if (fCurrentCapabilityFlags & kIOPMStaticPowerValid)
4151                fCurrentPowerConsumption = powerStatePtr->staticPower;
4152
4153            // inform subclass policy-maker
4154            if (fPCDFunctionOverride && fParentsKnowState &&
4155                assertPMDriverCall(&callEntry, kIOPMADC_NoInactiveCheck))
4156            {
4157                powerChangeDone(prevPowerState);
4158                deassertPMDriverCall(&callEntry);
4159            }
4160        }
4161        else if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride)
4162        {
4163            // changePowerStateWithOverrideTo() was cancelled
4164            fOverrideMaxPowerState = kIOPMPowerStateMax;
4165        }
4166    }
4167
4168    // parent's power change
4169    if ( fHeadNoteChangeFlags & kIOPMParentInitiated)
4170    {
4171        if (((fHeadNoteChangeFlags & kIOPMDomainWillChange) &&
4172             (fCurrentPowerState >= fHeadNotePowerState))   ||
4173			  ((fHeadNoteChangeFlags & kIOPMDomainDidChange)  &&
4174             (fCurrentPowerState < fHeadNotePowerState)))
4175        {
4176            trackSystemSleepPreventers(
4177                fCurrentPowerState, fHeadNotePowerState, fHeadNoteChangeFlags);
4178
4179            // did power raise?
4180            if ( fCurrentPowerState < fHeadNotePowerState )
4181            {
4182                // yes, inform clients and apps
4183                tellChangeUp (fHeadNotePowerState);
4184            }
4185            // either way
4186            prevPowerState = fCurrentPowerState;
4187            fCurrentPowerState = fHeadNotePowerState;
4188#if PM_VARS_SUPPORT
4189            fPMVars->myCurrentState = fCurrentPowerState;
4190#endif
4191            fMaxPowerState = fControllingDriver->maxCapabilityForDomainState(fHeadNoteDomainFlags);
4192
4193            OUR_PMLog(kPMLogChangeDone, fCurrentPowerState, prevPowerState);
4194            PM_ACTION_2(actionPowerChangeDone,
4195                fHeadNotePowerState, fHeadNoteChangeFlags);
4196            callAction = true;
4197
4198            powerStatePtr = &fPowerStates[fCurrentPowerState];
4199            fCurrentCapabilityFlags = powerStatePtr->capabilityFlags;
4200            if (fCurrentCapabilityFlags & kIOPMStaticPowerValid)
4201                fCurrentPowerConsumption = powerStatePtr->staticPower;
4202
4203            // inform subclass policy-maker
4204            if (fPCDFunctionOverride && fParentsKnowState &&
4205                assertPMDriverCall(&callEntry, kIOPMADC_NoInactiveCheck))
4206            {
4207                powerChangeDone(prevPowerState);
4208                deassertPMDriverCall(&callEntry);
4209            }
4210        }
4211    }
4212
4213    // When power rises enough to satisfy the tickle's desire for more power,
4214    // the condition preventing idle-timer from dropping power is removed.
4215
4216    if (fCurrentPowerState >= fIdleTimerMinPowerState)
4217    {
4218        fIdleTimerMinPowerState = 0;
4219    }
4220
4221    if (!callAction)
4222    {
4223        PM_ACTION_2(actionPowerChangeDone,
4224            fHeadNotePowerState, fHeadNoteChangeFlags);
4225    }
4226}
4227
4228// MARK: -
4229// MARK: Power Change Initiated by Driver
4230
4231//*********************************************************************************
4232// [private] OurChangeStart
4233//
4234// Begin the processing of a power change initiated by us.
4235//*********************************************************************************
4236
4237void IOService::OurChangeStart ( void )
4238{
4239	PM_ASSERT_IN_GATE();
4240    OUR_PMLog( kPMLogStartDeviceChange, fHeadNotePowerState, fCurrentPowerState );
4241
4242	// fMaxPowerState is our maximum possible power state based on the current
4243	// power state of our parents.  If we are trying to raise power beyond the
4244	// maximum, send an async request for more power to all parents.
4245
4246    if (!IS_PM_ROOT && (fMaxPowerState < fHeadNotePowerState))
4247    {
4248        fHeadNoteChangeFlags |= kIOPMNotDone;
4249        requestDomainPower(fHeadNotePowerState);
4250        OurChangeFinish();
4251        return;
4252    }
4253
4254	// Redundant power changes skips to the end of the state machine.
4255
4256    if (!fInitialPowerChange && (fHeadNotePowerState == fCurrentPowerState))
4257	{
4258		OurChangeFinish();
4259		return;
4260    }
4261    fInitialPowerChange = false;
4262
4263    // Change started, but may not complete...
4264    // Can be canceled (power drop) or deferred (power rise).
4265
4266    PM_ACTION_2(actionPowerChangeStart, fHeadNotePowerState, &fHeadNoteChangeFlags);
4267
4268	// Two separate paths, depending if power is being raised or lowered.
4269	// Lowering power is subject to approval by clients of this service.
4270
4271    if (IS_POWER_DROP)
4272    {
4273        fDoNotPowerDown = false;
4274
4275        // Ask for persmission to drop power state
4276        fMachineState = kIOPM_OurChangeTellClientsPowerDown;
4277        fOutOfBandParameter = kNotifyApps;
4278        askChangeDown(fHeadNotePowerState);
4279    }
4280	else
4281	{
4282        // This service is raising power and parents are able to support the
4283        // new power state. However a parent may have already committed to
4284        // drop power, which might force this object to temporarily drop power.
4285        // This results in "oscillations" before the state machines converge
4286        // to a steady state.
4287        //
4288        // To prevent this, a child must make a power reservation against all
4289        // parents before raising power. If the reservation fails, indicating
4290        // that the child will be unable to sustain the higher power state,
4291        // then the child will signal the parent to adjust power, and the child
4292        // will defer its power change.
4293
4294        IOReturn ret;
4295
4296        // Reserve parent power necessary to achieve fHeadNotePowerState.
4297        ret = requestDomainPower( fHeadNotePowerState, kReserveDomainPower );
4298        if (ret != kIOReturnSuccess)
4299        {
4300            // Reservation failed, defer power rise.
4301            fHeadNoteChangeFlags |= kIOPMNotDone;
4302            OurChangeFinish();
4303            return;
4304        }
4305
4306        OurChangeTellCapabilityWillChange();
4307    }
4308}
4309
4310//*********************************************************************************
4311
4312struct IOPMRequestDomainPowerContext {
4313    IOService *     child;              // the requesting child
4314    IOPMPowerFlags  requestPowerFlags;  // power flags requested by child
4315};
4316
4317static void
4318requestDomainPowerApplier(
4319    IORegistryEntry *   entry,
4320    void *              inContext )
4321{
4322    IOPowerConnection *             connection;
4323    IOService *                     parent;
4324    IOPMRequestDomainPowerContext * context;
4325
4326    if ((connection = OSDynamicCast(IOPowerConnection, entry)) == 0)
4327        return;
4328    parent = (IOService *) connection->copyParentEntry(gIOPowerPlane);
4329    if (!parent)
4330        return;
4331
4332    assert(inContext);
4333    context = (IOPMRequestDomainPowerContext *) inContext;
4334
4335    if (connection->parentKnowsState() && connection->getReadyFlag())
4336    {
4337        parent->requestPowerDomainState(
4338            context->requestPowerFlags,
4339            connection,
4340            IOPMLowestState);
4341    }
4342
4343    parent->release();
4344}
4345
4346//*********************************************************************************
4347// [private] requestDomainPower
4348//*********************************************************************************
4349
4350IOReturn IOService::requestDomainPower(
4351    IOPMPowerStateIndex ourPowerState,
4352    IOOptionBits        options )
4353{
4354    IOPMPowerFlags                  requestPowerFlags;
4355    IOPMPowerStateIndex             maxPowerState;
4356    IOPMRequestDomainPowerContext   context;
4357
4358	PM_ASSERT_IN_GATE();
4359    assert(ourPowerState < fNumberOfPowerStates);
4360    if (ourPowerState >= fNumberOfPowerStates)
4361        return kIOReturnBadArgument;
4362    if (IS_PM_ROOT)
4363        return kIOReturnSuccess;
4364
4365    // Fetch the input power flags for the requested power state.
4366    // Parent request is stated in terms of required power flags.
4367
4368	requestPowerFlags = fPowerStates[ourPowerState].inputPowerFlags;
4369
4370    // Disregard the "previous request" for power reservation.
4371
4372    if (((options & kReserveDomainPower) == 0) &&
4373        (fPreviousRequestPowerFlags == requestPowerFlags))
4374    {
4375        // skip if domain already knows our requirements
4376        goto done;
4377    }
4378    fPreviousRequestPowerFlags = requestPowerFlags;
4379
4380    context.child              = this;
4381    context.requestPowerFlags  = requestPowerFlags;
4382    fHeadNoteDomainTargetFlags = 0;
4383    applyToParents(requestDomainPowerApplier, &context, gIOPowerPlane);
4384
4385    if (options & kReserveDomainPower)
4386    {
4387        maxPowerState = fControllingDriver->maxCapabilityForDomainState(
4388                            fHeadNoteDomainTargetFlags );
4389
4390        if (maxPowerState < fHeadNotePowerState)
4391        {
4392            PM_LOG1("%s: power desired %u:0x%x got %u:0x%x\n",
4393                getName(),
4394                (uint32_t) ourPowerState, (uint32_t) requestPowerFlags,
4395                (uint32_t) maxPowerState, (uint32_t) fHeadNoteDomainTargetFlags);
4396            return kIOReturnNoPower;
4397        }
4398    }
4399
4400done:
4401    return kIOReturnSuccess;
4402}
4403
4404//*********************************************************************************
4405// [private] OurSyncStart
4406//*********************************************************************************
4407
4408void IOService::OurSyncStart ( void )
4409{
4410	PM_ASSERT_IN_GATE();
4411
4412    if (fInitialPowerChange)
4413        return;
4414
4415    PM_ACTION_2(actionPowerChangeStart, fHeadNotePowerState, &fHeadNoteChangeFlags);
4416
4417    if (fHeadNoteChangeFlags & kIOPMNotDone)
4418    {
4419		OurChangeFinish();
4420		return;
4421    }
4422
4423    if (fHeadNoteChangeFlags & kIOPMSyncTellPowerDown)
4424    {
4425        fDoNotPowerDown = false;
4426
4427        // Ask for permission to drop power state
4428        fMachineState = kIOPM_SyncTellClientsPowerDown;
4429        fOutOfBandParameter = kNotifyApps;
4430        askChangeDown(fHeadNotePowerState);
4431    }
4432    else
4433    {
4434        // Only inform capability app and clients.
4435        tellSystemCapabilityChange( kIOPM_SyncNotifyWillChange );
4436    }
4437}
4438
4439//*********************************************************************************
4440// [private] OurChangeTellClientsPowerDown
4441//
4442// All applications and kernel clients have acknowledged our permission to drop
4443// power. Here we notify them that we will lower the power and wait for acks.
4444//*********************************************************************************
4445
4446void IOService::OurChangeTellClientsPowerDown ( void )
4447{
4448    fMachineState = kIOPM_OurChangeTellPriorityClientsPowerDown;
4449    tellChangeDown1(fHeadNotePowerState);
4450}
4451
4452//*********************************************************************************
4453// [private] OurChangeTellPriorityClientsPowerDown
4454//
4455// All applications and kernel clients have acknowledged our intention to drop
4456// power.  Here we notify "priority" clients that we are lowering power.
4457//*********************************************************************************
4458
4459void IOService::OurChangeTellPriorityClientsPowerDown ( void )
4460{
4461    fMachineState = kIOPM_OurChangeNotifyInterestedDriversWillChange;
4462    tellChangeDown2(fHeadNotePowerState);
4463}
4464
4465//*********************************************************************************
4466// [private] OurChangeTellCapabilityWillChange
4467//
4468// Extra stage for root domain to notify apps and drivers about the
4469// system capability change when raising power state.
4470//*********************************************************************************
4471
4472void IOService::OurChangeTellCapabilityWillChange ( void )
4473{
4474    if (!IS_ROOT_DOMAIN)
4475        return OurChangeNotifyInterestedDriversWillChange();
4476
4477    tellSystemCapabilityChange( kIOPM_OurChangeNotifyInterestedDriversWillChange );
4478}
4479
4480//*********************************************************************************
4481// [private] OurChangeNotifyInterestedDriversWillChange
4482//
4483// All applications and kernel clients have acknowledged our power state change.
4484// Here we notify interested drivers pre-change.
4485//*********************************************************************************
4486
4487void IOService::OurChangeNotifyInterestedDriversWillChange ( void )
4488{
4489    IOPMrootDomain * rootDomain;
4490    if ((rootDomain = getPMRootDomain()) == this)
4491    {
4492        if (IS_POWER_DROP)
4493        {
4494            rootDomain->tracePoint( kIOPMTracePointSleepWillChangeInterests );
4495
4496            PMEventDetails *details = PMEventDetails::eventDetails(
4497                                        kIOPMEventTypeAppNotificationsFinished,
4498                                        NULL,
4499                                        100,
4500                                        kIOReturnSuccess);
4501            rootDomain->recordAndReleasePMEventGated( details );
4502        }
4503        else
4504            rootDomain->tracePoint( kIOPMTracePointWakeWillChangeInterests );
4505    }
4506
4507    notifyAll( kIOPM_OurChangeSetPowerState );
4508}
4509
4510//*********************************************************************************
4511// [private] OurChangeSetPowerState
4512//
4513// Instruct our controlling driver to program the hardware for the power state
4514// change. Wait for async completions.
4515//*********************************************************************************
4516
4517void IOService::OurChangeSetPowerState ( void )
4518{
4519    MS_PUSH( kIOPM_OurChangeWaitForPowerSettle );
4520    fMachineState     = kIOPM_DriverThreadCallDone;
4521    fDriverCallReason = kDriverCallSetPowerState;
4522
4523    if (notifyControllingDriver() == false)
4524        notifyControllingDriverDone();
4525}
4526
4527//*********************************************************************************
4528// [private] OurChangeWaitForPowerSettle
4529//
4530// Our controlling driver has completed the power state change we initiated.
4531// Wait for the driver specified settle time to expire.
4532//*********************************************************************************
4533
4534void IOService::OurChangeWaitForPowerSettle ( void )
4535{
4536    fMachineState = kIOPM_OurChangeNotifyInterestedDriversDidChange;
4537    startSettleTimer();
4538}
4539
4540//*********************************************************************************
4541// [private] OurChangeNotifyInterestedDriversDidChange
4542//
4543// Power has settled on a power change we initiated. Here we notify
4544// all our interested drivers post-change.
4545//*********************************************************************************
4546
4547void IOService::OurChangeNotifyInterestedDriversDidChange ( void )
4548{
4549    IOPMrootDomain * rootDomain;
4550    if ((rootDomain = getPMRootDomain()) == this)
4551    {
4552        rootDomain->tracePoint( IS_POWER_DROP ?
4553            kIOPMTracePointSleepDidChangeInterests :
4554            kIOPMTracePointWakeDidChangeInterests  );
4555    }
4556
4557    notifyAll( kIOPM_OurChangeTellCapabilityDidChange );
4558}
4559
4560//*********************************************************************************
4561// [private] OurChangeTellCapabilityDidChange
4562//
4563// For root domain to notify capability power-change.
4564//*********************************************************************************
4565
4566void IOService::OurChangeTellCapabilityDidChange ( void )
4567{
4568    if (!IS_ROOT_DOMAIN)
4569        return OurChangeFinish();
4570
4571    getPMRootDomain()->tracePoint( IS_POWER_DROP ?
4572        kIOPMTracePointSleepCapabilityClients :
4573        kIOPMTracePointWakeCapabilityClients  );
4574
4575    tellSystemCapabilityChange( kIOPM_OurChangeFinish );
4576}
4577
4578//*********************************************************************************
4579// [private] OurChangeFinish
4580//
4581// Done with this self-induced power state change.
4582//*********************************************************************************
4583
4584void IOService::OurChangeFinish ( void )
4585{
4586    all_done();
4587}
4588
4589// MARK: -
4590// MARK: Power Change Initiated by Parent
4591
4592//*********************************************************************************
4593// [private] ParentChangeStart
4594//
4595// Here we begin the processing of a power change initiated by our parent.
4596//*********************************************************************************
4597
4598IOReturn IOService::ParentChangeStart ( void )
4599{
4600	PM_ASSERT_IN_GATE();
4601    OUR_PMLog( kPMLogStartParentChange, fHeadNotePowerState, fCurrentPowerState );
4602
4603    // Power domain is lowering power
4604    if ( fHeadNotePowerState < fCurrentPowerState )
4605    {
4606        // Piggy-back idle timer cancellation on a parent down
4607        if (0 == fHeadNotePowerState)
4608            ParentChangeCancelIdleTimer(fHeadNotePowerState);
4609
4610		// TODO: redundant? See handlePowerDomainWillChangeTo()
4611		setParentInfo( fHeadNoteParentFlags, fHeadNoteParentConnection, true );
4612
4613        PM_ACTION_2(actionPowerChangeStart, fHeadNotePowerState, &fHeadNoteChangeFlags);
4614
4615    	// Tell apps and kernel clients
4616    	fInitialPowerChange = false;
4617        fMachineState = kIOPM_ParentChangeTellPriorityClientsPowerDown;
4618		tellChangeDown1(fHeadNotePowerState);
4619        return IOPMWillAckLater;
4620    }
4621
4622    // Power domain is raising power
4623    if ( fHeadNotePowerState > fCurrentPowerState )
4624    {
4625        if ( fDesiredPowerState > fCurrentPowerState )
4626        {
4627            if ( fDesiredPowerState < fHeadNotePowerState )
4628            {
4629                // We power up, but not all the way
4630                fHeadNotePowerState = fDesiredPowerState;
4631				fHeadNotePowerArrayEntry = &fPowerStates[fDesiredPowerState];
4632                OUR_PMLog(kPMLogAmendParentChange, fHeadNotePowerState, 0);
4633             }
4634        } else {
4635            // We don't need to change
4636            fHeadNotePowerState = fCurrentPowerState;
4637			fHeadNotePowerArrayEntry = &fPowerStates[fCurrentPowerState];
4638            OUR_PMLog(kPMLogAmendParentChange, fHeadNotePowerState, 0);
4639        }
4640    }
4641
4642    if ( fHeadNoteChangeFlags & kIOPMDomainDidChange )
4643	{
4644        if ( fHeadNotePowerState > fCurrentPowerState )
4645        {
4646            PM_ACTION_2(actionPowerChangeStart,
4647                fHeadNotePowerState, &fHeadNoteChangeFlags);
4648
4649            // Parent did change up - start our change up
4650            fInitialPowerChange = false;
4651            ParentChangeTellCapabilityWillChange();
4652            return IOPMWillAckLater;
4653        }
4654        else if (fHeadNoteChangeFlags & kIOPMSynchronize)
4655        {
4656            // We do not need to change power state, but notify
4657            // children to propagate tree synchronization.
4658            fMachineState     = kIOPM_SyncNotifyDidChange;
4659            fDriverCallReason = kDriverCallInformPreChange;
4660            notifyChildren();
4661            return IOPMWillAckLater;
4662        }
4663    }
4664
4665    all_done();
4666    return IOPMAckImplied;
4667}
4668
4669//*********************************************************************************
4670// [private] ParentChangeTellPriorityClientsPowerDown
4671//
4672// All applications and kernel clients have acknowledged our intention to drop
4673// power.  Here we notify "priority" clients that we are lowering power.
4674//*********************************************************************************
4675
4676void IOService::ParentChangeTellPriorityClientsPowerDown ( void )
4677{
4678    fMachineState = kIOPM_ParentChangeNotifyInterestedDriversWillChange;
4679	tellChangeDown2(fHeadNotePowerState);
4680}
4681
4682//*********************************************************************************
4683// [private] ParentChangeTellCapabilityWillChange
4684//
4685// All (legacy) applications and kernel clients have acknowledged, extra stage for
4686// root domain to notify apps and drivers about the system capability change.
4687//*********************************************************************************
4688
4689void IOService::ParentChangeTellCapabilityWillChange ( void )
4690{
4691    if (!IS_ROOT_DOMAIN)
4692        return ParentChangeNotifyInterestedDriversWillChange();
4693
4694    tellSystemCapabilityChange( kIOPM_ParentChangeNotifyInterestedDriversWillChange );
4695}
4696
4697//*********************************************************************************
4698// [private] ParentChangeNotifyInterestedDriversWillChange
4699//
4700// All applications and kernel clients have acknowledged our power state change.
4701// Here we notify interested drivers pre-change.
4702//*********************************************************************************
4703
4704void IOService::ParentChangeNotifyInterestedDriversWillChange ( void )
4705{
4706	notifyAll( kIOPM_ParentChangeSetPowerState );
4707}
4708
4709//*********************************************************************************
4710// [private] ParentChangeSetPowerState
4711//
4712// Instruct our controlling driver to program the hardware for the power state
4713// change. Wait for async completions.
4714//*********************************************************************************
4715
4716void IOService::ParentChangeSetPowerState ( void )
4717{
4718    MS_PUSH( kIOPM_ParentChangeWaitForPowerSettle );
4719    fMachineState     = kIOPM_DriverThreadCallDone;
4720    fDriverCallReason = kDriverCallSetPowerState;
4721
4722    if (notifyControllingDriver() == false)
4723        notifyControllingDriverDone();
4724}
4725
4726//*********************************************************************************
4727// [private] ParentChangeWaitForPowerSettle
4728//
4729// Our controlling driver has completed the power state change initiated by our
4730// parent. Wait for the driver specified settle time to expire.
4731//*********************************************************************************
4732
4733void IOService::ParentChangeWaitForPowerSettle ( void )
4734{
4735	fMachineState = kIOPM_ParentChangeNotifyInterestedDriversDidChange;
4736    startSettleTimer();
4737}
4738
4739//*********************************************************************************
4740// [private] ParentChangeNotifyInterestedDriversDidChange
4741//
4742// Power has settled on a power change initiated by our parent. Here we notify
4743// all our interested drivers post-change.
4744//*********************************************************************************
4745
4746void IOService::ParentChangeNotifyInterestedDriversDidChange ( void )
4747{
4748	notifyAll( kIOPM_ParentChangeTellCapabilityDidChange );
4749}
4750
4751//*********************************************************************************
4752// [private] ParentChangeTellCapabilityDidChange
4753//
4754// For root domain to notify capability power-change.
4755//*********************************************************************************
4756
4757void IOService::ParentChangeTellCapabilityDidChange ( void )
4758{
4759    if (!IS_ROOT_DOMAIN)
4760        return ParentChangeAcknowledgePowerChange();
4761
4762    tellSystemCapabilityChange( kIOPM_ParentChangeAcknowledgePowerChange );
4763}
4764
4765//*********************************************************************************
4766// [private] ParentAcknowledgePowerChange
4767//
4768// Acknowledge our power parent that our power change is done.
4769//*********************************************************************************
4770
4771void IOService::ParentChangeAcknowledgePowerChange ( void )
4772{
4773    IORegistryEntry *	nub;
4774    IOService *			parent;
4775
4776    nub = fHeadNoteParentConnection;
4777    nub->retain();
4778    all_done();
4779    parent = (IOService *)nub->copyParentEntry(gIOPowerPlane);
4780    if ( parent )
4781    {
4782        parent->acknowledgePowerChange((IOService *)nub);
4783        parent->release();
4784    }
4785    nub->release();
4786}
4787
4788void IOService::ParentChangeCancelIdleTimer( IOPMPowerStateIndex newPowerState )
4789{
4790    AbsoluteTime    now;
4791    uint64_t        nsec;
4792    bool            cancel = false;
4793
4794    // No ready or idle timer not in use
4795    if (!initialized || !fIdleTimerPeriod || fLockedFlags.PMStop ||
4796        !fAdvisoryTickleUsed)
4797        return;
4798
4799    // Not allowed to induce artifical idle timeout
4800    if (fIdleTimerIgnored || fIdleTimerMinPowerState)
4801        goto done;
4802
4803    // Idle timer already has no influence
4804    if (!fDesiredPowerState || fIdleTimerStopped)
4805        goto done;
4806
4807	IOLockLock(fActivityLock);
4808
4809    if (!fDeviceWasActive)
4810    {
4811        // No tickles since the last idle timer expiration.
4812        // Safe to drop the device desire to zero.
4813        cancel = true;
4814    }
4815    else
4816    {
4817        // Was tickled since the last idle timer expiration,
4818        // but not in the last minute.
4819        clock_get_uptime(&now);
4820        SUB_ABSOLUTETIME(&now, &fDeviceActiveTimestamp);
4821        absolutetime_to_nanoseconds(now, &nsec);
4822        if (nsec >= kNoTickleCancelWindow)
4823        {
4824            cancel = true;
4825        }
4826    }
4827
4828    if (cancel)
4829    {
4830        // Force the next tickle to raise power state
4831		fActivityTicklePowerState = kInvalidTicklePowerState;
4832        fDeviceWasActive = false;
4833    }
4834
4835	IOLockUnlock(fActivityLock);
4836
4837    if (cancel)
4838    {
4839        // cancel idle timer
4840        if (fIdleTimer && thread_call_cancel(fIdleTimer))
4841            release();
4842
4843        updatePowerClient(gIOPMPowerClientDevice, 0);
4844        computeDesiredState();
4845
4846        fIdleTimerStopped = true;
4847    }
4848
4849done:
4850    OUR_PMLog( kPMLogStartParentChange, fHeadNotePowerState, fCurrentPowerState );
4851    PM_LOG("%s::%s cancel=%d\n", fName, __FUNCTION__, cancel);
4852}
4853
4854// MARK: -
4855// MARK: Ack and Settle timers
4856
4857//*********************************************************************************
4858// [private] settleTimerExpired
4859//
4860// Power has settled after our last change.  Notify interested parties that
4861// there is a new power state.
4862//*********************************************************************************
4863
4864void IOService::settleTimerExpired( void )
4865{
4866	fSettleTimeUS = 0;
4867	gIOPMWorkQueue->signalWorkAvailable();
4868}
4869
4870//*********************************************************************************
4871// settle_timer_expired
4872//
4873// Holds a retain while the settle timer callout is in flight.
4874//*********************************************************************************
4875
4876static void
4877settle_timer_expired( thread_call_param_t arg0, thread_call_param_t arg1 )
4878{
4879	IOService * me = (IOService *) arg0;
4880
4881	if (gIOPMWorkLoop && gIOPMWorkQueue)
4882	{
4883		gIOPMWorkLoop->runAction(
4884            OSMemberFunctionCast(IOWorkLoop::Action, me, &IOService::settleTimerExpired),
4885            me);
4886	}
4887	me->release();
4888}
4889
4890//*********************************************************************************
4891// [private] startSettleTimer
4892//
4893// Calculate a power-settling delay in microseconds and start a timer.
4894//*********************************************************************************
4895
4896void IOService::startSettleTimer( void )
4897{
4898    AbsoluteTime        deadline;
4899    IOPMPowerStateIndex i;
4900    uint32_t            settleTime = 0;
4901	boolean_t           pending;
4902
4903	PM_ASSERT_IN_GATE();
4904
4905    i = fCurrentPowerState;
4906
4907    // lowering power
4908    if ( fHeadNotePowerState < fCurrentPowerState )
4909    {
4910        while ( i > fHeadNotePowerState )
4911        {
4912            settleTime += (uint32_t) fPowerStates[i].settleDownTime;
4913            i--;
4914        }
4915    }
4916
4917    // raising power
4918    if ( fHeadNotePowerState > fCurrentPowerState )
4919    {
4920        while ( i < fHeadNotePowerState )
4921        {
4922            settleTime += (uint32_t) fPowerStates[i+1].settleUpTime;
4923            i++;
4924        }
4925    }
4926
4927    if (settleTime)
4928    {
4929        retain();
4930        clock_interval_to_deadline(settleTime, kMicrosecondScale, &deadline);
4931        pending = thread_call_enter_delayed(fSettleTimer, deadline);
4932        if (pending) release();
4933    }
4934}
4935
4936//*********************************************************************************
4937// [private] ackTimerTick
4938//
4939// The acknowledgement timeout periodic timer has ticked.
4940// If we are awaiting acks for a power change notification,
4941// we decrement the timer word of each interested driver which hasn't acked.
4942// If a timer word becomes zero, we pretend the driver aknowledged.
4943// If we are waiting for the controlling driver to change the power
4944// state of the hardware, we decrement its timer word, and if it becomes
4945// zero, we pretend the driver acknowledged.
4946//
4947// Returns true if the timer tick made it possible to advance to the next
4948// machine state, false otherwise.
4949//*********************************************************************************
4950
4951#ifndef __LP64__
4952void IOService::ack_timer_ticked ( void )
4953{
4954	assert(false);
4955}
4956#endif /* !__LP64__ */
4957
4958bool IOService::ackTimerTick( void )
4959{
4960    IOPMinformee *		nextObject;
4961	bool				done = false;
4962
4963	PM_ASSERT_IN_GATE();
4964    switch (fMachineState) {
4965        case kIOPM_OurChangeWaitForPowerSettle:
4966        case kIOPM_ParentChangeWaitForPowerSettle:
4967            // are we waiting for controlling driver to acknowledge?
4968            if ( fDriverTimer > 0 )
4969            {
4970                // yes, decrement timer tick
4971                fDriverTimer--;
4972                if ( fDriverTimer == 0 )
4973                {
4974                    // controlling driver is tardy
4975                    uint64_t nsec = computeTimeDeltaNS(&fDriverCallStartTime);
4976                    OUR_PMLog(kPMLogCtrlDriverTardy, 0, 0);
4977                    setProperty(kIOPMTardyAckSPSKey, kOSBooleanTrue);
4978                    PM_ERROR("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms\n",
4979                        fName, this, fCurrentPowerState, fHeadNotePowerState, NS_TO_MS(nsec));
4980
4981#if LOG_SETPOWER_TIMES
4982                    PMEventDetails *details = PMEventDetails::eventDetails(
4983                                                kIOPMEventTypeSetPowerStateDelayed, // type
4984                                                fName,								// who
4985                                                (uintptr_t)this,					// owner unique
4986                                                NULL,								// interest name
4987                                                (uint8_t)getPowerState(),			// old
4988                                                0,									// new
4989                                                kIOReturnTimeout,					// result
4990                                                NS_TO_US(nsec));					// usec completion time
4991
4992                    getPMRootDomain()->recordAndReleasePMEventGated( details );
4993#endif
4994
4995                    if (gIOKitDebug & kIOLogDebugPower)
4996                    {
4997                        panic("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms",
4998                            fName, this, fCurrentPowerState, fHeadNotePowerState, NS_TO_MS(nsec));
4999                    }
5000                    else
5001					{
5002						// Unblock state machine and pretend driver has acked.
5003						done = true;
5004					}
5005                } else {
5006                    // still waiting, set timer again
5007                    start_ack_timer();
5008                }
5009            }
5010            break;
5011
5012        case kIOPM_NotifyChildrenStart:
5013            // are we waiting for interested parties to acknowledge?
5014            if ( fHeadNotePendingAcks != 0 )
5015            {
5016                // yes, go through the list of interested drivers
5017                nextObject = fInterestedDrivers->firstInList();
5018                // and check each one
5019                while (  nextObject != NULL )
5020                {
5021                    if ( nextObject->timer > 0 )
5022                    {
5023                        nextObject->timer--;
5024                        // this one should have acked by now
5025                        if ( nextObject->timer == 0 )
5026                        {
5027                            uint64_t nsec = computeTimeDeltaNS(&nextObject->startTime);
5028                            OUR_PMLog(kPMLogIntDriverTardy, 0, 0);
5029                            nextObject->whatObject->setProperty(kIOPMTardyAckPSCKey, kOSBooleanTrue);
5030                            PM_ERROR("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) timed out after %d ms\n",
5031                                nextObject->whatObject->getName(),
5032                                (fDriverCallReason == kDriverCallInformPreChange) ? "Will" : "Did",
5033                                nextObject->whatObject, fName, fCurrentPowerState, fHeadNotePowerState,
5034                                NS_TO_MS(nsec));
5035
5036#if LOG_SETPOWER_TIMES
5037                            uint16_t logType = (fDriverCallReason == kDriverCallInformPreChange)
5038                                                ? kIOPMEventTypePSWillChangeTo
5039                                                : kIOPMEventTypePSDidChangeTo;
5040
5041                            PMEventDetails *details = PMEventDetails::eventDetails(
5042                                                        logType,							  // type
5043                                                        fName,								  // who
5044                                                        (uintptr_t)this,					  // owner unique
5045                                                        nextObject->whatObject->getName(),	  // interest name
5046                                                        (uint8_t)fCurrentPowerState,		  // old
5047                                                        (uint8_t)fHeadNotePowerState,		  // new
5048                                                        kIOReturnTimeout,					  // result
5049                                                        NS_TO_US(nsec));					  // usec completion time
5050
5051                            getPMRootDomain()->recordAndReleasePMEventGated( details );
5052#endif
5053
5054                            // Pretend driver has acked.
5055                            fHeadNotePendingAcks--;
5056                        }
5057                    }
5058                    nextObject = fInterestedDrivers->nextInList(nextObject);
5059                }
5060
5061                // is that the last?
5062                if ( fHeadNotePendingAcks == 0 )
5063                {
5064                    // yes, we can continue
5065					done = true;
5066                } else {
5067                    // no, set timer again
5068                    start_ack_timer();
5069                }
5070            }
5071            break;
5072
5073        // TODO: aggreggate this
5074        case kIOPM_OurChangeTellClientsPowerDown:
5075        case kIOPM_OurChangeTellPriorityClientsPowerDown:
5076        case kIOPM_OurChangeNotifyInterestedDriversWillChange:
5077        case kIOPM_ParentChangeTellPriorityClientsPowerDown:
5078        case kIOPM_ParentChangeNotifyInterestedDriversWillChange:
5079        case kIOPM_SyncTellClientsPowerDown:
5080        case kIOPM_SyncTellPriorityClientsPowerDown:
5081        case kIOPM_SyncNotifyWillChange:
5082        case kIOPM_TellCapabilityChangeDone:
5083			// apps didn't respond in time
5084            cleanClientResponses(true);
5085            OUR_PMLog(kPMLogClientTardy, 0, 1);
5086			// tardy equates to approval
5087			done = true;
5088            break;
5089
5090        default:
5091            PM_LOG1("%s: unexpected ack timer tick (state = %d)\n",
5092				getName(), fMachineState);
5093            break;
5094    }
5095	return done;
5096}
5097
5098//*********************************************************************************
5099// [private] start_ack_timer
5100//*********************************************************************************
5101
5102void IOService::start_ack_timer ( void )
5103{
5104	start_ack_timer( ACK_TIMER_PERIOD, kNanosecondScale );
5105}
5106
5107void IOService::start_ack_timer ( UInt32 interval, UInt32 scale )
5108{
5109    AbsoluteTime	deadline;
5110	boolean_t		pending;
5111
5112    clock_interval_to_deadline(interval, scale, &deadline);
5113
5114	retain();
5115    pending = thread_call_enter_delayed(fAckTimer, deadline);
5116	if (pending) release();
5117}
5118
5119//*********************************************************************************
5120// [private] stop_ack_timer
5121//*********************************************************************************
5122
5123void IOService::stop_ack_timer ( void )
5124{
5125	boolean_t		pending;
5126
5127    pending = thread_call_cancel(fAckTimer);
5128	if (pending) release();
5129}
5130
5131//*********************************************************************************
5132// [static] actionAckTimerExpired
5133//
5134// Inside PM work loop's gate.
5135//*********************************************************************************
5136
5137IOReturn
5138IOService::actionAckTimerExpired (
5139	OSObject * target,
5140	void * arg0, void * arg1,
5141	void * arg2, void * arg3 )
5142{
5143	IOService * me = (IOService *) target;
5144	bool		done;
5145
5146	// done will be true if the timer tick unblocks the machine state,
5147	// otherwise no need to signal the work loop.
5148
5149	done = me->ackTimerTick();
5150	if (done && gIOPMWorkQueue)
5151		gIOPMWorkQueue->signalWorkAvailable();
5152
5153	return kIOReturnSuccess;
5154}
5155
5156//*********************************************************************************
5157// ack_timer_expired
5158//
5159// Thread call function. Holds a retain while the callout is in flight.
5160//*********************************************************************************
5161
5162void
5163IOService::ack_timer_expired ( thread_call_param_t arg0, thread_call_param_t arg1 )
5164{
5165	IOService * me = (IOService *) arg0;
5166
5167	if (gIOPMWorkLoop)
5168	{
5169		gIOPMWorkLoop->runAction(&actionAckTimerExpired, me);
5170	}
5171	me->release();
5172}
5173
5174// MARK: -
5175// MARK: Client Messaging
5176
5177//*********************************************************************************
5178// [private] tellSystemCapabilityChange
5179//*********************************************************************************
5180
5181void IOService::tellSystemCapabilityChange( uint32_t nextMS )
5182{
5183	MS_PUSH( nextMS );
5184    fMachineState       = kIOPM_TellCapabilityChangeDone;
5185    fOutOfBandMessage   = kIOMessageSystemCapabilityChange;
5186
5187    if (fIsPreChange)
5188    {
5189        // Notify app first on pre-change.
5190        fOutOfBandParameter = kNotifyCapabilityChangeApps;
5191    }
5192    else
5193    {
5194        // Notify kernel clients first on post-change.
5195        fOutOfBandParameter = kNotifyCapabilityChangePriority;
5196    }
5197
5198    tellClientsWithResponse( fOutOfBandMessage );
5199}
5200
5201//*********************************************************************************
5202// [public] askChangeDown
5203//
5204// Ask registered applications and kernel clients if we can change to a lower
5205// power state.
5206//
5207// Subclass can override this to send a different message type.  Parameter is
5208// the destination state number.
5209//
5210// Return true if we don't have to wait for acknowledgements
5211//*********************************************************************************
5212
5213bool IOService::askChangeDown ( unsigned long stateNum )
5214{
5215    return tellClientsWithResponse( kIOMessageCanDevicePowerOff );
5216}
5217
5218//*********************************************************************************
5219// [private] tellChangeDown1
5220//
5221// Notify registered applications and kernel clients that we are definitely
5222// dropping power.
5223//
5224// Return true if we don't have to wait for acknowledgements
5225//*********************************************************************************
5226
5227bool IOService::tellChangeDown1 ( unsigned long stateNum )
5228{
5229    fOutOfBandParameter = kNotifyApps;
5230    return tellChangeDown(stateNum);
5231}
5232
5233//*********************************************************************************
5234// [private] tellChangeDown2
5235//
5236// Notify priority clients that we are definitely dropping power.
5237//
5238// Return true if we don't have to wait for acknowledgements
5239//*********************************************************************************
5240
5241bool IOService::tellChangeDown2 ( unsigned long stateNum )
5242{
5243    fOutOfBandParameter = kNotifyPriority;
5244    return tellChangeDown(stateNum);
5245}
5246
5247//*********************************************************************************
5248// [public] tellChangeDown
5249//
5250// Notify registered applications and kernel clients that we are definitely
5251// dropping power.
5252//
5253// Subclass can override this to send a different message type.  Parameter is
5254// the destination state number.
5255//
5256// Return true if we don't have to wait for acknowledgements
5257//*********************************************************************************
5258
5259bool IOService::tellChangeDown ( unsigned long stateNum )
5260{
5261    return tellClientsWithResponse( kIOMessageDeviceWillPowerOff );
5262}
5263
5264//*********************************************************************************
5265// cleanClientResponses
5266//
5267//*********************************************************************************
5268
5269static void logAppTimeouts ( OSObject * object, void * arg )
5270{
5271    IOPMInterestContext *   context = (IOPMInterestContext *) arg;
5272    OSObject *              flag;
5273    unsigned int            clientIndex;
5274
5275    if (OSDynamicCast(_IOServiceInterestNotifier, object))
5276    {
5277        // Discover the 'counter' value or index assigned to this client
5278        // when it was notified, by searching for the array index of the
5279        // client in an array holding the cached interested clients.
5280
5281        clientIndex = context->notifyClients->getNextIndexOfObject(object, 0);
5282
5283        if ((clientIndex != (unsigned int) -1) &&
5284            (flag = context->responseArray->getObject(clientIndex)) &&
5285            (flag != kOSBooleanTrue))
5286        {
5287            OSString *logClientID = NULL;
5288            OSNumber *clientID = copyClientIDForNotification(object, context);
5289
5290            if (clientID) {
5291                logClientID = IOCopyLogNameForPID(clientID->unsigned32BitValue());
5292                clientID->release();
5293            }
5294
5295            PM_ERROR(context->errorLog, logClientID ? logClientID->getCStringNoCopy() : "");
5296
5297            // TODO: record message type if possible
5298            IOService::getPMRootDomain()->pmStatsRecordApplicationResponse(
5299                gIOPMStatsApplicationResponseTimedOut,
5300                logClientID ? logClientID->getCStringNoCopy() : "",
5301                0, (30*1000), -1);
5302
5303            if (logClientID)
5304                logClientID->release();
5305        }
5306    }
5307}
5308
5309void IOService::cleanClientResponses ( bool logErrors )
5310{
5311    if (logErrors && fResponseArray)
5312    {
5313        switch ( fOutOfBandParameter ) {
5314            case kNotifyApps:
5315            case kNotifyCapabilityChangeApps:
5316                if (fNotifyClientArray)
5317                {
5318                    IOPMInterestContext context;
5319
5320                    context.responseArray    = fResponseArray;
5321                    context.notifyClients    = fNotifyClientArray;
5322                    context.serialNumber     = fSerialNumber;
5323                    context.messageType      = kIOMessageCopyClientID;
5324                    context.notifyType       = kNotifyApps;
5325                    context.isPreChange      = fIsPreChange;
5326                    context.enableTracing    = false;
5327                    context.us               = this;
5328                    context.maxTimeRequested = 0;
5329                    context.stateNumber      = fHeadNotePowerState;
5330                    context.stateFlags       = fHeadNotePowerArrayEntry->capabilityFlags;
5331                    context.changeFlags      = fHeadNoteChangeFlags;
5332                    context.errorLog         = "PM notification timeout (%s)\n";
5333
5334                    applyToInterested(gIOAppPowerStateInterest, logAppTimeouts, (void *) &context);
5335                }
5336                break;
5337
5338            default:
5339                // kNotifyPriority, kNotifyCapabilityChangePriority
5340                // TODO: identify the priority client that has not acked
5341                PM_ERROR("PM priority notification timeout\n");
5342                if (gIOKitDebug & kIOLogDebugPower)
5343                {
5344                    panic("PM priority notification timeout");
5345                }
5346                break;
5347        }
5348    }
5349
5350    if (fResponseArray)
5351    {
5352        fResponseArray->release();
5353        fResponseArray = NULL;
5354    }
5355    if (fNotifyClientArray)
5356    {
5357        fNotifyClientArray->release();
5358        fNotifyClientArray = NULL;
5359    }
5360}
5361
5362//*********************************************************************************
5363// [protected] tellClientsWithResponse
5364//
5365// Notify registered applications and kernel clients that we are definitely
5366// dropping power.
5367//
5368// Return true if we don't have to wait for acknowledgements
5369//*********************************************************************************
5370
5371bool IOService::tellClientsWithResponse ( int messageType )
5372{
5373    IOPMInterestContext     context;
5374    bool                    isRootDomain = IS_ROOT_DOMAIN;
5375
5376	PM_ASSERT_IN_GATE();
5377    assert( fResponseArray == NULL );
5378    assert( fNotifyClientArray == NULL );
5379
5380    RD_LOG("tellClientsWithResponse( %s, %d )\n",
5381        getIOMessageString(messageType), fOutOfBandParameter);
5382
5383    fResponseArray = OSArray::withCapacity( 1 );
5384    if (!fResponseArray)
5385        goto exit;
5386
5387    fResponseArray->setCapacityIncrement(8);
5388    if (++fSerialNumber == 0)
5389        fSerialNumber++;
5390
5391    context.responseArray    = fResponseArray;
5392    context.notifyClients    = 0;
5393    context.serialNumber     = fSerialNumber;
5394    context.messageType      = messageType;
5395    context.notifyType       = fOutOfBandParameter;
5396    context.isPreChange      = fIsPreChange;
5397    context.enableTracing    = false;
5398    context.us               = this;
5399    context.maxTimeRequested = 0;
5400    context.stateNumber      = fHeadNotePowerState;
5401    context.stateFlags       = fHeadNotePowerArrayEntry->capabilityFlags;
5402    context.changeFlags      = fHeadNoteChangeFlags;
5403    context.messageFilter    = (isRootDomain) ?
5404                               OSMemberFunctionCast(
5405                                    IOPMMessageFilter,
5406                                    this,
5407                                    &IOPMrootDomain::systemMessageFilter) : 0;
5408
5409    switch ( fOutOfBandParameter ) {
5410        case kNotifyApps:
5411            applyToInterested( gIOAppPowerStateInterest,
5412				pmTellAppWithResponse, (void *) &context );
5413
5414            if (isRootDomain &&
5415                (fMachineState != kIOPM_OurChangeTellClientsPowerDown) &&
5416                (fMachineState != kIOPM_SyncTellClientsPowerDown))
5417            {
5418                // Notify capability app for tellChangeDown1()
5419                // but not for askChangeDown().
5420                context.notifyType  = kNotifyCapabilityChangeApps;
5421                context.messageType = kIOMessageSystemCapabilityChange;
5422                applyToInterested( gIOAppPowerStateInterest,
5423                    pmTellCapabilityAppWithResponse, (void *) &context );
5424                context.notifyType  = fOutOfBandParameter;
5425                context.messageType = messageType;
5426            }
5427            context.maxTimeRequested = k30Seconds;
5428
5429            applyToInterested( gIOGeneralInterest,
5430				pmTellClientWithResponse, (void *) &context );
5431
5432            fNotifyClientArray = context.notifyClients;
5433            break;
5434
5435        case kNotifyPriority:
5436            context.enableTracing = isRootDomain;
5437            applyToInterested( gIOPriorityPowerStateInterest,
5438				pmTellClientWithResponse, (void *) &context );
5439
5440            if (isRootDomain)
5441            {
5442                // Notify capability clients for tellChangeDown2().
5443                context.notifyType  = kNotifyCapabilityChangePriority;
5444                context.messageType = kIOMessageSystemCapabilityChange;
5445                applyToInterested( gIOPriorityPowerStateInterest,
5446                    pmTellCapabilityClientWithResponse, (void *) &context );
5447            }
5448            break;
5449
5450        case kNotifyCapabilityChangeApps:
5451            applyToInterested( gIOAppPowerStateInterest,
5452				pmTellCapabilityAppWithResponse, (void *) &context );
5453            fNotifyClientArray = context.notifyClients;
5454            context.maxTimeRequested = k30Seconds;
5455            break;
5456
5457        case kNotifyCapabilityChangePriority:
5458            applyToInterested( gIOPriorityPowerStateInterest,
5459				pmTellCapabilityClientWithResponse, (void *) &context );
5460            break;
5461    }
5462
5463    // do we have to wait for somebody?
5464    if ( !checkForDone() )
5465    {
5466        OUR_PMLog(kPMLogStartAckTimer, context.maxTimeRequested, 0);
5467        if (context.enableTracing)
5468            getPMRootDomain()->traceDetail( context.maxTimeRequested / 1000 );
5469		start_ack_timer( context.maxTimeRequested / 1000, kMillisecondScale );
5470        return false;
5471    }
5472
5473exit:
5474    // everybody responded
5475    if (fResponseArray)
5476    {
5477        fResponseArray->release();
5478        fResponseArray = NULL;
5479    }
5480    if (fNotifyClientArray)
5481    {
5482        fNotifyClientArray->release();
5483        fNotifyClientArray = NULL;
5484    }
5485
5486    return true;
5487}
5488
5489//*********************************************************************************
5490// [static private] pmTellAppWithResponse
5491//
5492// We send a message to an application, and we expect a response, so we compute a
5493// cookie we can identify the response with.
5494//*********************************************************************************
5495
5496void IOService::pmTellAppWithResponse ( OSObject * object, void * arg )
5497{
5498    IOPMInterestContext *   context = (IOPMInterestContext *) arg;
5499    IOServicePM *           pwrMgt = context->us->pwrMgt;
5500    uint32_t                msgIndex, msgRef, msgType;
5501    OSNumber                *clientID = NULL;
5502    proc_t                  proc = NULL;
5503    boolean_t               proc_suspended = FALSE;
5504#if LOG_APP_RESPONSE_TIMES
5505    AbsoluteTime            now;
5506#endif
5507
5508    if (!OSDynamicCast(_IOServiceInterestNotifier, object))
5509        return;
5510
5511    if (context->us == getPMRootDomain())
5512    {
5513        if ((clientID = copyClientIDForNotification(object, context)))
5514        {
5515            uint32_t clientPID = clientID->unsigned32BitValue();
5516            clientID->release();
5517            proc = proc_find(clientPID);
5518
5519            if (proc)
5520            {
5521                proc_suspended = get_task_pidsuspended((task_t) proc->task);
5522                proc_rele(proc);
5523
5524                if (proc_suspended)
5525                {
5526                    logClientIDForNotification(object, context, "PMTellAppWithResponse - Suspended");
5527                    return;
5528                }
5529            }
5530        }
5531    }
5532
5533    if (context->messageFilter &&
5534        !context->messageFilter(context->us, object, context, 0, 0))
5535    {
5536        if (kIOLogDebugPower & gIOKitDebug)
5537        {
5538            logClientIDForNotification(object, context, "DROP App");
5539        }
5540        return;
5541    }
5542
5543    // Create client array (for tracking purposes) only if the service
5544    // has app clients. Usually only root domain does.
5545    if (0 == context->notifyClients)
5546        context->notifyClients = OSArray::withCapacity( 32 );
5547
5548    msgType  = context->messageType;
5549    msgIndex = context->responseArray->getCount();
5550    msgRef   = ((context->serialNumber & 0xFFFF) << 16) + (msgIndex & 0xFFFF);
5551
5552    OUR_PMLog(kPMLogAppNotify, msgType, msgRef);
5553    if (kIOLogDebugPower & gIOKitDebug)
5554    {
5555        logClientIDForNotification(object, context, "MESG App");
5556    }
5557
5558#if LOG_APP_RESPONSE_TIMES
5559    OSNumber * num;
5560    clock_get_uptime(&now);
5561    num = OSNumber::withNumber(AbsoluteTime_to_scalar(&now), sizeof(uint64_t) * 8);
5562    if (num)
5563    {
5564        context->responseArray->setObject(msgIndex, num);
5565        num->release();
5566    }
5567    else
5568#endif
5569    context->responseArray->setObject(msgIndex, kOSBooleanFalse);
5570
5571    if (context->notifyClients)
5572        context->notifyClients->setObject(msgIndex, object);
5573
5574    context->us->messageClient(msgType, object, (void *) msgRef);
5575}
5576
5577//*********************************************************************************
5578// [static private] pmTellClientWithResponse
5579//
5580// We send a message to an in-kernel client, and we expect a response,
5581// so we compute a cookie we can identify the response with.
5582//*********************************************************************************
5583
5584void IOService::pmTellClientWithResponse ( OSObject * object, void * arg )
5585{
5586    IOPowerStateChangeNotification  notify;
5587    IOPMInterestContext *           context = (IOPMInterestContext *) arg;
5588    OSObject *                      replied = kOSBooleanTrue;
5589    _IOServiceInterestNotifier *    notifier;
5590    uint32_t                        msgIndex, msgRef, msgType;
5591    IOReturn                        retCode;
5592
5593    if (context->messageFilter &&
5594        !context->messageFilter(context->us, object, context, 0, 0))
5595    {
5596        if ((kIOLogDebugPower & gIOKitDebug) &&
5597            (OSDynamicCast(_IOServiceInterestNotifier, object)))
5598        {
5599            _IOServiceInterestNotifier *n = (_IOServiceInterestNotifier *) object;
5600            PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
5601                context->us->getName(),
5602                getIOMessageString(context->messageType),
5603                object, n->handler);
5604		}
5605        return;
5606    }
5607
5608    notifier = OSDynamicCast(_IOServiceInterestNotifier, object);
5609    msgType  = context->messageType;
5610    msgIndex = context->responseArray->getCount();
5611    msgRef   = ((context->serialNumber & 0xFFFF) << 16) + (msgIndex & 0xFFFF);
5612
5613    IOServicePM * pwrMgt = context->us->pwrMgt;
5614    if (gIOKitDebug & kIOLogPower) {
5615		OUR_PMLog(kPMLogClientNotify, msgRef, msgType);
5616		if (OSDynamicCast(IOService, object)) {
5617			const char *who = ((IOService *) object)->getName();
5618			gPlatform->PMLog(who, kPMLogClientNotify, (uintptr_t) object, 0);
5619		}
5620        else if (notifier) {
5621			OUR_PMLog(kPMLogClientNotify, (uintptr_t) notifier->handler, 0);
5622        }
5623    }
5624    if ((kIOLogDebugPower & gIOKitDebug) && notifier)
5625    {
5626        PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
5627            context->us->getName(),
5628            getIOMessageString(msgType),
5629            object, notifier->handler);
5630    }
5631
5632    notify.powerRef    = (void *)(uintptr_t) msgRef;
5633    notify.returnValue = 0;
5634    notify.stateNumber = context->stateNumber;
5635    notify.stateFlags  = context->stateFlags;
5636
5637    if (context->enableTracing && (notifier != 0))
5638    {
5639        uint32_t detail = ((msgIndex & 0xff) << 24) |
5640                          ((msgType & 0xfff) << 12) |
5641                          (((uintptr_t) notifier->handler) & 0xfff);
5642        getPMRootDomain()->traceDetail( detail );
5643    }
5644
5645    retCode = context->us->messageClient(msgType, object, (void *) &notify, sizeof(notify));
5646
5647    if (kIOReturnSuccess == retCode)
5648    {
5649        if (0 == notify.returnValue) {
5650			OUR_PMLog(kPMLogClientAcknowledge, msgRef, (uintptr_t) object);
5651        } else {
5652            replied = kOSBooleanFalse;
5653            if ( notify.returnValue > context->maxTimeRequested )
5654            {
5655                if (notify.returnValue > kPriorityClientMaxWait)
5656                {
5657                    context->maxTimeRequested = kPriorityClientMaxWait;
5658                    PM_ERROR("%s: client %p returned %llu for %s\n",
5659                        context->us->getName(),
5660                        notifier ? (void *)  notifier->handler : object,
5661                        (uint64_t) notify.returnValue,
5662                        getIOMessageString(msgType));
5663                }
5664                else
5665                    context->maxTimeRequested = notify.returnValue;
5666            }
5667        }
5668    } else {
5669        // not a client of ours
5670        // so we won't be waiting for response
5671		OUR_PMLog(kPMLogClientAcknowledge, msgRef, 0);
5672    }
5673
5674    context->responseArray->setObject(msgIndex, replied);
5675}
5676
5677//*********************************************************************************
5678// [static private] pmTellCapabilityAppWithResponse
5679//*********************************************************************************
5680
5681void IOService::pmTellCapabilityAppWithResponse ( OSObject * object, void * arg )
5682{
5683    IOPMSystemCapabilityChangeParameters msgArg;
5684    IOPMInterestContext *       context = (IOPMInterestContext *) arg;
5685    OSObject *                  replied = kOSBooleanTrue;
5686    IOServicePM *               pwrMgt = context->us->pwrMgt;
5687    uint32_t                    msgIndex, msgRef, msgType;
5688#if LOG_APP_RESPONSE_TIMES
5689    AbsoluteTime                now;
5690#endif
5691
5692    if (!OSDynamicCast(_IOServiceInterestNotifier, object))
5693        return;
5694
5695    memset(&msgArg, 0, sizeof(msgArg));
5696    if (context->messageFilter &&
5697        !context->messageFilter(context->us, object, context, &msgArg, &replied))
5698    {
5699        return;
5700    }
5701
5702    // Create client array (for tracking purposes) only if the service
5703    // has app clients. Usually only root domain does.
5704    if (0 == context->notifyClients)
5705        context->notifyClients = OSArray::withCapacity( 32 );
5706
5707    msgType  = context->messageType;
5708    msgIndex = context->responseArray->getCount();
5709    msgRef   = ((context->serialNumber & 0xFFFF) << 16) + (msgIndex & 0xFFFF);
5710
5711    OUR_PMLog(kPMLogAppNotify, msgType, msgRef);
5712    if (kIOLogDebugPower & gIOKitDebug)
5713    {
5714        // Log client pid/name and client array index.
5715        OSNumber * clientID = NULL;
5716        OSString * clientIDString = NULL;;
5717        context->us->messageClient(kIOMessageCopyClientID, object, &clientID);
5718        if (clientID) {
5719            clientIDString = IOCopyLogNameForPID(clientID->unsigned32BitValue());
5720        }
5721
5722        PM_LOG("%s MESG App(%u) %s, wait %u, %s\n",
5723            context->us->getName(),
5724            msgIndex, getIOMessageString(msgType),
5725            (replied != kOSBooleanTrue),
5726            clientIDString ? clientIDString->getCStringNoCopy() : "");
5727        if (clientID) clientID->release();
5728        if (clientIDString) clientIDString->release();
5729    }
5730
5731    msgArg.notifyRef = msgRef;
5732    msgArg.maxWaitForReply = 0;
5733
5734    if (replied == kOSBooleanTrue)
5735    {
5736        msgArg.notifyRef = 0;
5737        context->responseArray->setObject(msgIndex, kOSBooleanTrue);
5738        if (context->notifyClients)
5739            context->notifyClients->setObject(msgIndex, kOSBooleanTrue);
5740    }
5741    else
5742    {
5743#if LOG_APP_RESPONSE_TIMES
5744        OSNumber * num;
5745        clock_get_uptime(&now);
5746        num = OSNumber::withNumber(AbsoluteTime_to_scalar(&now), sizeof(uint64_t) * 8);
5747        if (num)
5748        {
5749            context->responseArray->setObject(msgIndex, num);
5750            num->release();
5751        }
5752        else
5753#endif
5754        context->responseArray->setObject(msgIndex, kOSBooleanFalse);
5755
5756        if (context->notifyClients)
5757            context->notifyClients->setObject(msgIndex, object);
5758    }
5759
5760    context->us->messageClient(msgType, object, (void *) &msgArg, sizeof(msgArg));
5761}
5762
5763//*********************************************************************************
5764// [static private] pmTellCapabilityClientWithResponse
5765//*********************************************************************************
5766
5767void IOService::pmTellCapabilityClientWithResponse(
5768    OSObject * object, void * arg )
5769{
5770    IOPMSystemCapabilityChangeParameters msgArg;
5771    IOPMInterestContext *           context = (IOPMInterestContext *) arg;
5772    OSObject *                      replied = kOSBooleanTrue;
5773    _IOServiceInterestNotifier *    notifier;
5774    uint32_t                        msgIndex, msgRef, msgType;
5775    IOReturn                        retCode;
5776
5777    memset(&msgArg, 0, sizeof(msgArg));
5778    if (context->messageFilter &&
5779        !context->messageFilter(context->us, object, context, &msgArg, 0))
5780    {
5781        if ((kIOLogDebugPower & gIOKitDebug) &&
5782            (OSDynamicCast(_IOServiceInterestNotifier, object)))
5783        {
5784            _IOServiceInterestNotifier *n = (_IOServiceInterestNotifier *) object;
5785            PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
5786                context->us->getName(),
5787                getIOMessageString(context->messageType),
5788                object, n->handler);
5789		}
5790        return;
5791    }
5792
5793    notifier = OSDynamicCast(_IOServiceInterestNotifier, object);
5794    msgType  = context->messageType;
5795    msgIndex = context->responseArray->getCount();
5796    msgRef   = ((context->serialNumber & 0xFFFF) << 16) + (msgIndex & 0xFFFF);
5797
5798    IOServicePM * pwrMgt = context->us->pwrMgt;
5799    if (gIOKitDebug & kIOLogPower) {
5800		OUR_PMLog(kPMLogClientNotify, msgRef, msgType);
5801		if (OSDynamicCast(IOService, object)) {
5802			const char *who = ((IOService *) object)->getName();
5803			gPlatform->PMLog(who, kPMLogClientNotify, (uintptr_t) object, 0);
5804		}
5805        else if (notifier) {
5806			OUR_PMLog(kPMLogClientNotify, (uintptr_t) notifier->handler, 0);
5807		}
5808    }
5809    if ((kIOLogDebugPower & gIOKitDebug) && notifier)
5810    {
5811        PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
5812            context->us->getName(),
5813            getIOMessageString(msgType),
5814            object, notifier->handler);
5815    }
5816
5817    msgArg.notifyRef = msgRef;
5818    msgArg.maxWaitForReply = 0;
5819
5820    if (context->enableTracing && (notifier != 0))
5821    {
5822        uint32_t detail = ((msgIndex & 0xff) << 24) |
5823                          ((msgType & 0xfff) << 12) |
5824                          (((uintptr_t) notifier->handler) & 0xfff);
5825        getPMRootDomain()->traceDetail( detail );
5826    }
5827
5828    retCode = context->us->messageClient(
5829        msgType, object, (void *) &msgArg, sizeof(msgArg));
5830
5831    if ( kIOReturnSuccess == retCode )
5832    {
5833        if ( 0 == msgArg.maxWaitForReply )
5834        {
5835            // client doesn't want time to respond
5836			OUR_PMLog(kPMLogClientAcknowledge, msgRef, (uintptr_t) object);
5837        }
5838        else
5839        {
5840            replied = kOSBooleanFalse;
5841            if ( msgArg.maxWaitForReply > context->maxTimeRequested )
5842            {
5843                if (msgArg.maxWaitForReply > kCapabilityClientMaxWait)
5844                {
5845                    context->maxTimeRequested = kCapabilityClientMaxWait;
5846                    PM_ERROR("%s: client %p returned %u for %s\n",
5847                        context->us->getName(),
5848                        notifier ? (void *) notifier->handler : object,
5849                        msgArg.maxWaitForReply,
5850                        getIOMessageString(msgType));
5851                }
5852                else
5853                    context->maxTimeRequested = msgArg.maxWaitForReply;
5854            }
5855        }
5856    }
5857    else
5858    {
5859        // not a client of ours
5860        // so we won't be waiting for response
5861		OUR_PMLog(kPMLogClientAcknowledge, msgRef, 0);
5862    }
5863
5864    context->responseArray->setObject(msgIndex, replied);
5865}
5866
5867//*********************************************************************************
5868// [public] tellNoChangeDown
5869//
5870// Notify registered applications and kernel clients that we are not
5871// dropping power.
5872//
5873// Subclass can override this to send a different message type.  Parameter is
5874// the aborted destination state number.
5875//*********************************************************************************
5876
5877void IOService::tellNoChangeDown ( unsigned long )
5878{
5879    return tellClients( kIOMessageDeviceWillNotPowerOff );
5880}
5881
5882//*********************************************************************************
5883// [public] tellChangeUp
5884//
5885// Notify registered applications and kernel clients that we are raising power.
5886//
5887// Subclass can override this to send a different message type.  Parameter is
5888// the aborted destination state number.
5889//*********************************************************************************
5890
5891void IOService::tellChangeUp ( unsigned long )
5892{
5893    return tellClients( kIOMessageDeviceHasPoweredOn );
5894}
5895
5896//*********************************************************************************
5897// [protected] tellClients
5898//
5899// Notify registered applications and kernel clients of something.
5900//*********************************************************************************
5901
5902void IOService::tellClients ( int messageType )
5903{
5904    IOPMInterestContext     context;
5905
5906    RD_LOG("tellClients( %s )\n", getIOMessageString(messageType));
5907
5908    memset(&context, 0, sizeof(context));
5909    context.messageType   = messageType;
5910    context.isPreChange   = fIsPreChange;
5911    context.us            = this;
5912    context.stateNumber   = fHeadNotePowerState;
5913    context.stateFlags    = fHeadNotePowerArrayEntry->capabilityFlags;
5914    context.changeFlags   = fHeadNoteChangeFlags;
5915    context.messageFilter = (IS_ROOT_DOMAIN) ?
5916                            OSMemberFunctionCast(
5917                                IOPMMessageFilter,
5918                                this,
5919                                &IOPMrootDomain::systemMessageFilter) : 0;
5920
5921    context.notifyType    = kNotifyPriority;
5922    applyToInterested( gIOPriorityPowerStateInterest,
5923        tellKernelClientApplier, (void *) &context );
5924
5925    context.notifyType    = kNotifyApps;
5926    applyToInterested( gIOAppPowerStateInterest,
5927        tellAppClientApplier, (void *) &context );
5928
5929    applyToInterested( gIOGeneralInterest,
5930        tellKernelClientApplier, (void *) &context );
5931}
5932
5933//*********************************************************************************
5934// [private] tellKernelClientApplier
5935//
5936// Message a kernel client.
5937//*********************************************************************************
5938
5939static void tellKernelClientApplier ( OSObject * object, void * arg )
5940{
5941    IOPowerStateChangeNotification	notify;
5942    IOPMInterestContext *           context = (IOPMInterestContext *) arg;
5943
5944    if (context->messageFilter &&
5945        !context->messageFilter(context->us, object, context, 0, 0))
5946    {
5947        if ((kIOLogDebugPower & gIOKitDebug) &&
5948            (OSDynamicCast(_IOServiceInterestNotifier, object)))
5949        {
5950            _IOServiceInterestNotifier *n = (_IOServiceInterestNotifier *) object;
5951            PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
5952                context->us->getName(),
5953                IOService::getIOMessageString(context->messageType),
5954                object, n->handler);
5955		}
5956        return;
5957    }
5958
5959    notify.powerRef     = (void *) 0;
5960    notify.returnValue	= 0;
5961    notify.stateNumber	= context->stateNumber;
5962    notify.stateFlags	= context->stateFlags;
5963
5964    context->us->messageClient(context->messageType, object, &notify, sizeof(notify));
5965
5966    if ((kIOLogDebugPower & gIOKitDebug) &&
5967        (OSDynamicCast(_IOServiceInterestNotifier, object)))
5968    {
5969        _IOServiceInterestNotifier *n = (_IOServiceInterestNotifier *) object;
5970        PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
5971            context->us->getName(),
5972            IOService::getIOMessageString(context->messageType),
5973            object, n->handler);
5974    }
5975}
5976
5977static OSNumber * copyClientIDForNotification(
5978    OSObject *object,
5979    IOPMInterestContext *context)
5980{
5981    OSNumber *clientID = NULL;
5982    context->us->messageClient(kIOMessageCopyClientID, object, &clientID);
5983    return clientID;
5984}
5985
5986static void logClientIDForNotification(
5987    OSObject *object,
5988    IOPMInterestContext *context,
5989    const char *logString)
5990{
5991    OSString *logClientID = NULL;
5992    OSNumber *clientID = copyClientIDForNotification(object, context);
5993
5994    if (logString)
5995    {
5996        if (clientID)
5997            logClientID = IOCopyLogNameForPID(clientID->unsigned32BitValue());
5998
5999        PM_LOG("%s %s %s, %s\n",
6000            context->us->getName(), logString,
6001            IOService::getIOMessageString(context->messageType),
6002            logClientID ? logClientID->getCStringNoCopy() : "");
6003
6004        if (logClientID)
6005            logClientID->release();
6006    }
6007
6008    if (clientID)
6009        clientID->release();
6010
6011    return;
6012}
6013
6014
6015static void tellAppClientApplier ( OSObject * object, void * arg )
6016{
6017    IOPMInterestContext * context = (IOPMInterestContext *) arg;
6018    OSNumber            * clientID = NULL;
6019    proc_t                proc = NULL;
6020    boolean_t             proc_suspended = FALSE;
6021
6022    if (context->us == IOService::getPMRootDomain())
6023    {
6024        if ((clientID = copyClientIDForNotification(object, context)))
6025        {
6026            uint32_t clientPID = clientID->unsigned32BitValue();
6027            clientID->release();
6028            proc = proc_find(clientPID);
6029
6030            if (proc)
6031            {
6032                proc_suspended = get_task_pidsuspended((task_t) proc->task);
6033                proc_rele(proc);
6034
6035                if (proc_suspended)
6036                {
6037                    logClientIDForNotification(object, context, "tellAppClientApplier - Suspended");
6038                    return;
6039                }
6040            }
6041        }
6042    }
6043
6044    if (context->messageFilter &&
6045        !context->messageFilter(context->us, object, context, 0, 0))
6046    {
6047        if (kIOLogDebugPower & gIOKitDebug)
6048        {
6049            logClientIDForNotification(object, context, "DROP App");
6050        }
6051        return;
6052    }
6053
6054    if (kIOLogDebugPower & gIOKitDebug)
6055    {
6056        logClientIDForNotification(object, context, "MESG App");
6057    }
6058
6059    context->us->messageClient(context->messageType, object, 0);
6060}
6061
6062//*********************************************************************************
6063// [private] checkForDone
6064//*********************************************************************************
6065
6066bool IOService::checkForDone ( void )
6067{
6068    int			i = 0;
6069    OSObject *	theFlag;
6070
6071    if (fResponseArray == NULL) {
6072        return true;
6073    }
6074
6075    for (i = 0; ; i++) {
6076        theFlag = fResponseArray->getObject(i);
6077
6078        if (NULL == theFlag) {
6079            break;
6080        }
6081
6082        if (kOSBooleanTrue != theFlag) {
6083            return false;
6084        }
6085    }
6086    return true;
6087}
6088
6089//*********************************************************************************
6090// [public] responseValid
6091//*********************************************************************************
6092
6093bool IOService::responseValid ( uint32_t refcon, int pid )
6094{
6095    UInt16			serialComponent;
6096    UInt16			ordinalComponent;
6097    OSObject *		theFlag;
6098
6099    serialComponent  = (refcon >> 16) & 0xFFFF;
6100    ordinalComponent = (refcon & 0xFFFF);
6101
6102    if ( serialComponent != fSerialNumber )
6103    {
6104        return false;
6105    }
6106
6107    if ( fResponseArray == NULL )
6108    {
6109        return false;
6110    }
6111
6112    theFlag = fResponseArray->getObject(ordinalComponent);
6113
6114    if ( theFlag == 0 )
6115    {
6116        return false;
6117    }
6118
6119    OSNumber * num;
6120    if ((num = OSDynamicCast(OSNumber, theFlag)))
6121    {
6122#if LOG_APP_RESPONSE_TIMES
6123        AbsoluteTime	now;
6124        AbsoluteTime	start;
6125        uint64_t        nsec;
6126        OSString        *name = IOCopyLogNameForPID(pid);
6127
6128        clock_get_uptime(&now);
6129        AbsoluteTime_to_scalar(&start) = num->unsigned64BitValue();
6130        SUB_ABSOLUTETIME(&now, &start);
6131        absolutetime_to_nanoseconds(now, &nsec);
6132
6133        PMEventDetails *details = PMEventDetails::eventDetails(
6134                                    kIOPMEventTypeAppResponse,				// type
6135                                    name ? name->getCStringNoCopy() : "",   // who
6136                                    (uintptr_t)pid,							// owner unique
6137                                    NULL,									// interest name
6138                                    0,										// old
6139                                    0,										// new
6140                                    0,										// result
6141                                    NS_TO_US(nsec));						// usec completion time
6142
6143        getPMRootDomain()->recordAndReleasePMEventGated( details );
6144
6145        if (kIOLogDebugPower & gIOKitDebug)
6146        {
6147            PM_LOG("Ack(%u) %u ms\n",
6148                (uint32_t) ordinalComponent,
6149                NS_TO_MS(nsec));
6150        }
6151
6152        // > 100 ms
6153        if (nsec > LOG_APP_RESPONSE_TIMES)
6154        {
6155            PM_LOG("PM response took %d ms (%s)\n", NS_TO_MS(nsec),
6156                name ? name->getCStringNoCopy() : "");
6157
6158            if (nsec > LOG_APP_RESPONSE_MSG_TRACER)
6159            {
6160                // TODO: populate the messageType argument
6161                getPMRootDomain()->pmStatsRecordApplicationResponse(
6162                    gIOPMStatsApplicationResponseSlow,
6163                    name ? name->getCStringNoCopy() : "", 0,
6164                    NS_TO_MS(nsec), pid);
6165            }
6166        }
6167
6168        if (name)
6169            name->release();
6170#endif
6171        theFlag = kOSBooleanFalse;
6172    }
6173
6174    if ( kOSBooleanFalse == theFlag )
6175    {
6176        fResponseArray->replaceObject(ordinalComponent, kOSBooleanTrue);
6177    }
6178
6179    return true;
6180}
6181
6182//*********************************************************************************
6183// [public] allowPowerChange
6184//
6185// Our power state is about to lower, and we have notified applications
6186// and kernel clients, and one of them has acknowledged.  If this is the last to do
6187// so, and all acknowledgements are positive, we continue with the power change.
6188//*********************************************************************************
6189
6190IOReturn IOService::allowPowerChange ( unsigned long refcon )
6191{
6192	IOPMRequest * request;
6193
6194    if ( !initialized )
6195    {
6196        // we're unloading
6197        return kIOReturnSuccess;
6198    }
6199
6200	request = acquirePMRequest( this, kIOPMRequestTypeAllowPowerChange );
6201	if (!request)
6202		return kIOReturnNoMemory;
6203
6204	request->fArg0 = (void *) refcon;
6205	request->fArg1 = (void *) proc_selfpid();
6206	request->fArg2 = (void *) 0;
6207	submitPMRequest( request );
6208
6209	return kIOReturnSuccess;
6210}
6211
6212#ifndef __LP64__
6213IOReturn IOService::serializedAllowPowerChange2 ( unsigned long refcon )
6214{
6215	// [deprecated] public
6216	return kIOReturnUnsupported;
6217}
6218#endif /* !__LP64__ */
6219
6220//*********************************************************************************
6221// [public] cancelPowerChange
6222//
6223// Our power state is about to lower, and we have notified applications
6224// and kernel clients, and one of them has vetoed the change.  If this is the last
6225// client to respond, we abandon the power change.
6226//*********************************************************************************
6227
6228IOReturn IOService::cancelPowerChange ( unsigned long refcon )
6229{
6230	IOPMRequest *   request;
6231    OSString *      name;
6232
6233    if ( !initialized )
6234    {
6235        // we're unloading
6236        return kIOReturnSuccess;
6237    }
6238
6239    name = IOCopyLogNameForPID(proc_selfpid());
6240    PM_ERROR("PM notification cancel (%s)\n", name ? name->getCStringNoCopy() : "");
6241
6242	request = acquirePMRequest( this, kIOPMRequestTypeCancelPowerChange );
6243	if (!request)
6244    {
6245        if (name)
6246            name->release();
6247        return kIOReturnNoMemory;
6248    }
6249
6250    request->fArg0 = (void *) refcon;
6251    request->fArg1 = (void *) proc_selfpid();
6252    request->fArg2 = (void *) name;
6253    submitPMRequest( request );
6254
6255    return kIOReturnSuccess;
6256}
6257
6258#ifndef __LP64__
6259IOReturn IOService::serializedCancelPowerChange2 ( unsigned long refcon )
6260{
6261	// [deprecated] public
6262	return kIOReturnUnsupported;
6263}
6264
6265//*********************************************************************************
6266// PM_Clamp_Timer_Expired
6267//
6268// called when clamp timer expires...set power state to 0.
6269//*********************************************************************************
6270
6271void IOService::PM_Clamp_Timer_Expired ( void )
6272{
6273}
6274
6275//*********************************************************************************
6276// clampPowerOn
6277//
6278// Set to highest available power state for a minimum of duration milliseconds
6279//*********************************************************************************
6280
6281void IOService::clampPowerOn ( unsigned long duration )
6282{
6283}
6284#endif /* !__LP64__ */
6285
6286// MARK: -
6287// MARK: Driver Overrides
6288
6289//*********************************************************************************
6290// [public] setPowerState
6291//
6292// Does nothing here.  This should be implemented in a subclass driver.
6293//*********************************************************************************
6294
6295IOReturn IOService::setPowerState (
6296	unsigned long powerStateOrdinal, IOService * whatDevice )
6297{
6298    return IOPMNoErr;
6299}
6300
6301//*********************************************************************************
6302// [public] maxCapabilityForDomainState
6303//
6304// Finds the highest power state in the array whose input power
6305// requirement is equal to the input parameter.  Where a more intelligent
6306// decision is possible, override this in the subclassed driver.
6307//*********************************************************************************
6308
6309unsigned long IOService::maxCapabilityForDomainState ( IOPMPowerFlags domainState )
6310{
6311   int i;
6312
6313   if (fNumberOfPowerStates == 0 )
6314   {
6315       return 0;
6316   }
6317   for ( i = fNumberOfPowerStates - 1; i >= 0; i-- )
6318   {
6319       if ( (domainState & fPowerStates[i].inputPowerFlags) ==
6320			               fPowerStates[i].inputPowerFlags )
6321       {
6322           return i;
6323       }
6324   }
6325   return 0;
6326}
6327
6328//*********************************************************************************
6329// [public] initialPowerStateForDomainState
6330//
6331// Finds the highest power state in the array whose input power
6332// requirement is equal to the input parameter.  Where a more intelligent
6333// decision is possible, override this in the subclassed driver.
6334//*********************************************************************************
6335
6336unsigned long IOService::initialPowerStateForDomainState ( IOPMPowerFlags domainState )
6337{
6338    int i;
6339
6340    if (fNumberOfPowerStates == 0 )
6341    {
6342        return 0;
6343    }
6344    for ( i = fNumberOfPowerStates - 1; i >= 0; i-- )
6345    {
6346        if ( (domainState & fPowerStates[i].inputPowerFlags) ==
6347			fPowerStates[i].inputPowerFlags )
6348        {
6349            return i;
6350        }
6351    }
6352    return 0;
6353}
6354
6355//*********************************************************************************
6356// [public] powerStateForDomainState
6357//
6358// Finds the highest power state in the array whose input power
6359// requirement is equal to the input parameter.  Where a more intelligent
6360// decision is possible, override this in the subclassed driver.
6361//*********************************************************************************
6362
6363unsigned long IOService::powerStateForDomainState ( IOPMPowerFlags domainState )
6364{
6365    int i;
6366
6367    if (fNumberOfPowerStates == 0 )
6368    {
6369        return 0;
6370    }
6371    for ( i = fNumberOfPowerStates - 1; i >= 0; i-- )
6372    {
6373        if ( (domainState & fPowerStates[i].inputPowerFlags) ==
6374			fPowerStates[i].inputPowerFlags )
6375        {
6376            return i;
6377        }
6378    }
6379    return 0;
6380}
6381
6382#ifndef __LP64__
6383//*********************************************************************************
6384// [deprecated] didYouWakeSystem
6385//
6386// Does nothing here.  This should be implemented in a subclass driver.
6387//*********************************************************************************
6388
6389bool IOService::didYouWakeSystem ( void )
6390{
6391    return false;
6392}
6393#endif /* !__LP64__ */
6394
6395//*********************************************************************************
6396// [public] powerStateWillChangeTo
6397//
6398// Does nothing here.  This should be implemented in a subclass driver.
6399//*********************************************************************************
6400
6401IOReturn IOService::powerStateWillChangeTo ( IOPMPowerFlags, unsigned long, IOService * )
6402{
6403    return kIOPMAckImplied;
6404}
6405
6406//*********************************************************************************
6407// [public] powerStateDidChangeTo
6408//
6409// Does nothing here.  This should be implemented in a subclass driver.
6410//*********************************************************************************
6411
6412IOReturn IOService::powerStateDidChangeTo ( IOPMPowerFlags, unsigned long, IOService * )
6413{
6414    return kIOPMAckImplied;
6415}
6416
6417//*********************************************************************************
6418// [protected] powerChangeDone
6419//
6420// Called from PM work loop thread.
6421// Does nothing here.  This should be implemented in a subclass policy-maker.
6422//*********************************************************************************
6423
6424void IOService::powerChangeDone ( unsigned long )
6425{
6426}
6427
6428#ifndef __LP64__
6429//*********************************************************************************
6430// [deprecated] newTemperature
6431//
6432// Does nothing here.  This should be implemented in a subclass driver.
6433//*********************************************************************************
6434
6435IOReturn IOService::newTemperature ( long currentTemp, IOService * whichZone )
6436{
6437    return IOPMNoErr;
6438}
6439#endif /* !__LP64__ */
6440
6441//*********************************************************************************
6442// [public] systemWillShutdown
6443//
6444// System shutdown and restart notification.
6445//*********************************************************************************
6446
6447void IOService::systemWillShutdown( IOOptionBits specifier )
6448{
6449	IOPMrootDomain * rootDomain = IOService::getPMRootDomain();
6450	if (rootDomain)
6451		rootDomain->acknowledgeSystemWillShutdown( this );
6452}
6453
6454// MARK: -
6455// MARK: PM State Machine
6456
6457//*********************************************************************************
6458// [private static] acquirePMRequest
6459//*********************************************************************************
6460
6461IOPMRequest *
6462IOService::acquirePMRequest( IOService * target, IOOptionBits requestType,
6463                             IOPMRequest * active )
6464{
6465	IOPMRequest * request;
6466
6467	assert(target);
6468
6469	request = IOPMRequest::create();
6470	if (request)
6471	{
6472		request->init( target, requestType );
6473        if (active)
6474        {
6475            IOPMRequest * root = active->getRootRequest();
6476            if (root) request->attachRootRequest(root);
6477        }
6478    }
6479	else
6480	{
6481        PM_ERROR("%s: No memory for PM request type 0x%x\n",
6482            target->getName(), (uint32_t) requestType);
6483	}
6484	return request;
6485}
6486
6487//*********************************************************************************
6488// [private static] releasePMRequest
6489//*********************************************************************************
6490
6491void IOService::releasePMRequest( IOPMRequest * request )
6492{
6493	if (request)
6494	{
6495		request->reset();
6496		request->release();
6497	}
6498}
6499
6500//*********************************************************************************
6501// [private] submitPMRequest
6502//*********************************************************************************
6503
6504void IOService::submitPMRequest( IOPMRequest * request )
6505{
6506	assert( request );
6507	assert( gIOPMReplyQueue );
6508	assert( gIOPMRequestQueue );
6509
6510	PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
6511		(long)request->getType(), request,
6512		request->getTarget(), request->getTarget()->getName(),
6513		request->fArg0, request->fArg1, request->fArg2);
6514
6515	if (request->isReplyType())
6516		gIOPMReplyQueue->queuePMRequest( request );
6517	else
6518		gIOPMRequestQueue->queuePMRequest( request );
6519}
6520
6521void IOService::submitPMRequest( IOPMRequest ** requests, IOItemCount count )
6522{
6523	assert( requests );
6524	assert( count > 0 );
6525	assert( gIOPMRequestQueue );
6526
6527	for (IOItemCount i = 0; i < count; i++)
6528	{
6529		IOPMRequest * req = requests[i];
6530		PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
6531			(long)req->getType(), req,
6532			req->getTarget(), req->getTarget()->getName(),
6533			req->fArg0, req->fArg1, req->fArg2);
6534	}
6535
6536	gIOPMRequestQueue->queuePMRequestChain( requests, count );
6537}
6538
6539//*********************************************************************************
6540// [private] servicePMRequestQueue
6541//
6542// Called from IOPMRequestQueue::checkForWork().
6543//*********************************************************************************
6544
6545bool IOService::servicePMRequestQueue(
6546	IOPMRequest *		request,
6547	IOPMRequestQueue *	queue )
6548{
6549    bool more;
6550
6551    if (initialized)
6552    {
6553        // Work queue will immediately execute the queue'd request if possible.
6554        // If execution blocks, the work queue will wait for a producer signal.
6555        // Only need to signal more when completing attached requests.
6556
6557        more = gIOPMWorkQueue->queuePMRequest(request, pwrMgt);
6558        return more;
6559    }
6560
6561    // Calling PM without PMinit() is not allowed, fail the request.
6562
6563    PM_LOG("%s: PM not initialized\n", getName());
6564	fAdjustPowerScheduled = false;
6565	more = gIOPMFreeQueue->queuePMRequest(request);
6566    if (more) gIOPMWorkQueue->incrementProducerCount();
6567	return more;
6568}
6569
6570//*********************************************************************************
6571// [private] servicePMFreeQueue
6572//
6573// Called from IOPMCompletionQueue::checkForWork().
6574//*********************************************************************************
6575
6576bool IOService::servicePMFreeQueue(
6577	IOPMRequest *		  request,
6578	IOPMCompletionQueue * queue )
6579{
6580	bool            more = request->getNextRequest();
6581    IOPMRequest *   root = request->getRootRequest();
6582
6583    if (root && (root != request))
6584        more = true;
6585    if (more)
6586        gIOPMWorkQueue->incrementProducerCount();
6587
6588	releasePMRequest( request );
6589	return more;
6590}
6591
6592//*********************************************************************************
6593// [private] retirePMRequest
6594//
6595// Called by IOPMWorkQueue to retire a completed request.
6596//*********************************************************************************
6597
6598bool IOService::retirePMRequest( IOPMRequest * request, IOPMWorkQueue * queue )
6599{
6600	assert(request && queue);
6601
6602	PM_LOG1("[- %02x] %p [%p %s] state %d, busy %d\n",
6603		request->getType(), request, this, getName(),
6604		fMachineState, gIOPMBusyCount);
6605
6606	// Catch requests created by idleTimerExpired().
6607
6608	if ((request->getType() == kIOPMRequestTypeActivityTickle) &&
6609	    (request->fArg1     == (void *) false))
6610	{
6611		// Idle timer expiration - power drop request completed.
6612		// Restart the idle timer if deviceDesire can go lower, otherwise set
6613		// a flag so we know to restart idle timer when fDeviceDesire > 0.
6614
6615		if (fDeviceDesire > 0)
6616		{
6617            fActivityTickleCount = 0;
6618			clock_get_uptime(&fIdleTimerStartTime);
6619			start_PM_idle_timer();
6620		}
6621        else if (fHasAdvisoryDesire)
6622        {
6623			start_PM_idle_timer();
6624        }
6625		else
6626        {
6627			fIdleTimerStopped = true;
6628        }
6629    }
6630
6631    // If the request is linked, then Work queue has already incremented its
6632    // producer count.
6633
6634	return (gIOPMFreeQueue->queuePMRequest( request ));
6635}
6636
6637//*********************************************************************************
6638// [private] isPMBlocked
6639//
6640// Check if machine state transition is blocked.
6641//*********************************************************************************
6642
6643bool IOService::isPMBlocked ( IOPMRequest * request, int count )
6644{
6645	int	reason = 0;
6646
6647	do {
6648		if (kIOPM_Finished == fMachineState)
6649			break;
6650
6651		if (kIOPM_DriverThreadCallDone == fMachineState)
6652		{
6653            // 5 = kDriverCallInformPreChange
6654            // 6 = kDriverCallInformPostChange
6655            // 7 = kDriverCallSetPowerState
6656			if (fDriverCallBusy)
6657                reason = 5 + fDriverCallReason;
6658			break;
6659		}
6660
6661		// Waiting on driver's setPowerState() timeout.
6662		if (fDriverTimer)
6663		{
6664			reason = 1; break;
6665		}
6666
6667		// Child or interested driver acks pending.
6668		if (fHeadNotePendingAcks)
6669		{
6670			reason = 2; break;
6671		}
6672
6673		// Waiting on apps or priority power interest clients.
6674		if (fResponseArray)
6675		{
6676			reason = 3; break;
6677		}
6678
6679		// Waiting on settle timer expiration.
6680		if (fSettleTimeUS)
6681		{
6682			reason = 4; break;
6683		}
6684	} while (false);
6685
6686	fWaitReason = reason;
6687
6688	if (reason)
6689	{
6690		if (count)
6691		{
6692			PM_LOG1("[B %02x] %p [%p %s] state %d, reason %d\n",
6693				request->getType(), request, this, getName(),
6694				fMachineState, reason);
6695		}
6696
6697		return true;
6698	}
6699
6700	return false;
6701}
6702
6703//*********************************************************************************
6704// [private] servicePMRequest
6705//
6706// Service a request from our work queue.
6707//*********************************************************************************
6708
6709bool IOService::servicePMRequest( IOPMRequest * request, IOPMWorkQueue * queue )
6710{
6711	bool	done = false;
6712	int		loop = 0;
6713
6714	assert(request && queue);
6715
6716	while (isPMBlocked(request, loop++) == false)
6717	{
6718		PM_LOG1("[W %02x] %p [%p %s] state %d\n",
6719			request->getType(), request, this, getName(), fMachineState);
6720
6721		gIOPMRequest = request;
6722        gIOPMWorkCount++;
6723
6724		// Every PM machine states must be handled in one of the cases below.
6725
6726		switch ( fMachineState )
6727		{
6728			case kIOPM_Finished:
6729				executePMRequest( request );
6730				break;
6731
6732			case kIOPM_OurChangeTellClientsPowerDown:
6733                // Root domain might self cancel due to assertions.
6734                if (IS_ROOT_DOMAIN)
6735                {
6736                    bool cancel = (bool) fDoNotPowerDown;
6737                    getPMRootDomain()->askChangeDownDone(
6738                        &fHeadNoteChangeFlags, &cancel);
6739                    fDoNotPowerDown = cancel;
6740                }
6741
6742                // askChangeDown() done, was it vetoed?
6743				if (!fDoNotPowerDown)
6744				{
6745                    if (IS_ROOT_DOMAIN) {
6746                        PMEventDetails *details = PMEventDetails::eventDetails(
6747                                                    kIOPMEventTypeAppNotificationsFinished,
6748                                                    NULL,
6749                                                    0,
6750                                                    0);
6751
6752						getPMRootDomain()->recordAndReleasePMEventGated( details );
6753                    }
6754
6755					// no, we can continue
6756					OurChangeTellClientsPowerDown();
6757				}
6758				else
6759				{
6760                    if (IS_ROOT_DOMAIN) {
6761                        PMEventDetails *details = PMEventDetails::eventDetails(
6762                                                    kIOPMEventTypeSleepDone,
6763                                                    NULL,
6764                                                    1, /* reason: 1 == Ask clients succeeded */
6765                                                    kIOReturnAborted); /* result */
6766
6767                        getPMRootDomain()->recordAndReleasePMEventGated( details );
6768                    }
6769
6770					OUR_PMLog(kPMLogIdleCancel, (uintptr_t) this, fMachineState);
6771					PM_ERROR("%s: idle cancel\n", fName);
6772					// yes, rescind the warning
6773					tellNoChangeDown(fHeadNotePowerState);
6774					// mark the change note un-actioned
6775					fHeadNoteChangeFlags |= kIOPMNotDone;
6776					// and we're done
6777					OurChangeFinish();
6778				}
6779				break;
6780
6781			case kIOPM_OurChangeTellPriorityClientsPowerDown:
6782				// tellChangeDown(kNotifyApps) done, was it cancelled?
6783				if (fDoNotPowerDown)
6784				{
6785                    if (IS_ROOT_DOMAIN) {
6786						PMEventDetails *details = PMEventDetails::eventDetails(
6787                                                    kIOPMEventTypeSleepDone,
6788                                                    NULL,
6789                                                    2, /* reason: 2 == Client cancelled wake */
6790                                                    kIOReturnAborted); /* result */
6791
6792						getPMRootDomain()->recordAndReleasePMEventGated( details );
6793                    }
6794					OUR_PMLog(kPMLogIdleCancel, (uintptr_t) this, fMachineState);
6795					PM_ERROR("%s: idle revert\n", fName);
6796					// no, tell clients we're back in the old state
6797					tellChangeUp(fCurrentPowerState);
6798					// mark the change note un-actioned
6799					fHeadNoteChangeFlags |= kIOPMNotDone;
6800					// and we're done
6801					OurChangeFinish();
6802				}
6803				else
6804				{
6805                    if (IS_ROOT_DOMAIN) {
6806						PMEventDetails *details = PMEventDetails::eventDetails(
6807                                                    kIOPMEventTypeAppNotificationsFinished,
6808                                                    NULL,
6809                                                    2, /* reason: 2 == TellPriorityClientsDone */
6810                                                    kIOReturnSuccess); /* result */
6811
6812						getPMRootDomain()->recordAndReleasePMEventGated( details );
6813                    }
6814					// yes, we can continue
6815					OurChangeTellPriorityClientsPowerDown();
6816				}
6817				break;
6818
6819			case kIOPM_OurChangeNotifyInterestedDriversWillChange:
6820				OurChangeNotifyInterestedDriversWillChange();
6821				break;
6822
6823			case kIOPM_OurChangeSetPowerState:
6824				OurChangeSetPowerState();
6825				break;
6826
6827			case kIOPM_OurChangeWaitForPowerSettle:
6828				OurChangeWaitForPowerSettle();
6829				break;
6830
6831			case kIOPM_OurChangeNotifyInterestedDriversDidChange:
6832				OurChangeNotifyInterestedDriversDidChange();
6833				break;
6834
6835            case kIOPM_OurChangeTellCapabilityDidChange:
6836                OurChangeTellCapabilityDidChange();
6837                break;
6838
6839			case kIOPM_OurChangeFinish:
6840				OurChangeFinish();
6841				break;
6842
6843			case kIOPM_ParentChangeTellPriorityClientsPowerDown:
6844				ParentChangeTellPriorityClientsPowerDown();
6845				break;
6846
6847			case kIOPM_ParentChangeNotifyInterestedDriversWillChange:
6848				ParentChangeNotifyInterestedDriversWillChange();
6849				break;
6850
6851			case kIOPM_ParentChangeSetPowerState:
6852				ParentChangeSetPowerState();
6853				break;
6854
6855			case kIOPM_ParentChangeWaitForPowerSettle:
6856				ParentChangeWaitForPowerSettle();
6857				break;
6858
6859			case kIOPM_ParentChangeNotifyInterestedDriversDidChange:
6860				ParentChangeNotifyInterestedDriversDidChange();
6861				break;
6862
6863            case kIOPM_ParentChangeTellCapabilityDidChange:
6864                ParentChangeTellCapabilityDidChange();
6865                break;
6866
6867			case kIOPM_ParentChangeAcknowledgePowerChange:
6868				ParentChangeAcknowledgePowerChange();
6869				break;
6870
6871			case kIOPM_DriverThreadCallDone:
6872				if (fDriverCallReason == kDriverCallSetPowerState)
6873					notifyControllingDriverDone();
6874				else
6875					notifyInterestedDriversDone();
6876				break;
6877
6878			case kIOPM_NotifyChildrenOrdered:
6879				notifyChildrenOrdered();
6880				break;
6881
6882			case kIOPM_NotifyChildrenDelayed:
6883				notifyChildrenDelayed();
6884				break;
6885
6886            case kIOPM_NotifyChildrenStart:
6887                PM_LOG2("%s: kIOPM_NotifyChildrenStart done\n", getName());
6888                MS_POP();   // from notifyInterestedDriversDone()
6889                notifyChildren();
6890                break;
6891
6892            case kIOPM_SyncTellClientsPowerDown:
6893                // Root domain might self cancel due to assertions.
6894                if (IS_ROOT_DOMAIN)
6895                {
6896                    bool cancel = (bool) fDoNotPowerDown;
6897                    getPMRootDomain()->askChangeDownDone(
6898                        &fHeadNoteChangeFlags, &cancel);
6899                    fDoNotPowerDown = cancel;
6900                }
6901				if (!fDoNotPowerDown)
6902				{
6903                    fMachineState = kIOPM_SyncTellPriorityClientsPowerDown;
6904                    fOutOfBandParameter = kNotifyApps;
6905                    tellChangeDown(fHeadNotePowerState);
6906				}
6907				else
6908				{
6909					OUR_PMLog(kPMLogIdleCancel, (uintptr_t) this, fMachineState);
6910					PM_ERROR("%s: idle cancel\n", fName);
6911					tellNoChangeDown(fHeadNotePowerState);
6912					fHeadNoteChangeFlags |= kIOPMNotDone;
6913					OurChangeFinish();
6914				}
6915                break;
6916
6917            case kIOPM_SyncTellPriorityClientsPowerDown:
6918				if (!fDoNotPowerDown)
6919				{
6920                    fMachineState = kIOPM_SyncNotifyWillChange;
6921                    fOutOfBandParameter = kNotifyPriority;
6922                    tellChangeDown(fHeadNotePowerState);
6923                }
6924                else
6925                {
6926					OUR_PMLog(kPMLogIdleCancel, (uintptr_t) this, fMachineState);
6927					PM_ERROR("%s: idle revert\n", fName);
6928					tellChangeUp(fCurrentPowerState);
6929					fHeadNoteChangeFlags |= kIOPMNotDone;
6930					OurChangeFinish();
6931				}
6932				break;
6933
6934            case kIOPM_SyncNotifyWillChange:
6935                if (kIOPMSyncNoChildNotify & fHeadNoteChangeFlags)
6936                {
6937                    fMachineState = kIOPM_SyncFinish;
6938                    continue;
6939                }
6940                fMachineState     = kIOPM_SyncNotifyDidChange;
6941                fDriverCallReason = kDriverCallInformPreChange;
6942                notifyChildren();
6943                break;
6944
6945            case kIOPM_SyncNotifyDidChange:
6946                fIsPreChange = false;
6947
6948                if (fHeadNoteChangeFlags & kIOPMParentInitiated)
6949                    fMachineState = kIOPM_SyncFinish;
6950                else
6951                    fMachineState = kIOPM_SyncTellCapabilityDidChange;
6952
6953                fDriverCallReason = kDriverCallInformPostChange;
6954                notifyChildren();
6955                break;
6956
6957            case kIOPM_SyncTellCapabilityDidChange:
6958                tellSystemCapabilityChange( kIOPM_SyncFinish );
6959                break;
6960
6961            case kIOPM_SyncFinish:
6962                if (fHeadNoteChangeFlags & kIOPMParentInitiated)
6963                    ParentChangeAcknowledgePowerChange();
6964                else
6965                    OurChangeFinish();
6966                break;
6967
6968            case kIOPM_TellCapabilityChangeDone:
6969                if (fIsPreChange)
6970                {
6971                    if (fOutOfBandParameter == kNotifyCapabilityChangePriority)
6972                    {
6973                        MS_POP();   // tellSystemCapabilityChange()
6974                        continue;
6975                    }
6976                    fOutOfBandParameter = kNotifyCapabilityChangePriority;
6977                }
6978                else
6979                {
6980                    if (fOutOfBandParameter == kNotifyCapabilityChangeApps)
6981                    {
6982                        MS_POP();   // tellSystemCapabilityChange()
6983                        continue;
6984                    }
6985                    fOutOfBandParameter = kNotifyCapabilityChangeApps;
6986                }
6987                tellClientsWithResponse( fOutOfBandMessage );
6988                break;
6989
6990			default:
6991				panic("servicePMWorkQueue: unknown machine state %x",
6992                    fMachineState);
6993		}
6994
6995		gIOPMRequest = 0;
6996
6997		if (fMachineState == kIOPM_Finished)
6998		{
6999			done = true;
7000			break;
7001		}
7002	}
7003
7004	return done;
7005}
7006
7007//*********************************************************************************
7008// [private] executePMRequest
7009//*********************************************************************************
7010
7011void IOService::executePMRequest( IOPMRequest * request )
7012{
7013	assert( kIOPM_Finished == fMachineState );
7014
7015	switch (request->getType())
7016	{
7017		case kIOPMRequestTypePMStop:
7018			handlePMstop( request );
7019			break;
7020
7021		case kIOPMRequestTypeAddPowerChild1:
7022			addPowerChild1( request );
7023			break;
7024
7025		case kIOPMRequestTypeAddPowerChild2:
7026			addPowerChild2( request );
7027			break;
7028
7029		case kIOPMRequestTypeAddPowerChild3:
7030			addPowerChild3( request );
7031			break;
7032
7033		case kIOPMRequestTypeRegisterPowerDriver:
7034			handleRegisterPowerDriver( request );
7035			break;
7036
7037		case kIOPMRequestTypeAdjustPowerState:
7038			fAdjustPowerScheduled = false;
7039			adjustPowerState();
7040			break;
7041
7042		case kIOPMRequestTypePowerDomainWillChange:
7043			handlePowerDomainWillChangeTo( request );
7044			break;
7045
7046		case kIOPMRequestTypePowerDomainDidChange:
7047			handlePowerDomainDidChangeTo( request );
7048			break;
7049
7050		case kIOPMRequestTypeRequestPowerState:
7051        case kIOPMRequestTypeRequestPowerStateOverride:
7052			handleRequestPowerState( request );
7053			break;
7054
7055		case kIOPMRequestTypePowerOverrideOnPriv:
7056		case kIOPMRequestTypePowerOverrideOffPriv:
7057			handlePowerOverrideChanged( request );
7058			break;
7059
7060		case kIOPMRequestTypeActivityTickle:
7061			handleActivityTickle( request );
7062			break;
7063
7064        case kIOPMRequestTypeSynchronizePowerTree:
7065			handleSynchronizePowerTree( request );
7066			break;
7067
7068        case kIOPMRequestTypeSetIdleTimerPeriod:
7069            {
7070                fIdleTimerPeriod = (uintptr_t) request->fArg0;
7071
7072                if ((false == fLockedFlags.PMStop) && (fIdleTimerPeriod > 0))
7073                {
7074                    fActivityTickleCount = 0;
7075                    clock_get_uptime(&fIdleTimerStartTime);
7076                    start_PM_idle_timer();
7077                }
7078            }
7079            break;
7080
7081        case kIOPMRequestTypeIgnoreIdleTimer:
7082            fIdleTimerIgnored = request->fArg0 ? 1 : 0;
7083            break;
7084
7085		default:
7086			panic("executePMRequest: unknown request type %x", request->getType());
7087	}
7088}
7089
7090//*********************************************************************************
7091// [private] servicePMReplyQueue
7092//*********************************************************************************
7093
7094bool IOService::servicePMReplyQueue( IOPMRequest * request, IOPMRequestQueue * queue )
7095{
7096	bool more = false;
7097
7098	assert( request && queue );
7099	assert( request->isReplyType() );
7100
7101	PM_LOG1("[A %02x] %p [%p %s] state %d\n",
7102		request->getType(), request, this, getName(), fMachineState);
7103
7104	switch ( request->getType() )
7105	{
7106		case kIOPMRequestTypeAllowPowerChange:
7107		case kIOPMRequestTypeCancelPowerChange:
7108			// Check if we are expecting this response.
7109			if (responseValid((uint32_t)(uintptr_t) request->fArg0,
7110                              (int)(uintptr_t) request->fArg1))
7111			{
7112				if (kIOPMRequestTypeCancelPowerChange == request->getType())
7113                {
7114                    // Clients are not allowed to cancel when kIOPMSkipAskPowerDown
7115                    // flag is set. Only root domain will set this flag.
7116
7117                    if ((fHeadNoteChangeFlags & kIOPMSkipAskPowerDown) == 0)
7118                    {
7119                        fDoNotPowerDown = true;
7120
7121                        OSString * name = (OSString *) request->fArg2;
7122                        getPMRootDomain()->pmStatsRecordApplicationResponse(
7123                            gIOPMStatsApplicationResponseCancel,
7124                            name ? name->getCStringNoCopy() : "", 0,
7125                            0, (int)(uintptr_t) request->fArg1);
7126                    }
7127                }
7128
7129				if (checkForDone())
7130				{
7131					stop_ack_timer();
7132                    cleanClientResponses(false);
7133					more = true;
7134				}
7135			}
7136            // OSString containing app name in Arg2 must be released.
7137            if (request->getType() == kIOPMRequestTypeCancelPowerChange)
7138            {
7139                OSObject * obj = (OSObject *) request->fArg2;
7140                if (obj) obj->release();
7141            }
7142			break;
7143
7144		case kIOPMRequestTypeAckPowerChange:
7145			more = handleAcknowledgePowerChange( request );
7146			break;
7147
7148		case kIOPMRequestTypeAckSetPowerState:
7149			if (fDriverTimer == -1)
7150			{
7151				// driver acked while setPowerState() call is in-flight.
7152				// take this ack, return value from setPowerState() is irrelevant.
7153				OUR_PMLog(kPMLogDriverAcknowledgeSet,
7154					(uintptr_t) this, fDriverTimer);
7155				fDriverTimer = 0;
7156			}
7157			else if (fDriverTimer > 0)
7158			{
7159				// expected ack, stop the timer
7160				stop_ack_timer();
7161
7162#if LOG_SETPOWER_TIMES
7163                uint64_t nsec = computeTimeDeltaNS(&fDriverCallStartTime);
7164                if (nsec > LOG_SETPOWER_TIMES)
7165                    PM_LOG("%s::setPowerState(%p, %lu -> %lu) async took %d ms\n",
7166                        fName, this, fCurrentPowerState, fHeadNotePowerState, NS_TO_MS(nsec));
7167
7168				PMEventDetails *details = PMEventDetails::eventDetails(
7169                                            kIOPMEventTypeSetPowerStateDelayed,		// type
7170                                            fName,									// who
7171                                            (uintptr_t)this,						// owner unique
7172                                            NULL,									// interest name
7173                                            (uint8_t)getPowerState(),				// old
7174                                            (uint8_t)fHeadNotePowerState,			// new
7175                                            0,										// result
7176                                            NS_TO_US(nsec));						// usec completion time
7177
7178				getPMRootDomain()->recordAndReleasePMEventGated( details );
7179#endif
7180				OUR_PMLog(kPMLogDriverAcknowledgeSet, (uintptr_t) this, fDriverTimer);
7181				fDriverTimer = 0;
7182				more = true;
7183			}
7184			else
7185			{
7186				// unexpected ack
7187				OUR_PMLog(kPMLogAcknowledgeErr4, (uintptr_t) this, 0);
7188			}
7189			break;
7190
7191		case kIOPMRequestTypeInterestChanged:
7192			handleInterestChanged( request );
7193			more = true;
7194			break;
7195
7196		case kIOPMRequestTypeIdleCancel:
7197			if ((fMachineState == kIOPM_OurChangeTellClientsPowerDown)
7198             || (fMachineState == kIOPM_OurChangeTellPriorityClientsPowerDown)
7199             || (fMachineState == kIOPM_SyncTellClientsPowerDown)
7200             || (fMachineState == kIOPM_SyncTellPriorityClientsPowerDown))
7201			{
7202				OUR_PMLog(kPMLogIdleCancel, (uintptr_t) this, fMachineState);
7203                PM_LOG2("%s: cancel from machine state %d\n",
7204                    getName(), fMachineState);
7205				fDoNotPowerDown = true;
7206                // Stop waiting for app replys.
7207				if ((fMachineState == kIOPM_OurChangeTellPriorityClientsPowerDown) ||
7208                    (fMachineState == kIOPM_SyncTellPriorityClientsPowerDown))
7209					cleanClientResponses(false);
7210				more = true;
7211			}
7212			break;
7213
7214        case kIOPMRequestTypeChildNotifyDelayCancel:
7215            if (fMachineState == kIOPM_NotifyChildrenDelayed)
7216            {
7217                PM_LOG2("%s: delay notify cancelled\n", getName());
7218                notifyChildrenDelayed();
7219            }
7220            break;
7221
7222		default:
7223			panic("servicePMReplyQueue: unknown reply type %x",
7224                request->getType());
7225	}
7226
7227	more |= gIOPMFreeQueue->queuePMRequest(request);
7228    if (more)
7229        gIOPMWorkQueue->incrementProducerCount();
7230
7231	return more;
7232}
7233
7234//*********************************************************************************
7235// [private] assertPMDriverCall / deassertPMDriverCall
7236//*********************************************************************************
7237
7238bool IOService::assertPMDriverCall(
7239    IOPMDriverCallEntry *   entry,
7240    IOOptionBits            options,
7241    IOPMinformee *          inform )
7242{
7243    IOService * target = 0;
7244    bool        ok = false;
7245
7246    if (!initialized)
7247        return false;
7248
7249    PM_LOCK();
7250
7251    if (fLockedFlags.PMStop)
7252    {
7253        goto fail;
7254    }
7255
7256    if (((options & kIOPMADC_NoInactiveCheck) == 0) && isInactive())
7257    {
7258        goto fail;
7259    }
7260
7261    if (inform)
7262    {
7263        if (!inform->active)
7264        {
7265            goto fail;
7266        }
7267        target = inform->whatObject;
7268        if (target->isInactive())
7269        {
7270            goto fail;
7271        }
7272    }
7273
7274    entry->thread = current_thread();
7275    entry->target = target;
7276    queue_enter(&fPMDriverCallQueue, entry, IOPMDriverCallEntry *, link);
7277    ok = true;
7278
7279fail:
7280    PM_UNLOCK();
7281
7282    return ok;
7283}
7284
7285void IOService::deassertPMDriverCall( IOPMDriverCallEntry * entry )
7286{
7287    bool wakeup = false;
7288
7289    PM_LOCK();
7290
7291    assert( !queue_empty(&fPMDriverCallQueue) );
7292    queue_remove(&fPMDriverCallQueue, entry, IOPMDriverCallEntry *, link);
7293    if (fLockedFlags.PMDriverCallWait)
7294    {
7295        wakeup = true;
7296    }
7297
7298    PM_UNLOCK();
7299
7300    if (wakeup)
7301        PM_LOCK_WAKEUP(&fPMDriverCallQueue);
7302}
7303
7304void IOService::waitForPMDriverCall( IOService * target )
7305{
7306    const IOPMDriverCallEntry * entry;
7307    thread_t                    thread = current_thread();
7308    AbsoluteTime                deadline;
7309    int                         waitResult;
7310    bool                        log = true;
7311    bool                        wait;
7312
7313    do {
7314        wait = false;
7315        queue_iterate(&fPMDriverCallQueue, entry, const IOPMDriverCallEntry *, link)
7316        {
7317            // Target of interested driver call
7318            if (target && (target != entry->target))
7319                continue;
7320
7321            if (entry->thread == thread)
7322            {
7323                if (log)
7324                {
7325                    PM_LOG("%s: %s(%s) on PM thread\n",
7326                        fName, __FUNCTION__, target ? target->getName() : "");
7327                    OSReportWithBacktrace("%s: %s(%s) on PM thread\n",
7328                        fName, __FUNCTION__, target ? target->getName() : "");
7329                    log = false;
7330                }
7331                continue;
7332            }
7333
7334            wait = true;
7335            break;
7336        }
7337
7338        if (wait)
7339        {
7340            fLockedFlags.PMDriverCallWait = true;
7341            clock_interval_to_deadline(15, kSecondScale, &deadline);
7342            waitResult = PM_LOCK_SLEEP(&fPMDriverCallQueue, deadline);
7343            fLockedFlags.PMDriverCallWait = false;
7344            if (THREAD_TIMED_OUT == waitResult)
7345            {
7346                PM_ERROR("%s: waitForPMDriverCall timeout\n", fName);
7347                wait = false;
7348            }
7349        }
7350    } while (wait);
7351}
7352
7353//*********************************************************************************
7354// [private] Debug helpers
7355//*********************************************************************************
7356
7357const char * IOService::getIOMessageString( uint32_t msg )
7358{
7359#define MSG_ENTRY(x)    {x, #x}
7360
7361    static const IONamedValue msgNames[] = {
7362        MSG_ENTRY( kIOMessageCanDevicePowerOff      ),
7363        MSG_ENTRY( kIOMessageDeviceWillPowerOff     ),
7364        MSG_ENTRY( kIOMessageDeviceWillNotPowerOff  ),
7365        MSG_ENTRY( kIOMessageDeviceHasPoweredOn     ),
7366        MSG_ENTRY( kIOMessageCanSystemPowerOff      ),
7367        MSG_ENTRY( kIOMessageSystemWillPowerOff     ),
7368        MSG_ENTRY( kIOMessageSystemWillNotPowerOff  ),
7369        MSG_ENTRY( kIOMessageCanSystemSleep         ),
7370        MSG_ENTRY( kIOMessageSystemWillSleep        ),
7371        MSG_ENTRY( kIOMessageSystemWillNotSleep     ),
7372        MSG_ENTRY( kIOMessageSystemHasPoweredOn     ),
7373        MSG_ENTRY( kIOMessageSystemWillRestart      ),
7374        MSG_ENTRY( kIOMessageSystemWillPowerOn      ),
7375        MSG_ENTRY( kIOMessageSystemCapabilityChange )
7376    };
7377
7378    return IOFindNameForValue(msg, msgNames);
7379}
7380
7381// MARK: -
7382// MARK: IOPMRequest
7383
7384//*********************************************************************************
7385// IOPMRequest Class
7386//
7387// Requests from PM clients, and also used for inter-object messaging within PM.
7388//*********************************************************************************
7389
7390OSDefineMetaClassAndStructors( IOPMRequest, IOCommand );
7391
7392IOPMRequest * IOPMRequest::create( void )
7393{
7394	IOPMRequest * me = OSTypeAlloc(IOPMRequest);
7395	if (me && !me->init(0, kIOPMRequestTypeInvalid))
7396	{
7397		me->release();
7398		me = 0;
7399	}
7400	return me;
7401}
7402
7403bool IOPMRequest::init( IOService * target, IOOptionBits type )
7404{
7405	if (!IOCommand::init())
7406		return false;
7407
7408	fType             = type;
7409	fTarget           = target;
7410    fCompletionStatus = kIOReturnSuccess;
7411
7412	if (fTarget)
7413		fTarget->retain();
7414
7415	return true;
7416}
7417
7418void IOPMRequest::reset( void )
7419{
7420	assert( fWorkWaitCount == 0 );
7421	assert( fFreeWaitCount == 0 );
7422
7423	detachNextRequest();
7424    detachRootRequest();
7425
7426	fType = kIOPMRequestTypeInvalid;
7427
7428	if (fCompletionAction)
7429	{
7430        fCompletionAction(fCompletionTarget, fCompletionParam, fCompletionStatus);
7431    }
7432
7433	if (fTarget)
7434	{
7435		fTarget->release();
7436		fTarget = 0;
7437	}
7438}
7439
7440bool IOPMRequest::attachNextRequest( IOPMRequest * next )
7441{
7442    bool ok = false;
7443
7444    if (!fRequestNext)
7445    {
7446        // Postpone the execution of the next request after
7447        // this request.
7448        fRequestNext = next;
7449        fRequestNext->fWorkWaitCount++;
7450#if LOG_REQUEST_ATTACH
7451        kprintf("Attached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
7452            this, (uint32_t) fType, fRequestNext,
7453            (uint32_t) fRequestNext->fType,
7454            (uint32_t) fRequestNext->fWorkWaitCount,
7455            fTarget->getName());
7456#endif
7457        ok = true;
7458    }
7459    return ok;
7460}
7461
7462bool IOPMRequest::detachNextRequest( void )
7463{
7464    bool ok = false;
7465
7466    if (fRequestNext)
7467    {
7468        assert(fRequestNext->fWorkWaitCount);
7469        if (fRequestNext->fWorkWaitCount)
7470            fRequestNext->fWorkWaitCount--;
7471#if LOG_REQUEST_ATTACH
7472        kprintf("Detached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
7473            this, (uint32_t) fType, fRequestNext,
7474            (uint32_t) fRequestNext->fType,
7475            (uint32_t) fRequestNext->fWorkWaitCount,
7476            fTarget->getName());
7477#endif
7478        fRequestNext = 0;
7479        ok = true;
7480    }
7481    return ok;
7482}
7483
7484bool IOPMRequest::attachRootRequest( IOPMRequest * root )
7485{
7486    bool ok = false;
7487
7488    if (!fRequestRoot)
7489    {
7490        // Delay the completion of the root request after
7491        // this request.
7492        fRequestRoot = root;
7493        fRequestRoot->fFreeWaitCount++;
7494#if LOG_REQUEST_ATTACH
7495        kprintf("Attached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
7496            this, (uint32_t) fType, fRequestRoot,
7497            (uint32_t) fRequestRoot->fType,
7498            (uint32_t) fRequestRoot->fFreeWaitCount,
7499            fTarget->getName());
7500#endif
7501        ok = true;
7502    }
7503    return ok;
7504}
7505
7506bool IOPMRequest::detachRootRequest( void )
7507{
7508    bool ok = false;
7509
7510    if (fRequestRoot)
7511    {
7512        assert(fRequestRoot->fFreeWaitCount);
7513        if (fRequestRoot->fFreeWaitCount)
7514            fRequestRoot->fFreeWaitCount--;
7515#if LOG_REQUEST_ATTACH
7516        kprintf("Detached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
7517            this, (uint32_t) fType, fRequestRoot,
7518            (uint32_t) fRequestRoot->fType,
7519            (uint32_t) fRequestRoot->fFreeWaitCount,
7520            fTarget->getName());
7521#endif
7522        fRequestRoot = 0;
7523        ok = true;
7524    }
7525    return ok;
7526}
7527
7528// MARK: -
7529// MARK: IOPMRequestQueue
7530
7531//*********************************************************************************
7532// IOPMRequestQueue Class
7533//
7534// Global queues. Queues are created once and never released.
7535//*********************************************************************************
7536
7537OSDefineMetaClassAndStructors( IOPMRequestQueue, IOEventSource );
7538
7539IOPMRequestQueue * IOPMRequestQueue::create( IOService * inOwner, Action inAction )
7540{
7541	IOPMRequestQueue * me = OSTypeAlloc(IOPMRequestQueue);
7542	if (me && !me->init(inOwner, inAction))
7543	{
7544		me->release();
7545		me = 0;
7546	}
7547	return me;
7548}
7549
7550bool IOPMRequestQueue::init( IOService * inOwner, Action inAction )
7551{
7552	if (!inAction || !IOEventSource::init(inOwner, (IOEventSourceAction)inAction))
7553        return false;
7554
7555	queue_init(&fQueue);
7556	fLock = IOLockAlloc();
7557	return (fLock != 0);
7558}
7559
7560void IOPMRequestQueue::free( void )
7561{
7562	if (fLock)
7563	{
7564		IOLockFree(fLock);
7565		fLock = 0;
7566	}
7567	return IOEventSource::free();
7568}
7569
7570void IOPMRequestQueue::queuePMRequest( IOPMRequest * request )
7571{
7572	assert(request);
7573	IOLockLock(fLock);
7574	queue_enter(&fQueue, request, IOPMRequest *, fCommandChain);
7575	IOLockUnlock(fLock);
7576	if (workLoop) signalWorkAvailable();
7577}
7578
7579void
7580IOPMRequestQueue::queuePMRequestChain( IOPMRequest ** requests, IOItemCount count )
7581{
7582	IOPMRequest * next;
7583
7584	assert(requests && count);
7585	IOLockLock(fLock);
7586	while (count--)
7587	{
7588		next = *requests;
7589		requests++;
7590		queue_enter(&fQueue, next, IOPMRequest *, fCommandChain);
7591	}
7592	IOLockUnlock(fLock);
7593	if (workLoop) signalWorkAvailable();
7594}
7595
7596bool IOPMRequestQueue::checkForWork( void )
7597{
7598    Action			dqAction = (Action) action;
7599	IOPMRequest *	request;
7600	IOService *		target;
7601	bool			more = false;
7602
7603	IOLockLock( fLock );
7604
7605	while (!queue_empty(&fQueue))
7606	{
7607		queue_remove_first( &fQueue, request, IOPMRequest *, fCommandChain );
7608		IOLockUnlock( fLock );
7609		target = request->getTarget();
7610		assert(target);
7611		more |= (*dqAction)( target, request, this );
7612		IOLockLock( fLock );
7613	}
7614
7615	IOLockUnlock( fLock );
7616	return more;
7617}
7618
7619// MARK: -
7620// MARK: IOPMWorkQueue
7621
7622//*********************************************************************************
7623// IOPMWorkQueue Class
7624//
7625// Queue of IOServicePM objects with busy IOPMRequest(s).
7626//*********************************************************************************
7627
7628OSDefineMetaClassAndStructors( IOPMWorkQueue, IOEventSource );
7629
7630IOPMWorkQueue *
7631IOPMWorkQueue::create( IOService * inOwner, Action work, Action retire )
7632{
7633	IOPMWorkQueue * me = OSTypeAlloc(IOPMWorkQueue);
7634	if (me && !me->init(inOwner, work, retire))
7635	{
7636		me->release();
7637		me = 0;
7638	}
7639	return me;
7640}
7641
7642bool IOPMWorkQueue::init( IOService * inOwner, Action work, Action retire )
7643{
7644	if (!work || !retire ||
7645		!IOEventSource::init(inOwner, (IOEventSourceAction)0))
7646		return false;
7647
7648	queue_init(&fWorkQueue);
7649
7650	fWorkAction    = work;
7651	fRetireAction  = retire;
7652    fConsumerCount = fProducerCount = 0;
7653
7654	return true;
7655}
7656
7657bool IOPMWorkQueue::queuePMRequest( IOPMRequest * request, IOServicePM * pwrMgt )
7658{
7659    bool more = false;
7660    bool empty;
7661
7662	assert( request );
7663    assert( pwrMgt );
7664	assert( onThread() );
7665    assert( queue_next(&request->fCommandChain) ==
7666            queue_prev(&request->fCommandChain) );
7667
7668	gIOPMBusyCount++;
7669
7670    // Add new request to the tail of the per-service request queue.
7671    // Then immediately check the request queue to minimize latency
7672    // if the queue was empty.
7673
7674    empty = queue_empty(&pwrMgt->RequestHead);
7675	queue_enter(&pwrMgt->RequestHead, request, IOPMRequest *, fCommandChain);
7676    if (empty)
7677    {
7678        more = checkRequestQueue(&pwrMgt->RequestHead, &empty);
7679        if (!empty)
7680        {
7681            // New Request is blocked, add IOServicePM to work queue.
7682            assert( queue_next(&pwrMgt->WorkChain) ==
7683                    queue_prev(&pwrMgt->WorkChain) );
7684
7685            queue_enter(&fWorkQueue, pwrMgt, IOServicePM *, WorkChain);
7686            fQueueLength++;
7687            PM_LOG3("IOPMWorkQueue: [%u] added %s@%p to queue\n",
7688                fQueueLength, pwrMgt->Name, pwrMgt);
7689        }
7690    }
7691
7692    return more;
7693}
7694
7695bool IOPMWorkQueue::checkRequestQueue( queue_head_t * queue, bool * empty )
7696{
7697	IOPMRequest *	request;
7698	IOService *		target;
7699    bool            more = false;
7700	bool			done = false;
7701
7702    assert(!queue_empty(queue));
7703    do {
7704		request = (IOPMRequest *) queue_first(queue);
7705		if (request->isWorkBlocked())
7706            break;  // cannot start, blocked on attached request
7707
7708		target = request->getTarget();
7709        done = (*fWorkAction)( target, request, this );
7710		if (!done)
7711            break;  // work started, blocked on PM state machine
7712
7713        assert(gIOPMBusyCount > 0);
7714		if (gIOPMBusyCount)
7715            gIOPMBusyCount--;
7716
7717        queue_remove_first(queue, request, IOPMRequest *, fCommandChain);
7718        more |= (*fRetireAction)( target, request, this );
7719        done = queue_empty(queue);
7720    } while (!done);
7721
7722    *empty = done;
7723
7724    if (more)
7725    {
7726        // Retired request blocks another request, since the
7727        // blocked request may reside in the work queue, we
7728        // must bump the producer count to avoid work stall.
7729        fProducerCount++;
7730    }
7731
7732    return more;
7733}
7734
7735bool IOPMWorkQueue::checkForWork( void )
7736{
7737	IOServicePM *   entry;
7738	IOServicePM *   next;
7739    bool			more = false;
7740    bool            empty;
7741
7742#if WORK_QUEUE_STATS
7743    fStatCheckForWork++;
7744#endif
7745
7746    // Each producer signal triggers a full iteration over
7747    // all IOServicePM entries in the work queue.
7748
7749    while (fConsumerCount != fProducerCount)
7750    {
7751        PM_LOG3("IOPMWorkQueue: checkForWork %u %u\n",
7752            fProducerCount, fConsumerCount);
7753
7754        fConsumerCount = fProducerCount;
7755
7756#if WORK_QUEUE_STATS
7757        if (queue_empty(&fWorkQueue))
7758        {
7759            fStatQueueEmpty++;
7760            break;
7761        }
7762        fStatScanEntries++;
7763        uint32_t cachedWorkCount = gIOPMWorkCount;
7764#endif
7765
7766        entry = (IOServicePM *) queue_first(&fWorkQueue);
7767        while (!queue_end(&fWorkQueue, (queue_entry_t) entry))
7768        {
7769            more |= checkRequestQueue(&entry->RequestHead, &empty);
7770
7771            // Get next entry, points to head if current entry is last.
7772            next = (IOServicePM *) queue_next(&entry->WorkChain);
7773
7774            // if request queue is empty, remove IOServicePM from queue.
7775            if (empty)
7776            {
7777                assert(fQueueLength);
7778                if (fQueueLength) fQueueLength--;
7779                PM_LOG3("IOPMWorkQueue: [%u] removed %s@%p from queue\n",
7780                    fQueueLength, entry->Name, entry);
7781                queue_remove(&fWorkQueue, entry, IOServicePM *, WorkChain);
7782            }
7783            entry = next;
7784        }
7785
7786#if WORK_QUEUE_STATS
7787        if (cachedWorkCount == gIOPMWorkCount)
7788            fStatNoWorkDone++;
7789#endif
7790    }
7791
7792    return more;
7793}
7794
7795void IOPMWorkQueue::signalWorkAvailable( void )
7796{
7797    fProducerCount++;
7798	IOEventSource::signalWorkAvailable();
7799}
7800
7801void IOPMWorkQueue::incrementProducerCount( void )
7802{
7803    fProducerCount++;
7804}
7805
7806// MARK: -
7807// MARK: IOPMCompletionQueue
7808
7809//*********************************************************************************
7810// IOPMCompletionQueue Class
7811//*********************************************************************************
7812
7813OSDefineMetaClassAndStructors( IOPMCompletionQueue, IOEventSource );
7814
7815IOPMCompletionQueue *
7816IOPMCompletionQueue::create( IOService * inOwner, Action inAction )
7817{
7818	IOPMCompletionQueue * me = OSTypeAlloc(IOPMCompletionQueue);
7819	if (me && !me->init(inOwner, inAction))
7820	{
7821		me->release();
7822		me = 0;
7823	}
7824	return me;
7825}
7826
7827bool IOPMCompletionQueue::init( IOService * inOwner, Action inAction )
7828{
7829	if (!inAction || !IOEventSource::init(inOwner, (IOEventSourceAction)inAction))
7830        return false;
7831
7832	queue_init(&fQueue);
7833	return true;
7834}
7835
7836bool IOPMCompletionQueue::queuePMRequest( IOPMRequest * request )
7837{
7838    bool more;
7839
7840	assert(request);
7841    // unblock dependent request
7842    more = request->detachNextRequest();
7843	queue_enter(&fQueue, request, IOPMRequest *, fCommandChain);
7844    return more;
7845}
7846
7847bool IOPMCompletionQueue::checkForWork( void )
7848{
7849    Action			dqAction = (Action) action;
7850	IOPMRequest *	request;
7851	IOPMRequest *   next;
7852	IOService *		target;
7853	bool			more = false;
7854
7855    request = (IOPMRequest *) queue_first(&fQueue);
7856    while (!queue_end(&fQueue, (queue_entry_t) request))
7857    {
7858        next = (IOPMRequest *) queue_next(&request->fCommandChain);
7859		if (!request->isFreeBlocked())
7860        {
7861            queue_remove(&fQueue, request, IOPMRequest *, fCommandChain);
7862            target = request->getTarget();
7863            assert(target);
7864            more |= (*dqAction)( target, request, this );
7865        }
7866        request = next;
7867    }
7868
7869    return more;
7870}
7871
7872// MARK: -
7873// MARK: IOServicePM
7874
7875OSDefineMetaClassAndStructors(IOServicePM, OSObject)
7876
7877//*********************************************************************************
7878// serialize
7879//
7880// Serialize IOServicePM for debugging.
7881//*********************************************************************************
7882
7883static void
7884setPMProperty( OSDictionary * dict, const char * key, uint64_t value )
7885{
7886    OSNumber * num = OSNumber::withNumber(value, sizeof(value) * 8);
7887    if (num)
7888    {
7889        dict->setObject(key, num);
7890        num->release();
7891    }
7892}
7893
7894IOReturn IOServicePM::gatedSerialize( OSSerialize * s  )
7895{
7896	OSDictionary *	dict;
7897	bool			ok = false;
7898	int				dictSize = 5;
7899
7900	if (IdleTimerPeriod)
7901		dictSize += 4;
7902
7903#if WORK_QUEUE_STATS
7904    if (gIOPMRootNode == ControllingDriver)
7905        dictSize += 4;
7906#endif
7907
7908    if (PowerClients)
7909        dict = OSDictionary::withDictionary(
7910            PowerClients, PowerClients->getCount() + dictSize);
7911    else
7912        dict = OSDictionary::withCapacity(dictSize);
7913
7914	if (dict)
7915	{
7916        setPMProperty(dict, "CurrentPowerState", CurrentPowerState);
7917        if (NumberOfPowerStates)
7918            setPMProperty(dict, "MaxPowerState", NumberOfPowerStates-1);
7919        if (DesiredPowerState != CurrentPowerState)
7920            setPMProperty(dict, "DesiredPowerState", DesiredPowerState);
7921        if (kIOPM_Finished != MachineState)
7922            setPMProperty(dict, "MachineState", MachineState);
7923        if (DeviceOverrideEnabled)
7924            dict->setObject("PowerOverrideOn", kOSBooleanTrue);
7925
7926		if (IdleTimerPeriod)
7927		{
7928            AbsoluteTime    now;
7929            AbsoluteTime    delta;
7930            uint64_t        nsecs;
7931
7932            clock_get_uptime(&now);
7933
7934			// The idle timer period in milliseconds.
7935			setPMProperty(dict, "IdleTimerPeriod", IdleTimerPeriod * 1000ULL);
7936
7937            // The number of activity tickles recorded since device idle
7938            setPMProperty(dict, "ActivityTickles", ActivityTickleCount);
7939
7940            if (AbsoluteTime_to_scalar(&DeviceActiveTimestamp))
7941            {
7942                // The number of milliseconds since the last activity tickle.
7943                delta = now;
7944                SUB_ABSOLUTETIME(&delta, &DeviceActiveTimestamp);
7945                absolutetime_to_nanoseconds(delta, &nsecs);
7946                setPMProperty(dict, "TimeSinceLastTickle", NS_TO_MS(nsecs));
7947            }
7948
7949            if (AbsoluteTime_to_scalar(&IdleTimerStartTime))
7950            {
7951                // The number of milliseconds since the last device idle.
7952                delta = now;
7953                SUB_ABSOLUTETIME(&delta, &IdleTimerStartTime);
7954                absolutetime_to_nanoseconds(delta, &nsecs);
7955                setPMProperty(dict, "TimeSinceDeviceIdle", NS_TO_MS(nsecs));
7956            }
7957		}
7958
7959#if WORK_QUEUE_STATS
7960        if (gIOPMRootNode == Owner)
7961        {
7962            setPMProperty(dict, "WQ-CheckForWork",
7963                gIOPMWorkQueue->fStatCheckForWork);
7964            setPMProperty(dict, "WQ-ScanEntries",
7965                gIOPMWorkQueue->fStatScanEntries);
7966            setPMProperty(dict, "WQ-QueueEmpty",
7967                gIOPMWorkQueue->fStatQueueEmpty);
7968            setPMProperty(dict, "WQ-NoWorkDone",
7969                gIOPMWorkQueue->fStatNoWorkDone);
7970        }
7971#endif
7972
7973        if (HasAdvisoryDesire && !gIOPMAdvisoryTickleEnabled)
7974        {
7975            // Don't report advisory tickle when it has no influence
7976            dict->removeObject(gIOPMPowerClientAdvisoryTickle);
7977        }
7978
7979		ok = dict->serialize(s);
7980		dict->release();
7981	}
7982
7983	return (ok ? kIOReturnSuccess : kIOReturnNoMemory);
7984}
7985
7986bool IOServicePM::serialize( OSSerialize * s ) const
7987{
7988    IOReturn ret = kIOReturnNotReady;
7989
7990    if (gIOPMWorkLoop)
7991	{
7992		ret = gIOPMWorkLoop->runAction(
7993            OSMemberFunctionCast(IOWorkLoop::Action, this, &IOServicePM::gatedSerialize),
7994            (OSObject *) this, (void *) s);
7995	}
7996
7997    return (kIOReturnSuccess == ret);
7998}
7999
8000void IOServicePM::pmPrint(
8001    uint32_t        event,
8002    uintptr_t       param1,
8003    uintptr_t       param2 ) const
8004{
8005    gPlatform->PMLog(Name, event, param1, param2);
8006}
8007
8008void IOServicePM::pmTrace(
8009    uint32_t        event,
8010    uintptr_t       param1,
8011    uintptr_t       param2 ) const
8012{
8013    const char *  who = Name;
8014    uint64_t    regId = Owner->getRegistryEntryID();
8015    uintptr_t    name = 0;
8016
8017    static const uint32_t sStartStopBitField[] =
8018    { 0x00000000, 0x00000040 }; // Only Program Hardware so far
8019
8020    // Arcane formula from Hacker's Delight by Warren
8021    // abs(x)  = ((int) x >> 31) ^ (x + ((int) x >> 31))
8022    uint32_t sgnevent = ((int) event >> 31);
8023    uint32_t absevent = sgnevent ^ (event + sgnevent);
8024    uint32_t code     = IODBG_POWER(absevent);
8025
8026    uint32_t bit = 1 << (absevent & 0x1f);
8027    if ((absevent < (sizeof(sStartStopBitField) * 8)) &&
8028        (sStartStopBitField[absevent >> 5] & bit))
8029    {
8030        // Or in the START or END bits, Start = 1 & END = 2
8031        //      If sgnevent ==  0 then START -  0 => START
8032        // else if sgnevent == -1 then START - -1 => END
8033        code |= DBG_FUNC_START - sgnevent;
8034    }
8035
8036    // Copy the first characters of the name into an uintptr_t
8037    for (uint32_t i = 0; (i < sizeof(uintptr_t) && who[i] != 0); i++)
8038    {
8039        ((char *) &name)[sizeof(uintptr_t) - i - 1] = who[i];
8040    }
8041
8042    IOTimeStampConstant(code, name, (uintptr_t) regId, param1, param2);
8043}
8044
8045PMEventDetails* PMEventDetails::eventDetails(uint32_t   type,
8046                                             const char *ownerName,
8047                                             uintptr_t  ownerUnique,
8048                                             const char *interestName,
8049                                             uint8_t    oldState,
8050                                             uint8_t    newState,
8051                                             uint32_t   result,
8052                                             uint32_t   elapsedTimeUS) {
8053
8054	PMEventDetails *myself;
8055	myself  = new PMEventDetails;
8056
8057	if(myself) {
8058		myself->eventType     = type;
8059		myself->ownerName     = ownerName;
8060		myself->ownerUnique   = ownerUnique;
8061		myself->interestName  = interestName;
8062		myself->oldState      = oldState;
8063		myself->newState      = newState;
8064		myself->result        = result;
8065		myself->elapsedTimeUS = elapsedTimeUS;
8066
8067		myself->eventClassifier = kIOPMEventClassDriverEvent;
8068	}
8069
8070	return myself;
8071}
8072
8073
8074PMEventDetails* PMEventDetails::eventDetails(uint32_t   type,
8075                                             const char *uuid,
8076                                             uint32_t   reason,
8077                                             uint32_t   result) {
8078
8079	PMEventDetails *myself;
8080	myself  = new PMEventDetails;
8081
8082	if(myself) {
8083		myself->eventType     = type;
8084		myself->uuid          = uuid;
8085		myself->reason        = reason;
8086		myself->result        = result;
8087
8088		myself->eventClassifier = kIOPMEventClassSystemEvent;
8089	}
8090
8091	return myself;
8092}
8093
8094