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