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