xref: /xnu-11215/iokit/Kernel/IOPMrootDomain.cpp (revision a3bb9fcc)
1 /*
2  * Copyright (c) 1998-2008 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 #include <libkern/c++/OSKext.h>
29 #include <libkern/c++/OSMetaClass.h>
30 #include <libkern/OSAtomic.h>
31 #include <libkern/OSDebug.h>
32 #include <IOKit/IOWorkLoop.h>
33 #include <IOKit/IOCommandGate.h>
34 #include <IOKit/IOPlatformExpert.h>
35 #include <IOKit/IOCPU.h>
36 #include <IOKit/IOKitDebug.h>
37 #include <IOKit/IOTimeStamp.h>
38 #include <IOKit/pwr_mgt/IOPMlog.h>
39 #include <IOKit/pwr_mgt/RootDomain.h>
40 #include <IOKit/pwr_mgt/IOPMPrivate.h>
41 #include <IOKit/IODeviceTreeSupport.h>
42 #include <IOKit/IOMessage.h>
43 #include <IOKit/IOReturn.h>
44 #include <IOKit/IONVRAM.h>
45 #include "RootDomainUserClient.h"
46 #include "IOKit/pwr_mgt/IOPowerConnection.h"
47 #include "IOPMPowerStateQueue.h"
48 #include <IOKit/IOCatalogue.h>
49 #include <IOKit/IOReportMacros.h>
50 #if HIBERNATION
51 #include <IOKit/IOHibernatePrivate.h>
52 #endif
53 #include <console/video_console.h>
54 #include <sys/syslog.h>
55 #include <sys/sysctl.h>
56 #include <sys/vnode.h>
57 #include <sys/vnode_internal.h>
58 #include <sys/fcntl.h>
59 
60 #include <sys/time.h>
61 #include "IOServicePrivate.h"   // _IOServiceInterestNotifier
62 #include "IOServicePMPrivate.h"
63 
64 __BEGIN_DECLS
65 #include <mach/shared_region.h>
66 __END_DECLS
67 
68 #if defined(__i386__) || defined(__x86_64__)
69 __BEGIN_DECLS
70 #include "IOPMrootDomainInternal.h"
71 __END_DECLS
72 #endif
73 
74 #define kIOPMrootDomainClass    "IOPMrootDomain"
75 #define LOG_PREFIX              "PMRD: "
76 
77 
78 #define MSG(x...) \
79     do { kprintf(LOG_PREFIX x); IOLog(x); } while (false)
80 
81 #define LOG(x...)    \
82     do { kprintf(LOG_PREFIX x); } while (false)
83 
84 #define DLOG(x...)  do { \
85     if (kIOLogPMRootDomain & gIOKitDebug) \
86         kprintf(LOG_PREFIX x); \
87 } while (false)
88 
89 #define DMSG(x...)  do { \
90     if (kIOLogPMRootDomain & gIOKitDebug) { \
91         kprintf(LOG_PREFIX x); IOLog(x); \
92     } \
93 } while (false)
94 
95 
96 #define _LOG(x...)
97 
98 #define CHECK_THREAD_CONTEXT
99 #ifdef  CHECK_THREAD_CONTEXT
100 static IOWorkLoop * gIOPMWorkLoop = 0;
101 #define ASSERT_GATED()                                      \
102 do {                                                        \
103     if (gIOPMWorkLoop && gIOPMWorkLoop->inGate() != true) { \
104         panic("RootDomain: not inside PM gate");            \
105     }                                                       \
106 } while(false)
107 #else
108 #define ASSERT_GATED()
109 #endif /* CHECK_THREAD_CONTEXT */
110 
111 #define CAP_LOSS(c)  \
112         (((_pendingCapability & (c)) == 0) && \
113          ((_currentCapability & (c)) != 0))
114 
115 #define CAP_GAIN(c)  \
116         (((_currentCapability & (c)) == 0) && \
117          ((_pendingCapability & (c)) != 0))
118 
119 #define CAP_CHANGE(c)    \
120         (((_currentCapability ^ _pendingCapability) & (c)) != 0)
121 
122 #define CAP_CURRENT(c)  \
123         ((_currentCapability & (c)) != 0)
124 
125 #define CAP_HIGHEST(c)  \
126         ((_highestCapability & (c)) != 0)
127 
128 #if defined(__i386__) || defined(__x86_64__)
129 #define DARK_TO_FULL_EVALUATE_CLAMSHELL     1
130 #endif
131 
132 // Event types for IOPMPowerStateQueue::submitPowerEvent()
133 enum {
134     kPowerEventFeatureChanged = 1,              // 1
135     kPowerEventReceivedPowerNotification,       // 2
136     kPowerEventSystemBootCompleted,             // 3
137     kPowerEventSystemShutdown,                  // 4
138     kPowerEventUserDisabledSleep,               // 5
139     kPowerEventRegisterSystemCapabilityClient,  // 6
140     kPowerEventRegisterKernelCapabilityClient,  // 7
141     kPowerEventPolicyStimulus,                  // 8
142     kPowerEventAssertionCreate,                 // 9
143     kPowerEventAssertionRelease,                // 10
144     kPowerEventAssertionSetLevel,               // 11
145     kPowerEventQueueSleepWakeUUID,              // 12
146     kPowerEventPublishSleepWakeUUID,            // 13
147     kPowerEventSetDisplayPowerOn                // 14
148 };
149 
150 // For evaluatePolicy()
151 // List of stimuli that affects the root domain policy.
152 enum {
153     kStimulusDisplayWranglerSleep,      // 0
154     kStimulusDisplayWranglerWake,       // 1
155     kStimulusAggressivenessChanged,     // 2
156     kStimulusDemandSystemSleep,         // 3
157     kStimulusAllowSystemSleepChanged,   // 4
158     kStimulusDarkWakeActivityTickle,    // 5
159     kStimulusDarkWakeEntry,             // 6
160     kStimulusDarkWakeReentry,           // 7
161     kStimulusDarkWakeEvaluate,          // 8
162     kStimulusNoIdleSleepPreventers,     // 9
163     kStimulusEnterUserActiveState,      // 10
164     kStimulusLeaveUserActiveState       // 11
165 };
166 
167 extern "C" {
168 IOReturn OSKextSystemSleepOrWake( UInt32 );
169 }
170 extern "C" ppnum_t      pmap_find_phys(pmap_t pmap, addr64_t va);
171 extern "C" addr64_t     kvtophys(vm_offset_t va);
172 extern "C" int  stack_snapshot_from_kernel(pid_t pid, void *buf, uint32_t size, uint32_t flags, unsigned *bytesTraced);
173 
174 static void idleSleepTimerExpired( thread_call_param_t, thread_call_param_t );
175 static void notifySystemShutdown( IOService * root, unsigned long event );
176 static void handleAggressivesFunction( thread_call_param_t, thread_call_param_t );
177 static void pmEventTimeStamp(uint64_t *recordTS);
178 
179 // "IOPMSetSleepSupported"  callPlatformFunction name
180 static const OSSymbol *sleepSupportedPEFunction = NULL;
181 static const OSSymbol *sleepMessagePEFunction   = NULL;
182 
183 #define kIOSleepSupportedKey        "IOSleepSupported"
184 #define kIOPMSystemCapabilitiesKey  "System Capabilities"
185 
186 #define kIORequestWranglerIdleKey   "IORequestIdle"
187 #define kDefaultWranglerIdlePeriod  25 // in milliseconds
188 
189 #define kIOSleepWakeDebugKey        "Persistent-memory-note"
190 
191 #define kRD_AllPowerSources (kIOPMSupportedOnAC \
192                            | kIOPMSupportedOnBatt \
193                            | kIOPMSupportedOnUPS)
194 
195 enum
196 {
197     // not idle around autowake time, secs
198     kAutoWakePreWindow  = 45,
199     kAutoWakePostWindow = 15
200 };
201 
202 #define kLocalEvalClamshellCommand  (1 << 15)
203 #define kIdleSleepRetryInterval     (3 * 60)
204 
205 enum {
206     kWranglerPowerStateMin   = 0,
207     kWranglerPowerStateSleep = 2,
208     kWranglerPowerStateDim   = 3,
209     kWranglerPowerStateMax   = 4
210 };
211 
212 enum {
213     OFF_STATE           = 0,
214     RESTART_STATE       = 1,
215     SLEEP_STATE         = 2,
216     ON_STATE            = 3,
217     NUM_POWER_STATES
218 };
219 
220 #define ON_POWER        kIOPMPowerOn
221 #define RESTART_POWER   kIOPMRestart
222 #define SLEEP_POWER     kIOPMAuxPowerOn
223 
224 static IOPMPowerState ourPowerStates[NUM_POWER_STATES] =
225 {
226     {1, 0,                      0,              0,             0,0,0,0,0,0,0,0},
227     {1, kIOPMRestartCapability, kIOPMRestart,   RESTART_POWER, 0,0,0,0,0,0,0,0},
228     {1, kIOPMSleepCapability,   kIOPMSleep,     SLEEP_POWER,   0,0,0,0,0,0,0,0},
229     {1, kIOPMPowerOn,           kIOPMPowerOn,   ON_POWER,      0,0,0,0,0,0,0,0}
230 };
231 
232 #define kIOPMRootDomainWakeTypeSleepService     "SleepService"
233 #define kIOPMRootDomainWakeTypeMaintenance      "Maintenance"
234 #define kIOPMRootDomainWakeTypeSleepTimer       "SleepTimer"
235 #define kIOPMrootDomainWakeTypeLowBattery       "LowBattery"
236 #define kIOPMRootDomainWakeTypeUser             "User"
237 #define kIOPMRootDomainWakeTypeAlarm            "Alarm"
238 #define kIOPMRootDomainWakeTypeNetwork          "Network"
239 #define kIOPMRootDomainWakeTypeHIDActivity      "HID Activity"
240 #define kIOPMRootDomainWakeTypeNotification     "Notification"
241 #define kIOPMRootDomainWakeTypeHibernateError   "HibernateError"
242 
243 // Special interest that entitles the interested client from receiving
244 // all system messages. Only used by powerd.
245 //
246 #define kIOPMSystemCapabilityInterest       "IOPMSystemCapabilityInterest"
247 
248 #define WAKEEVENT_LOCK()        IOLockLock(wakeEventLock)
249 #define WAKEEVENT_UNLOCK()      IOLockUnlock(wakeEventLock)
250 
251 /*
252  * Aggressiveness
253  */
254 #define AGGRESSIVES_LOCK()      IOLockLock(featuresDictLock)
255 #define AGGRESSIVES_UNLOCK()    IOLockUnlock(featuresDictLock)
256 
257 #define kAggressivesMinValue    1
258 
259 enum {
260     kAggressivesStateBusy           = 0x01,
261     kAggressivesStateQuickSpindown  = 0x02
262 };
263 
264 struct AggressivesRecord {
265     uint32_t    flags;
266     uint32_t    type;
267     uint32_t    value;
268 };
269 
270 struct AggressivesRequest {
271     queue_chain_t           chain;
272     uint32_t                options;
273     uint32_t                dataType;
274     union {
275         IOService *         service;
276         AggressivesRecord   record;
277     } data;
278 };
279 
280 enum {
281     kAggressivesRequestTypeService  = 1,
282     kAggressivesRequestTypeRecord
283 };
284 
285 enum {
286     kAggressivesOptionSynchronous          = 0x00000001,
287     kAggressivesOptionQuickSpindownEnable  = 0x00000100,
288     kAggressivesOptionQuickSpindownDisable = 0x00000200,
289     kAggressivesOptionQuickSpindownMask    = 0x00000300
290 };
291 
292 enum {
293     kAggressivesRecordFlagModified         = 0x00000001,
294     kAggressivesRecordFlagMinValue         = 0x00000002
295 };
296 
297 // gDarkWakeFlags
298 enum {
299     kDarkWakeFlagHIDTickleEarly      = 0x01, // hid tickle before gfx suppression
300     kDarkWakeFlagHIDTickleLate       = 0x02, // hid tickle after gfx suppression
301     kDarkWakeFlagHIDTickleNone       = 0x03, // hid tickle is not posted
302     kDarkWakeFlagHIDTickleMask       = 0x03,
303     kDarkWakeFlagAlarmIsDark         = 0x0100,
304     kDarkWakeFlagGraphicsPowerState1 = 0x0200,
305     kDarkWakeFlagAudioNotSuppressed  = 0x0400
306 };
307 
308 static IOPMrootDomain * gRootDomain;
309 static IONotifier *     gSysPowerDownNotifier = 0;
310 static UInt32           gSleepOrShutdownPending = 0;
311 static UInt32           gWillShutdown = 0;
312 static UInt32           gPagingOff = 0;
313 static UInt32           gSleepWakeUUIDIsSet = false;
314 static uint32_t         gAggressivesState = 0;
315 
316 uuid_string_t bootsessionuuid_string;
317 
318 static uint32_t         gDarkWakeFlags = kDarkWakeFlagHIDTickleNone;
319 static PMStatsStruct    gPMStats;
320 
321 #if HIBERNATION
322 static IOPMSystemSleepPolicyHandler     gSleepPolicyHandler = 0;
323 static IOPMSystemSleepPolicyVariables * gSleepPolicyVars = 0;
324 static void *                           gSleepPolicyTarget;
325 #endif
326 
327 struct timeval gIOLastSleepTime;
328 struct timeval gIOLastWakeTime;
329 
330 static char gWakeReasonString[128];
331 static bool gWakeReasonSysctlRegistered = false;
332 
333 // Constants used as arguments to IOPMrootDomain::informCPUStateChange
334 #define kCPUUnknownIndex    9999999
335 enum {
336     kInformAC = 0,
337     kInformLid = 1,
338     kInformableCount = 2
339 };
340 
341 const OSSymbol *gIOPMStatsApplicationResponseTimedOut;
342 const OSSymbol *gIOPMStatsApplicationResponseCancel;
343 const OSSymbol *gIOPMStatsApplicationResponseSlow;
344 const OSSymbol *gIOPMStatsApplicationResponsePrompt;
345 const OSSymbol *gIOPMStatsDriverPSChangeSlow;
346 
347 #define kBadPMFeatureID     0
348 
349 /*
350  * PMSettingHandle
351  * Opaque handle passed to clients of registerPMSettingController()
352  */
353 class PMSettingHandle : public OSObject
354 {
355     OSDeclareFinalStructors( PMSettingHandle )
356     friend class PMSettingObject;
357 
358 private:
359     PMSettingObject *pmso;
360     void free(void);
361 };
362 
363 /*
364  * PMSettingObject
365  * Internal object to track each PM setting controller
366  */
367 class PMSettingObject : public OSObject
368 {
369     OSDeclareFinalStructors( PMSettingObject )
370     friend class IOPMrootDomain;
371 
372 private:
373     queue_head_t                    calloutQueue;
374     thread_t                        waitThread;
375     IOPMrootDomain                  *parent;
376     PMSettingHandle                 *pmsh;
377     IOPMSettingControllerCallback   func;
378     OSObject                        *target;
379     uintptr_t                       refcon;
380     uint32_t                        *publishedFeatureID;
381     uint32_t                        settingCount;
382     bool                            disabled;
383 
384     void free(void);
385 
386 public:
387     static PMSettingObject *pmSettingObject(
388                 IOPMrootDomain                  *parent_arg,
389                 IOPMSettingControllerCallback   handler_arg,
390                 OSObject                        *target_arg,
391                 uintptr_t                       refcon_arg,
392                 uint32_t                        supportedPowerSources,
393                 const OSSymbol                  *settings[],
394                 OSObject                        **handle_obj);
395 
396     void dispatchPMSetting(const OSSymbol *type, OSObject *object);
397     void clientHandleFreed(void);
398 };
399 
400 struct PMSettingCallEntry {
401     queue_chain_t   link;
402     thread_t        thread;
403 };
404 
405 #define PMSETTING_LOCK()    IOLockLock(settingsCtrlLock)
406 #define PMSETTING_UNLOCK()  IOLockUnlock(settingsCtrlLock)
407 #define PMSETTING_WAIT(p)   IOLockSleep(settingsCtrlLock, p, THREAD_UNINT)
408 #define PMSETTING_WAKEUP(p) IOLockWakeup(settingsCtrlLock, p, true)
409 
410 /*
411  * PMTraceWorker
412  * Internal helper object for logging trace points to RTC
413  * IOPMrootDomain and only IOPMrootDomain should instantiate
414  * exactly one of these.
415  */
416 
417 typedef void (*IOPMTracePointHandler)(
418         void * target, uint32_t code, uint32_t data );
419 
420 class PMTraceWorker : public OSObject
421 {
422     OSDeclareDefaultStructors(PMTraceWorker)
423 public:
424     typedef enum { kPowerChangeStart, kPowerChangeCompleted } change_t;
425 
426     static PMTraceWorker        *tracer( IOPMrootDomain * );
427     void                        tracePCIPowerChange(change_t, IOService *, uint32_t, uint32_t);
428     void                        tracePoint(uint8_t phase);
429     void                        tracePoint(uint8_t phase, uint8_t data8);
430     void                        traceDetail(uint32_t detail);
431     void                        traceLoginWindowPhase(uint8_t phase);
432     int                         recordTopLevelPCIDevice(IOService *);
433     void                        RTC_TRACE(void);
434     virtual bool                serialize(OSSerialize *s) const;
435 
436     IOPMTracePointHandler       tracePointHandler;
437     void *                      tracePointTarget;
438     uint64_t                    getPMStatusCode();
439 private:
440     IOPMrootDomain              *owner;
441     IOLock                      *pciMappingLock;
442     OSArray                     *pciDeviceBitMappings;
443 
444     uint8_t                     addedToRegistry;
445     uint8_t                     tracePhase;
446     uint8_t                     loginWindowPhase;
447     uint8_t                     traceData8;
448     uint32_t                    traceData32;
449 };
450 
451 /*
452  * PMAssertionsTracker
453  * Tracks kernel and user space PM assertions
454  */
455 class PMAssertionsTracker : public OSObject
456 {
457     OSDeclareFinalStructors(PMAssertionsTracker)
458 public:
459     static PMAssertionsTracker  *pmAssertionsTracker( IOPMrootDomain * );
460 
461     IOReturn                    createAssertion(IOPMDriverAssertionType, IOPMDriverAssertionLevel, IOService *, const char *, IOPMDriverAssertionID *);
462     IOReturn                    releaseAssertion(IOPMDriverAssertionID);
463     IOReturn                    setAssertionLevel(IOPMDriverAssertionID, IOPMDriverAssertionLevel);
464     IOReturn                    setUserAssertionLevels(IOPMDriverAssertionType);
465 
466     OSArray                     *copyAssertionsArray(void);
467     IOPMDriverAssertionType     getActivatedAssertions(void);
468     IOPMDriverAssertionLevel    getAssertionLevel(IOPMDriverAssertionType);
469 
470     IOReturn                    handleCreateAssertion(OSData *);
471     IOReturn                    handleReleaseAssertion(IOPMDriverAssertionID);
472     IOReturn                    handleSetAssertionLevel(IOPMDriverAssertionID, IOPMDriverAssertionLevel);
473     IOReturn                    handleSetUserAssertionLevels(void * arg0);
474     void                        publishProperties(void);
475 
476 private:
477     typedef struct {
478         IOPMDriverAssertionID       id;
479         IOPMDriverAssertionType     assertionBits;
480         uint64_t                    createdTime;
481         uint64_t                    modifiedTime;
482         const OSSymbol              *ownerString;
483         IOService                   *ownerService;
484         uint64_t                    registryEntryID;
485         IOPMDriverAssertionLevel    level;
486     } PMAssertStruct;
487 
488     uint32_t                    tabulateProducerCount;
489     uint32_t                    tabulateConsumerCount;
490 
491     PMAssertStruct              *detailsForID(IOPMDriverAssertionID, int *);
492     void                        tabulate(void);
493 
494     IOPMrootDomain              *owner;
495     OSArray                     *assertionsArray;
496     IOLock                      *assertionsArrayLock;
497     IOPMDriverAssertionID       issuingUniqueID __attribute__((aligned(8))); /* aligned for atomic access */
498     IOPMDriverAssertionType     assertionsKernel;
499     IOPMDriverAssertionType     assertionsUser;
500     IOPMDriverAssertionType     assertionsCombined;
501 };
502 
503 OSDefineMetaClassAndFinalStructors(PMAssertionsTracker, OSObject);
504 
505 /*
506  * PMHaltWorker
507  * Internal helper object for Shutdown/Restart notifications.
508  */
509 #define kPMHaltMaxWorkers   8
510 #define kPMHaltTimeoutMS    100
511 
512 class PMHaltWorker : public OSObject
513 {
514     OSDeclareFinalStructors( PMHaltWorker )
515 
516 public:
517     IOService *  service;    // service being worked on
518     AbsoluteTime startTime;  // time when work started
519     int          depth;      // work on nubs at this PM-tree depth
520     int          visits;     // number of nodes visited (debug)
521     IOLock *     lock;
522     bool         timeout;    // service took too long
523 
524     static  PMHaltWorker * worker( void );
525     static  void main( void * arg, wait_result_t waitResult );
526     static  void work( PMHaltWorker * me );
527     static  void checkTimeout( PMHaltWorker * me, AbsoluteTime * now );
528     virtual void free( void );
529 };
530 
531 OSDefineMetaClassAndFinalStructors( PMHaltWorker, OSObject )
532 
533 
534 #define super IOService
535 OSDefineMetaClassAndFinalStructors(IOPMrootDomain, IOService)
536 
537 static void IOPMRootDomainWillShutdown(void)
538 {
539     if (OSCompareAndSwap(0, 1, &gWillShutdown))
540     {
541     OSKext::willShutdown();
542     for (int i = 0; i < 100; i++)
543     {
544         if (OSCompareAndSwap(0, 1, &gSleepOrShutdownPending)) break;
545         IOSleep( 100 );
546     }
547     }
548 }
549 
550 extern "C"
551 {
552     IONotifier * registerSleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref)
553     {
554         return gRootDomain->registerInterest( gIOGeneralInterest, handler, self, ref );
555     }
556 
557     IONotifier * registerPrioritySleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref)
558     {
559         return gRootDomain->registerInterest( gIOPriorityPowerStateInterest, handler, self, ref );
560     }
561 
562     IOReturn acknowledgeSleepWakeNotification(void * PMrefcon)
563     {
564         return gRootDomain->allowPowerChange ( (unsigned long)PMrefcon );
565     }
566 
567     IOReturn vetoSleepWakeNotification(void * PMrefcon)
568     {
569         return gRootDomain->cancelPowerChange ( (unsigned long)PMrefcon );
570     }
571 
572     IOReturn rootDomainRestart ( void )
573     {
574         return gRootDomain->restartSystem();
575     }
576 
577     IOReturn rootDomainShutdown ( void )
578     {
579         return gRootDomain->shutdownSystem();
580     }
581 
582     void IOSystemShutdownNotification(void)
583     {
584         IOPMRootDomainWillShutdown();
585         if (OSCompareAndSwap(0, 1, &gPagingOff))
586         {
587             gRootDomain->handlePlatformHaltRestart(kPEPagingOff);
588         }
589     }
590 
591     int sync_internal(void);
592 }
593 
594 /*
595 A device is always in the highest power state which satisfies its driver,
596 its policy-maker, and any power children it has, but within the constraint
597 of the power state provided by its parent.  The driver expresses its desire by
598 calling changePowerStateTo(), the policy-maker expresses its desire by calling
599 changePowerStateToPriv(), and the children express their desires by calling
600 requestPowerDomainState().
601 
602 The Root Power Domain owns the policy for idle and demand sleep for the system.
603 It is a power-managed IOService just like the others in the system.
604 It implements several power states which map to what we see as Sleep and On.
605 
606 The sleep policy is as follows:
607 1. Sleep is prevented if the case is open so that nobody will think the machine
608    is off and plug/unplug cards.
609 2. Sleep is prevented if the sleep timeout slider in the prefs panel is zero.
610 3. System cannot Sleep if some object in the tree is in a power state marked
611    kIOPMPreventSystemSleep.
612 
613 These three conditions are enforced using the "driver clamp" by calling
614 changePowerStateTo(). For example, if the case is opened,
615 changePowerStateTo(ON_STATE) is called to hold the system on regardless
616 of the desires of the children of the root or the state of the other clamp.
617 
618 Demand Sleep is initiated by pressing the front panel power button, closing
619 the clamshell, or selecting the menu item. In this case the root's parent
620 actually initiates the power state change so that the root domain has no
621 choice and does not give applications the opportunity to veto the change.
622 
623 Idle Sleep occurs if no objects in the tree are in a state marked
624 kIOPMPreventIdleSleep.  When this is true, the root's children are not holding
625 the root on, so it sets the "policy-maker clamp" by calling
626 changePowerStateToPriv(ON_STATE) to hold itself on until the sleep timer expires.
627 This timer is set for the difference between the sleep timeout slider and the
628 display dim timeout slider. When the timer expires, it releases its clamp and
629 now nothing is holding it awake, so it falls asleep.
630 
631 Demand sleep is prevented when the system is booting.  When preferences are
632 transmitted by the loginwindow at the end of boot, a flag is cleared,
633 and this allows subsequent Demand Sleep.
634 */
635 
636 //******************************************************************************
637 
638 IOPMrootDomain * IOPMrootDomain::construct( void )
639 {
640     IOPMrootDomain  *root;
641 
642     root = new IOPMrootDomain;
643     if( root)
644         root->init();
645 
646     return( root );
647 }
648 
649 //******************************************************************************
650 
651 static void disk_sync_callout( thread_call_param_t p0, thread_call_param_t p1 )
652 {
653     IOService * rootDomain = (IOService *) p0;
654     uint32_t    notifyRef  = (uint32_t)(uintptr_t) p1;
655     uint32_t    powerState = rootDomain->getPowerState();
656 
657     DLOG("disk_sync_callout ps=%u\n", powerState);
658 
659     if (ON_STATE == powerState)
660     {
661         sync_internal();
662     }
663 #if HIBERNATION
664     else
665     {
666         IOHibernateSystemPostWake();
667     }
668 #endif
669 
670     rootDomain->allowPowerChange(notifyRef);
671     DLOG("disk_sync_callout finish\n");
672 }
673 
674 //******************************************************************************
675 
676 static void hib_debugSetup_callout( thread_call_param_t p0, thread_call_param_t p1 )
677 {
678     IOService * rootDomain = (IOService *) p0;
679     uint32_t    notifyRef  = (uint32_t)(uintptr_t) p1;
680 
681 #if	HIBERNATION
682     IOHibernateOpenForDebugData();
683 #endif
684 
685     rootDomain->allowPowerChange(notifyRef);
686     DLOG("hib_debugSetup_callout finish\n");
687 }
688 //******************************************************************************
689 
690 static UInt32 computeDeltaTimeMS( const AbsoluteTime * startTime )
691 {
692     AbsoluteTime    endTime;
693     UInt64          nano = 0;
694 
695     clock_get_uptime(&endTime);
696     if (CMP_ABSOLUTETIME(&endTime, startTime) > 0)
697     {
698         SUB_ABSOLUTETIME(&endTime, startTime);
699         absolutetime_to_nanoseconds(endTime, &nano);
700     }
701 
702     return (UInt32)(nano / 1000000ULL);
703 }
704 
705 //******************************************************************************
706 
707 static int
708 sysctl_sleepwaketime SYSCTL_HANDLER_ARGS
709 {
710   struct timeval *swt = (struct timeval *)arg1;
711   struct proc *p = req->p;
712 
713   if (p == kernproc) {
714     return sysctl_io_opaque(req, swt, sizeof(*swt), NULL);
715   } else if(proc_is64bit(p)) {
716     struct user64_timeval t;
717     t.tv_sec = swt->tv_sec;
718     t.tv_usec = swt->tv_usec;
719     return sysctl_io_opaque(req, &t, sizeof(t), NULL);
720   } else {
721     struct user32_timeval t;
722     t.tv_sec = swt->tv_sec;
723     t.tv_usec = swt->tv_usec;
724     return sysctl_io_opaque(req, &t, sizeof(t), NULL);
725   }
726 }
727 
728 static SYSCTL_PROC(_kern, OID_AUTO, sleeptime,
729         CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
730         &gIOLastSleepTime, 0, sysctl_sleepwaketime, "S,timeval", "");
731 
732 static SYSCTL_PROC(_kern, OID_AUTO, waketime,
733         CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
734         &gIOLastWakeTime, 0, sysctl_sleepwaketime, "S,timeval", "");
735 
736 
737 static int
738 sysctl_willshutdown
739 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
740 {
741     int new_value, changed;
742     int error = sysctl_io_number(req, gWillShutdown, sizeof(int), &new_value, &changed);
743     if (changed) {
744     if (!gWillShutdown && (new_value == 1)) {
745         IOPMRootDomainWillShutdown();
746     } else
747         error = EINVAL;
748     }
749     return(error);
750 }
751 
752 static SYSCTL_PROC(_kern, OID_AUTO, willshutdown,
753         CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
754         0, 0, sysctl_willshutdown, "I", "");
755 
756 
757 static int
758 sysctl_progressmeterenable
759 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
760 {
761     int error;
762     int new_value, changed;
763 
764     error = sysctl_io_number(req, vc_progressmeter_enable, sizeof(int), &new_value, &changed);
765 
766     if (changed) vc_enable_progressmeter(new_value);
767 
768     return (error);
769 }
770 
771 static int
772 sysctl_progressmeter
773 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
774 {
775     int error;
776     int new_value, changed;
777 
778     error = sysctl_io_number(req, vc_progressmeter_value, sizeof(int), &new_value, &changed);
779 
780     if (changed) vc_set_progressmeter(new_value);
781 
782     return (error);
783 }
784 
785 static SYSCTL_PROC(_kern, OID_AUTO, progressmeterenable,
786         CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
787         0, 0, sysctl_progressmeterenable, "I", "");
788 
789 static SYSCTL_PROC(_kern, OID_AUTO, progressmeter,
790         CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
791         0, 0, sysctl_progressmeter, "I", "");
792 
793 
794 static int
795 sysctl_wakereason SYSCTL_HANDLER_ARGS
796 {
797     char wr[ sizeof(gWakeReasonString) ];
798 
799     wr[0] = '\0';
800     if (gRootDomain)
801         gRootDomain->copyWakeReasonString(wr, sizeof(wr));
802 
803     return sysctl_io_string(req, wr, 0, 0, NULL);
804 }
805 
806 SYSCTL_PROC(_kern, OID_AUTO, wakereason,
807     CTLTYPE_STRING| CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED,
808     NULL, 0, sysctl_wakereason, "A", "wakereason");
809 
810 static SYSCTL_INT(_debug, OID_AUTO, darkwake, CTLFLAG_RW, &gDarkWakeFlags, 0, "");
811 
812 static const OSSymbol * gIOPMSettingAutoWakeCalendarKey;
813 static const OSSymbol * gIOPMSettingAutoWakeSecondsKey;
814 static const OSSymbol * gIOPMSettingDebugWakeRelativeKey;
815 static const OSSymbol * gIOPMSettingMaintenanceWakeCalendarKey;
816 static const OSSymbol * gIOPMSettingSleepServiceWakeCalendarKey;
817 static const OSSymbol * gIOPMSettingSilentRunningKey;
818 static const OSSymbol * gIOPMUserTriggeredFullWakeKey;
819 static const OSSymbol * gIOPMUserIsActiveKey;
820 
821 //******************************************************************************
822 // start
823 //
824 //******************************************************************************
825 
826 #define kRootDomainSettingsCount        17
827 
828 bool IOPMrootDomain::start( IOService * nub )
829 {
830     OSIterator      *psIterator;
831     OSDictionary    *tmpDict;
832     IORootParent *   patriarch;
833 #if defined(__i386__) || defined(__x86_64__)
834     IONotifier   *   notifier;
835 #endif
836 
837     super::start(nub);
838 
839     gRootDomain = this;
840     gIOPMSettingAutoWakeCalendarKey = OSSymbol::withCString(kIOPMSettingAutoWakeCalendarKey);
841     gIOPMSettingAutoWakeSecondsKey = OSSymbol::withCString(kIOPMSettingAutoWakeSecondsKey);
842     gIOPMSettingDebugWakeRelativeKey = OSSymbol::withCString(kIOPMSettingDebugWakeRelativeKey);
843     gIOPMSettingMaintenanceWakeCalendarKey = OSSymbol::withCString(kIOPMSettingMaintenanceWakeCalendarKey);
844     gIOPMSettingSleepServiceWakeCalendarKey = OSSymbol::withCString(kIOPMSettingSleepServiceWakeCalendarKey);
845     gIOPMSettingSilentRunningKey = OSSymbol::withCStringNoCopy(kIOPMSettingSilentRunningKey);
846     gIOPMUserTriggeredFullWakeKey = OSSymbol::withCStringNoCopy(kIOPMUserTriggeredFullWakeKey);
847     gIOPMUserIsActiveKey = OSSymbol::withCStringNoCopy(kIOPMUserIsActiveKey);
848 
849     gIOPMStatsApplicationResponseTimedOut = OSSymbol::withCString(kIOPMStatsResponseTimedOut);
850     gIOPMStatsApplicationResponseCancel = OSSymbol::withCString(kIOPMStatsResponseCancel);
851     gIOPMStatsApplicationResponseSlow = OSSymbol::withCString(kIOPMStatsResponseSlow);
852     gIOPMStatsApplicationResponsePrompt = OSSymbol::withCString(kIOPMStatsResponsePrompt);
853     gIOPMStatsDriverPSChangeSlow = OSSymbol::withCString(kIOPMStatsDriverPSChangeSlow);
854 
855     sleepSupportedPEFunction = OSSymbol::withCString("IOPMSetSleepSupported");
856     sleepMessagePEFunction = OSSymbol::withCString("IOPMSystemSleepMessage");
857 
858     const OSSymbol  *settingsArr[kRootDomainSettingsCount] =
859         {
860             OSSymbol::withCString(kIOPMSettingSleepOnPowerButtonKey),
861             gIOPMSettingAutoWakeSecondsKey,
862             OSSymbol::withCString(kIOPMSettingAutoPowerSecondsKey),
863             gIOPMSettingAutoWakeCalendarKey,
864             OSSymbol::withCString(kIOPMSettingAutoPowerCalendarKey),
865             gIOPMSettingDebugWakeRelativeKey,
866             OSSymbol::withCString(kIOPMSettingDebugPowerRelativeKey),
867             OSSymbol::withCString(kIOPMSettingWakeOnRingKey),
868             OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey),
869             OSSymbol::withCString(kIOPMSettingWakeOnClamshellKey),
870             OSSymbol::withCString(kIOPMSettingWakeOnACChangeKey),
871             OSSymbol::withCString(kIOPMSettingTimeZoneOffsetKey),
872             OSSymbol::withCString(kIOPMSettingDisplaySleepUsesDimKey),
873             OSSymbol::withCString(kIOPMSettingMobileMotionModuleKey),
874             OSSymbol::withCString(kIOPMSettingGraphicsSwitchKey),
875             OSSymbol::withCString(kIOPMStateConsoleShutdown),
876             gIOPMSettingSilentRunningKey
877         };
878 
879     PE_parse_boot_argn("darkwake", &gDarkWakeFlags, sizeof(gDarkWakeFlags));
880 
881     queue_init(&aggressivesQueue);
882     aggressivesThreadCall = thread_call_allocate(handleAggressivesFunction, this);
883     aggressivesData = OSData::withCapacity(
884                         sizeof(AggressivesRecord) * (kPMLastAggressivenessType + 4));
885 
886     featuresDictLock = IOLockAlloc();
887     settingsCtrlLock = IOLockAlloc();
888     wakeEventLock = IOLockAlloc();
889     setPMRootDomain(this);
890 
891     extraSleepTimer = thread_call_allocate(
892                         idleSleepTimerExpired,
893                         (thread_call_param_t) this);
894 
895     diskSyncCalloutEntry = thread_call_allocate(
896                         &disk_sync_callout,
897                         (thread_call_param_t) this);
898     hibDebugSetupEntry = thread_call_allocate(
899                         &hib_debugSetup_callout,
900                         (thread_call_param_t) this);
901 
902 #if DARK_TO_FULL_EVALUATE_CLAMSHELL
903     fullWakeThreadCall = thread_call_allocate(
904                             OSMemberFunctionCast(thread_call_func_t, this,
905                                 &IOPMrootDomain::fullWakeDelayedWork),
906                             (thread_call_param_t) this);
907 #endif
908 
909     setProperty(kIOSleepSupportedKey, true);
910 
911     bzero(&gPMStats, sizeof(gPMStats));
912 
913     pmTracer = PMTraceWorker::tracer(this);
914 
915     pmAssertions = PMAssertionsTracker::pmAssertionsTracker(this);
916 
917     userDisabledAllSleep = false;
918     systemBooting = true;
919     sleepSlider = 0;
920     idleSleepTimerPending = false;
921     wrangler = NULL;
922     clamshellClosed    = false;
923     clamshellExists    = false;
924     clamshellDisabled  = true;
925     acAdaptorConnected = true;
926     clamshellSleepDisabled = false;
927     gWakeReasonString[0] = '\0';
928 
929     // Initialize to user active.
930     // Will never transition to user inactive w/o wrangler.
931     fullWakeReason = kFullWakeReasonLocalUser;
932     userIsActive = userWasActive = true;
933     setProperty(gIOPMUserIsActiveKey, kOSBooleanTrue);
934 
935     // Set the default system capabilities at boot.
936     _currentCapability = kIOPMSystemCapabilityCPU      |
937                          kIOPMSystemCapabilityGraphics |
938                          kIOPMSystemCapabilityAudio    |
939                          kIOPMSystemCapabilityNetwork;
940 
941     _pendingCapability = _currentCapability;
942     _desiredCapability = _currentCapability;
943     _highestCapability = _currentCapability;
944     setProperty(kIOPMSystemCapabilitiesKey, _currentCapability, 64);
945 
946     queuedSleepWakeUUIDString = NULL;
947     initializeBootSessionUUID();
948     pmStatsAppResponses     = OSArray::withCapacity(5);
949     _statsNameKey           = OSSymbol::withCString(kIOPMStatsNameKey);
950     _statsPIDKey            = OSSymbol::withCString(kIOPMStatsPIDKey);
951     _statsTimeMSKey         = OSSymbol::withCString(kIOPMStatsTimeMSKey);
952     _statsResponseTypeKey   = OSSymbol::withCString(kIOPMStatsApplicationResponseTypeKey);
953     _statsMessageTypeKey    = OSSymbol::withCString(kIOPMStatsMessageTypeKey);
954     _statsPowerCapsKey      = OSSymbol::withCString(kIOPMStatsPowerCapabilityKey);
955 
956     pmStatsLock = IOLockAlloc();
957     idxPMCPUClamshell = kCPUUnknownIndex;
958     idxPMCPULimitedPower = kCPUUnknownIndex;
959 
960     tmpDict = OSDictionary::withCapacity(1);
961     setProperty(kRootDomainSupportedFeatures, tmpDict);
962     tmpDict->release();
963 
964     settingsCallbacks = OSDictionary::withCapacity(1);
965 
966     // Create a list of the valid PM settings that we'll relay to
967     // interested clients in setProperties() => setPMSetting()
968     allowedPMSettings = OSArray::withObjects(
969                     (const OSObject **)settingsArr,
970                     kRootDomainSettingsCount,
971                     0);
972 
973     // List of PM settings that should not automatically publish itself
974     // as a feature when registered by a listener.
975     noPublishPMSettings = OSArray::withObjects(
976                     (const OSObject **) &gIOPMSettingSilentRunningKey, 1, 0);
977 
978     fPMSettingsDict = OSDictionary::withCapacity(5);
979     preventIdleSleepList = OSSet::withCapacity(8);
980     preventSystemSleepList = OSSet::withCapacity(2);
981 
982     PMinit();   // creates gIOPMWorkLoop
983 
984     // Create IOPMPowerStateQueue used to queue external power
985     // events, and to handle those events on the PM work loop.
986     pmPowerStateQueue = IOPMPowerStateQueue::PMPowerStateQueue(
987         this, OSMemberFunctionCast(IOEventSource::Action, this,
988                 &IOPMrootDomain::dispatchPowerEvent));
989     getPMworkloop()->addEventSource(pmPowerStateQueue);
990 #ifdef CHECK_THREAD_CONTEXT
991     gIOPMWorkLoop = getPMworkloop();
992 #endif
993 
994     // create our power parent
995     patriarch = new IORootParent;
996     patriarch->init();
997     patriarch->attach(this);
998     patriarch->start(this);
999     patriarch->addPowerChild(this);
1000 
1001     registerPowerDriver(this, ourPowerStates, NUM_POWER_STATES);
1002     changePowerStateToPriv(ON_STATE);
1003 
1004     // install power change handler
1005     gSysPowerDownNotifier = registerPrioritySleepWakeInterest( &sysPowerDownHandler, this, 0);
1006 
1007 #if !NO_KERNEL_HID
1008     // Register for a notification when IODisplayWrangler is published
1009     if ((tmpDict = serviceMatching("IODisplayWrangler")))
1010     {
1011         _displayWranglerNotifier = addMatchingNotification(
1012                 gIOPublishNotification, tmpDict,
1013                 (IOServiceMatchingNotificationHandler) &displayWranglerMatchPublished,
1014                 this, 0);
1015         tmpDict->release();
1016     }
1017 #endif
1018 
1019 #if defined(__i386__) || defined(__x86_64__)
1020 
1021     if ((tmpDict = serviceMatching("IODTNVRAM")))
1022     {
1023         notifier = addMatchingNotification(
1024                 gIOFirstPublishNotification, tmpDict,
1025                 (IOServiceMatchingNotificationHandler) &IONVRAMMatchPublished,
1026                 this, 0);
1027         tmpDict->release();
1028     }
1029 
1030     wranglerIdleSettings = NULL;
1031     OSNumber * wranglerIdlePeriod = NULL;
1032     wranglerIdleSettings = OSDictionary::withCapacity(1);
1033     wranglerIdlePeriod  = OSNumber::withNumber(kDefaultWranglerIdlePeriod, 32);
1034 
1035     if(wranglerIdleSettings && wranglerIdlePeriod)
1036         wranglerIdleSettings->setObject(kIORequestWranglerIdleKey,
1037                                         wranglerIdlePeriod);
1038 
1039     if(wranglerIdlePeriod)
1040         wranglerIdlePeriod->release();
1041 #endif
1042 
1043     const OSSymbol *ucClassName = OSSymbol::withCStringNoCopy("RootDomainUserClient");
1044     setProperty(gIOUserClientClassKey, (OSObject *) ucClassName);
1045     ucClassName->release();
1046 
1047     // IOBacklightDisplay can take a long time to load at boot, or it may
1048     // not load at all if you're booting with clamshell closed. We publish
1049     // 'DisplayDims' here redundantly to get it published early and at all.
1050     psIterator = getMatchingServices( serviceMatching("IOPMPowerSource") );
1051     if( psIterator && psIterator->getNextObject() )
1052     {
1053         // There's at least one battery on the system, so we publish
1054         // 'DisplayDims' support for the LCD.
1055         publishFeature("DisplayDims");
1056     }
1057     if(psIterator) {
1058         psIterator->release();
1059     }
1060 
1061     sysctl_register_oid(&sysctl__kern_sleeptime);
1062     sysctl_register_oid(&sysctl__kern_waketime);
1063     sysctl_register_oid(&sysctl__kern_willshutdown);
1064     sysctl_register_oid(&sysctl__kern_progressmeterenable);
1065     sysctl_register_oid(&sysctl__kern_progressmeter);
1066     sysctl_register_oid(&sysctl__kern_wakereason);
1067 
1068 #if HIBERNATION
1069     IOHibernateSystemInit(this);
1070 #endif
1071 
1072     registerService();                      // let clients find us
1073 
1074     return true;
1075 }
1076 
1077 //******************************************************************************
1078 // setProperties
1079 //
1080 // Receive a setProperty call
1081 // The "System Boot" property means the system is completely booted.
1082 //******************************************************************************
1083 
1084 IOReturn IOPMrootDomain::setProperties( OSObject * props_obj )
1085 {
1086     IOReturn        return_value = kIOReturnSuccess;
1087     OSDictionary    *dict = OSDynamicCast(OSDictionary, props_obj);
1088     OSBoolean       *b;
1089     OSNumber        *n;
1090     const OSSymbol  *key;
1091     OSObject        *obj;
1092     OSCollectionIterator * iter = 0;
1093 
1094     const OSSymbol *publish_simulated_battery_string    = OSSymbol::withCString("SoftwareSimulatedBatteries");
1095     const OSSymbol *boot_complete_string                = OSSymbol::withCString("System Boot Complete");
1096     const OSSymbol *sys_shutdown_string                 = OSSymbol::withCString("System Shutdown");
1097     const OSSymbol *stall_halt_string                   = OSSymbol::withCString("StallSystemAtHalt");
1098     const OSSymbol *battery_warning_disabled_string     = OSSymbol::withCString("BatteryWarningsDisabled");
1099     const OSSymbol *idle_seconds_string                 = OSSymbol::withCString("System Idle Seconds");
1100     const OSSymbol *sleepdisabled_string                = OSSymbol::withCString("SleepDisabled");
1101     const OSSymbol *ondeck_sleepwake_uuid_string        = OSSymbol::withCString(kIOPMSleepWakeUUIDKey);
1102     const OSSymbol *loginwindow_tracepoint_string       = OSSymbol::withCString(kIOPMLoginWindowSecurityDebugKey);
1103 #if HIBERNATION
1104     const OSSymbol *hibernatemode_string                = OSSymbol::withCString(kIOHibernateModeKey);
1105     const OSSymbol *hibernatefile_string                = OSSymbol::withCString(kIOHibernateFileKey);
1106     const OSSymbol *hibernatefilemin_string            = OSSymbol::withCString(kIOHibernateFileMinSizeKey);
1107     const OSSymbol *hibernatefilemax_string            = OSSymbol::withCString(kIOHibernateFileMaxSizeKey);
1108     const OSSymbol *hibernatefreeratio_string           = OSSymbol::withCString(kIOHibernateFreeRatioKey);
1109     const OSSymbol *hibernatefreetime_string            = OSSymbol::withCString(kIOHibernateFreeTimeKey);
1110 #endif
1111 
1112     if (!dict)
1113     {
1114         return_value = kIOReturnBadArgument;
1115         goto exit;
1116     }
1117 
1118     iter = OSCollectionIterator::withCollection(dict);
1119     if (!iter)
1120     {
1121         return_value = kIOReturnNoMemory;
1122         goto exit;
1123     }
1124 
1125     while ((key = (const OSSymbol *) iter->getNextObject()) &&
1126            (obj = dict->getObject(key)))
1127     {
1128         if (key->isEqualTo(publish_simulated_battery_string))
1129         {
1130             if (OSDynamicCast(OSBoolean, obj))
1131                 publishResource(key, kOSBooleanTrue);
1132         }
1133         else if (key->isEqualTo(idle_seconds_string))
1134         {
1135             if ((n = OSDynamicCast(OSNumber, obj)))
1136             {
1137                 setProperty(key, n);
1138                 idleSeconds = n->unsigned32BitValue();
1139             }
1140         }
1141         else if (key->isEqualTo(boot_complete_string))
1142         {
1143             pmPowerStateQueue->submitPowerEvent(kPowerEventSystemBootCompleted);
1144         }
1145         else if (key->isEqualTo(sys_shutdown_string))
1146         {
1147             if ((b = OSDynamicCast(OSBoolean, obj)))
1148                 pmPowerStateQueue->submitPowerEvent(kPowerEventSystemShutdown, (void *) b);
1149         }
1150         else if (key->isEqualTo(battery_warning_disabled_string))
1151         {
1152             setProperty(key, obj);
1153         }
1154 #if HIBERNATION
1155         else if (key->isEqualTo(hibernatemode_string) ||
1156                  key->isEqualTo(hibernatefilemin_string) ||
1157                  key->isEqualTo(hibernatefilemax_string) ||
1158                  key->isEqualTo(hibernatefreeratio_string) ||
1159                  key->isEqualTo(hibernatefreetime_string))
1160         {
1161             if ((n = OSDynamicCast(OSNumber, obj)))
1162                 setProperty(key, n);
1163         }
1164         else if (key->isEqualTo(hibernatefile_string))
1165         {
1166             OSString * str = OSDynamicCast(OSString, obj);
1167             if (str) setProperty(key, str);
1168         }
1169 #endif
1170         else if (key->isEqualTo(sleepdisabled_string))
1171         {
1172             if ((b = OSDynamicCast(OSBoolean, obj)))
1173             {
1174                 setProperty(key, b);
1175                 pmPowerStateQueue->submitPowerEvent(kPowerEventUserDisabledSleep, (void *) b);
1176             }
1177         }
1178         else if (key->isEqualTo(ondeck_sleepwake_uuid_string))
1179         {
1180             obj->retain();
1181             pmPowerStateQueue->submitPowerEvent(kPowerEventQueueSleepWakeUUID, (void *)obj);
1182         }
1183         else if (key->isEqualTo(loginwindow_tracepoint_string))
1184         {
1185             if (pmTracer && (n = OSDynamicCast(OSNumber, obj)))
1186                 pmTracer->traceLoginWindowPhase(n->unsigned8BitValue());
1187         }
1188         else if (key->isEqualTo(kIOPMDeepSleepEnabledKey)       ||
1189                  key->isEqualTo(kIOPMDestroyFVKeyOnStandbyKey)  ||
1190                  key->isEqualTo(kIOPMAutoPowerOffEnabledKey)    ||
1191                  key->isEqualTo(stall_halt_string))
1192         {
1193             if ((b = OSDynamicCast(OSBoolean, obj)))
1194                 setProperty(key, b);
1195         }
1196         else if (key->isEqualTo(kIOPMDeepSleepDelayKey) ||
1197                  key->isEqualTo(kIOPMAutoPowerOffDelayKey) ||
1198                  key->isEqualTo(kIOPMAutoPowerOffTimerKey))
1199         {
1200             if ((n = OSDynamicCast(OSNumber, obj)))
1201                 setProperty(key, n);
1202         }
1203         else if (key->isEqualTo(kIOPMUserWakeAlarmScheduledKey))
1204         {
1205             if (kOSBooleanTrue == obj)
1206                 OSBitOrAtomic(kIOPMAlarmBitCalendarWake, &_userScheduledAlarm);
1207             else
1208                 OSBitAndAtomic(~kIOPMAlarmBitCalendarWake, &_userScheduledAlarm);
1209             DLOG("_userScheduledAlarm = 0x%x\n", (uint32_t) _userScheduledAlarm);
1210         }
1211 
1212         // Relay our allowed PM settings onto our registered PM clients
1213         else if ((allowedPMSettings->getNextIndexOfObject(key, 0) != (unsigned int) -1))
1214         {
1215             if ((gIOPMSettingAutoWakeSecondsKey == key) && ((n = OSDynamicCast(OSNumber, obj))))
1216             {
1217                 UInt32 rsecs = n->unsigned32BitValue();
1218                 if (!rsecs)
1219                 autoWakeStart = autoWakeEnd = 0;
1220                 else
1221                 {
1222                 AbsoluteTime deadline;
1223                 clock_interval_to_deadline(rsecs + kAutoWakePostWindow, kSecondScale, &deadline);
1224                 autoWakeEnd = AbsoluteTime_to_scalar(&deadline);
1225                 if (rsecs > kAutoWakePreWindow)
1226                     rsecs -= kAutoWakePreWindow;
1227                 else
1228                     rsecs = 0;
1229                 clock_interval_to_deadline(rsecs, kSecondScale, &deadline);
1230                 autoWakeStart = AbsoluteTime_to_scalar(&deadline);
1231                 }
1232             }
1233 
1234             return_value = setPMSetting(key, obj);
1235             if (kIOReturnSuccess != return_value)
1236                 break;
1237 
1238             if (gIOPMSettingDebugWakeRelativeKey == key)
1239             {
1240                 if ((n = OSDynamicCast(OSNumber, obj)) &&
1241                     (_debugWakeSeconds = n->unsigned32BitValue()))
1242                 {
1243                     OSBitOrAtomic(kIOPMAlarmBitDebugWake, &_scheduledAlarms);
1244                 }
1245                 else
1246                 {
1247                     _debugWakeSeconds = 0;
1248                     OSBitAndAtomic(~kIOPMAlarmBitDebugWake, &_scheduledAlarms);
1249                 }
1250                 DLOG("_scheduledAlarms = 0x%x\n", (uint32_t) _scheduledAlarms);
1251             }
1252             else if (gIOPMSettingAutoWakeCalendarKey == key)
1253             {
1254                 OSData * data;
1255                 if ((data = OSDynamicCast(OSData, obj)) &&
1256                     (data->getLength() == sizeof(IOPMCalendarStruct)))
1257                 {
1258                     const IOPMCalendarStruct * cs =
1259                         (const IOPMCalendarStruct *) data->getBytesNoCopy();
1260 
1261                     if (cs->year)
1262                         OSBitOrAtomic(kIOPMAlarmBitCalendarWake, &_scheduledAlarms);
1263                     else
1264                         OSBitAndAtomic(~kIOPMAlarmBitCalendarWake, &_scheduledAlarms);
1265                     DLOG("_scheduledAlarms = 0x%x\n", (uint32_t) _scheduledAlarms);
1266                 }
1267             }
1268         }
1269         else
1270         {
1271             DLOG("setProperties(%s) not handled\n", key->getCStringNoCopy());
1272         }
1273     }
1274 
1275 exit:
1276     if(publish_simulated_battery_string) publish_simulated_battery_string->release();
1277     if(boot_complete_string) boot_complete_string->release();
1278     if(sys_shutdown_string) sys_shutdown_string->release();
1279     if(stall_halt_string) stall_halt_string->release();
1280     if(battery_warning_disabled_string) battery_warning_disabled_string->release();
1281     if(idle_seconds_string) idle_seconds_string->release();
1282     if(sleepdisabled_string) sleepdisabled_string->release();
1283     if(ondeck_sleepwake_uuid_string) ondeck_sleepwake_uuid_string->release();
1284     if(loginwindow_tracepoint_string) loginwindow_tracepoint_string->release();
1285 #if HIBERNATION
1286     if(hibernatemode_string) hibernatemode_string->release();
1287     if(hibernatefile_string) hibernatefile_string->release();
1288     if(hibernatefreeratio_string) hibernatefreeratio_string->release();
1289     if(hibernatefreetime_string) hibernatefreetime_string->release();
1290 #endif
1291     if (iter) iter->release();
1292     return return_value;
1293 }
1294 
1295 // MARK: -
1296 // MARK: Aggressiveness
1297 
1298 //******************************************************************************
1299 // setAggressiveness
1300 //
1301 // Override IOService::setAggressiveness()
1302 //******************************************************************************
1303 
1304 IOReturn IOPMrootDomain::setAggressiveness(
1305     unsigned long   type,
1306     unsigned long   value )
1307 {
1308     return setAggressiveness( type, value, 0 );
1309 }
1310 
1311 /*
1312  * Private setAggressiveness() with an internal options argument.
1313  */
1314 IOReturn IOPMrootDomain::setAggressiveness(
1315     unsigned long   type,
1316     unsigned long   value,
1317     IOOptionBits    options )
1318 {
1319     AggressivesRequest *    entry;
1320     AggressivesRequest *    request;
1321     bool                    found = false;
1322 
1323     DLOG("setAggressiveness(%x) 0x%x = %u\n",
1324         (uint32_t) options, (uint32_t) type, (uint32_t) value);
1325 
1326     request = IONew(AggressivesRequest, 1);
1327     if (!request)
1328         return kIOReturnNoMemory;
1329 
1330     memset(request, 0, sizeof(*request));
1331     request->options  = options;
1332     request->dataType = kAggressivesRequestTypeRecord;
1333     request->data.record.type  = (uint32_t) type;
1334     request->data.record.value = (uint32_t) value;
1335 
1336     AGGRESSIVES_LOCK();
1337 
1338     // Update disk quick spindown flag used by getAggressiveness().
1339     // Never merge requests with quick spindown flags set.
1340 
1341     if (options & kAggressivesOptionQuickSpindownEnable)
1342         gAggressivesState |= kAggressivesStateQuickSpindown;
1343     else if (options & kAggressivesOptionQuickSpindownDisable)
1344         gAggressivesState &= ~kAggressivesStateQuickSpindown;
1345     else
1346     {
1347         // Coalesce requests with identical aggressives types.
1348         // Deal with callers that calls us too "aggressively".
1349 
1350         queue_iterate(&aggressivesQueue, entry, AggressivesRequest *, chain)
1351         {
1352             if ((entry->dataType == kAggressivesRequestTypeRecord) &&
1353                 (entry->data.record.type == type) &&
1354                 ((entry->options & kAggressivesOptionQuickSpindownMask) == 0))
1355             {
1356                 entry->data.record.value = value;
1357                 found = true;
1358                 break;
1359             }
1360         }
1361     }
1362 
1363     if (!found)
1364     {
1365         queue_enter(&aggressivesQueue, request, AggressivesRequest *, chain);
1366     }
1367 
1368     AGGRESSIVES_UNLOCK();
1369 
1370     if (found)
1371         IODelete(request, AggressivesRequest, 1);
1372 
1373     if (options & kAggressivesOptionSynchronous)
1374         handleAggressivesRequests();   // not truly synchronous
1375     else
1376         thread_call_enter(aggressivesThreadCall);
1377 
1378     return kIOReturnSuccess;
1379 }
1380 
1381 //******************************************************************************
1382 // getAggressiveness
1383 //
1384 // Override IOService::setAggressiveness()
1385 // Fetch the aggressiveness factor with the given type.
1386 //******************************************************************************
1387 
1388 IOReturn IOPMrootDomain::getAggressiveness (
1389     unsigned long   type,
1390     unsigned long * outLevel )
1391 {
1392     uint32_t    value  = 0;
1393     int         source = 0;
1394 
1395     if (!outLevel)
1396         return kIOReturnBadArgument;
1397 
1398     AGGRESSIVES_LOCK();
1399 
1400     // Disk quick spindown in effect, report value = 1
1401 
1402     if ((gAggressivesState & kAggressivesStateQuickSpindown) &&
1403         (type == kPMMinutesToSpinDown))
1404     {
1405         value  = kAggressivesMinValue;
1406         source = 1;
1407     }
1408 
1409     // Consult the pending request queue.
1410 
1411     if (!source)
1412     {
1413         AggressivesRequest * entry;
1414 
1415         queue_iterate(&aggressivesQueue, entry, AggressivesRequest *, chain)
1416         {
1417             if ((entry->dataType == kAggressivesRequestTypeRecord) &&
1418                 (entry->data.record.type == type) &&
1419                 ((entry->options & kAggressivesOptionQuickSpindownMask) == 0))
1420             {
1421                 value  = entry->data.record.value;
1422                 source = 2;
1423                 break;
1424             }
1425         }
1426     }
1427 
1428     // Consult the backend records.
1429 
1430     if (!source && aggressivesData)
1431     {
1432         AggressivesRecord * record;
1433         int                 i, count;
1434 
1435         count  = aggressivesData->getLength() / sizeof(AggressivesRecord);
1436         record = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
1437 
1438         for (i = 0; i < count; i++, record++)
1439         {
1440             if (record->type == type)
1441             {
1442                 value  = record->value;
1443                 source = 3;
1444                 break;
1445             }
1446         }
1447     }
1448 
1449     AGGRESSIVES_UNLOCK();
1450 
1451     if (source)
1452     {
1453         DLOG("getAggressiveness(%d) 0x%x = %u\n",
1454             source, (uint32_t) type, value);
1455         *outLevel = (unsigned long) value;
1456         return kIOReturnSuccess;
1457     }
1458     else
1459     {
1460         DLOG("getAggressiveness type 0x%x not found\n", (uint32_t) type);
1461         *outLevel = 0;  // default return = 0, driver may not check for error
1462         return kIOReturnInvalid;
1463     }
1464 }
1465 
1466 //******************************************************************************
1467 // joinAggressiveness
1468 //
1469 // Request from IOService to join future aggressiveness broadcasts.
1470 //******************************************************************************
1471 
1472 IOReturn IOPMrootDomain::joinAggressiveness(
1473     IOService * service )
1474 {
1475     AggressivesRequest *    request;
1476 
1477     if (!service || (service == this))
1478         return kIOReturnBadArgument;
1479 
1480     DLOG("joinAggressiveness %s %p\n", service->getName(), OBFUSCATE(service));
1481 
1482     request = IONew(AggressivesRequest, 1);
1483     if (!request)
1484         return kIOReturnNoMemory;
1485 
1486     service->retain();  // released by synchronizeAggressives()
1487 
1488     memset(request, 0, sizeof(*request));
1489     request->dataType = kAggressivesRequestTypeService;
1490     request->data.service = service;
1491 
1492     AGGRESSIVES_LOCK();
1493     queue_enter(&aggressivesQueue, request, AggressivesRequest *, chain);
1494     AGGRESSIVES_UNLOCK();
1495 
1496     thread_call_enter(aggressivesThreadCall);
1497 
1498     return kIOReturnSuccess;
1499 }
1500 
1501 //******************************************************************************
1502 // handleAggressivesRequests
1503 //
1504 // Backend thread processes all incoming aggressiveness requests in the queue.
1505 //******************************************************************************
1506 
1507 static void
1508 handleAggressivesFunction(
1509     thread_call_param_t param1,
1510     thread_call_param_t param2 )
1511 {
1512     if (param1)
1513     {
1514         ((IOPMrootDomain *) param1)->handleAggressivesRequests();
1515     }
1516 }
1517 
1518 void IOPMrootDomain::handleAggressivesRequests( void )
1519 {
1520     AggressivesRecord *     start;
1521     AggressivesRecord *     record;
1522     AggressivesRequest *    request;
1523     queue_head_t            joinedQueue;
1524     int                     i, count;
1525     bool                    broadcast;
1526     bool                    found;
1527     bool                    pingSelf = false;
1528 
1529     AGGRESSIVES_LOCK();
1530 
1531     if ((gAggressivesState & kAggressivesStateBusy) || !aggressivesData ||
1532         queue_empty(&aggressivesQueue))
1533         goto unlock_done;
1534 
1535     gAggressivesState |= kAggressivesStateBusy;
1536     count = aggressivesData->getLength() / sizeof(AggressivesRecord);
1537     start = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
1538 
1539     do
1540     {
1541         broadcast = false;
1542         queue_init(&joinedQueue);
1543 
1544         do
1545         {
1546             // Remove request from the incoming queue in FIFO order.
1547             queue_remove_first(&aggressivesQueue, request, AggressivesRequest *, chain);
1548             switch (request->dataType)
1549             {
1550                 case kAggressivesRequestTypeRecord:
1551                     // Update existing record if found.
1552                     found = false;
1553                     for (i = 0, record = start; i < count; i++, record++)
1554                     {
1555                         if (record->type == request->data.record.type)
1556                         {
1557                             found = true;
1558 
1559                             if (request->options & kAggressivesOptionQuickSpindownEnable)
1560                             {
1561                                 if ((record->flags & kAggressivesRecordFlagMinValue) == 0)
1562                                 {
1563                                     broadcast = true;
1564                                     record->flags |= (kAggressivesRecordFlagMinValue |
1565                                                       kAggressivesRecordFlagModified);
1566                                     DLOG("disk spindown accelerated, was %u min\n",
1567                                         record->value);
1568                                 }
1569                             }
1570                             else if (request->options & kAggressivesOptionQuickSpindownDisable)
1571                             {
1572                                 if (record->flags & kAggressivesRecordFlagMinValue)
1573                                 {
1574                                     broadcast = true;
1575                                     record->flags |= kAggressivesRecordFlagModified;
1576                                     record->flags &= ~kAggressivesRecordFlagMinValue;
1577                                     DLOG("disk spindown restored to %u min\n",
1578                                         record->value);
1579                                 }
1580                             }
1581                             else if (record->value != request->data.record.value)
1582                             {
1583                                 record->value = request->data.record.value;
1584                                 if ((record->flags & kAggressivesRecordFlagMinValue) == 0)
1585                                 {
1586                                     broadcast = true;
1587                                     record->flags |= kAggressivesRecordFlagModified;
1588                                 }
1589                             }
1590                             break;
1591                         }
1592                     }
1593 
1594                     // No matching record, append a new record.
1595                     if (!found &&
1596                         ((request->options & kAggressivesOptionQuickSpindownDisable) == 0))
1597                     {
1598                         AggressivesRecord   newRecord;
1599 
1600                         newRecord.flags = kAggressivesRecordFlagModified;
1601                         newRecord.type  = request->data.record.type;
1602                         newRecord.value = request->data.record.value;
1603                         if (request->options & kAggressivesOptionQuickSpindownEnable)
1604                         {
1605                             newRecord.flags |= kAggressivesRecordFlagMinValue;
1606                             DLOG("disk spindown accelerated\n");
1607                         }
1608 
1609                         aggressivesData->appendBytes(&newRecord, sizeof(newRecord));
1610 
1611                         // OSData may have switched to another (larger) buffer.
1612                         count = aggressivesData->getLength() / sizeof(AggressivesRecord);
1613                         start = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
1614                         broadcast = true;
1615                     }
1616 
1617                     // Finished processing the request, release it.
1618                     IODelete(request, AggressivesRequest, 1);
1619                     break;
1620 
1621                 case kAggressivesRequestTypeService:
1622                     // synchronizeAggressives() will free request.
1623                     queue_enter(&joinedQueue, request, AggressivesRequest *, chain);
1624                     break;
1625 
1626                 default:
1627                     panic("bad aggressives request type %x\n", request->dataType);
1628                     break;
1629             }
1630         } while (!queue_empty(&aggressivesQueue));
1631 
1632         // Release the lock to perform work, with busy flag set.
1633         if (!queue_empty(&joinedQueue) || broadcast)
1634         {
1635             AGGRESSIVES_UNLOCK();
1636             if (!queue_empty(&joinedQueue))
1637                 synchronizeAggressives(&joinedQueue, start, count);
1638             if (broadcast)
1639                 broadcastAggressives(start, count);
1640             AGGRESSIVES_LOCK();
1641         }
1642 
1643         // Remove the modified flag from all records.
1644         for (i = 0, record = start; i < count; i++, record++)
1645         {
1646             if ((record->flags & kAggressivesRecordFlagModified) &&
1647                 ((record->type == kPMMinutesToDim) ||
1648                  (record->type == kPMMinutesToSleep)))
1649                 pingSelf = true;
1650 
1651             record->flags &= ~kAggressivesRecordFlagModified;
1652         }
1653 
1654         // Check the incoming queue again since new entries may have been
1655         // added while lock was released above.
1656 
1657     } while (!queue_empty(&aggressivesQueue));
1658 
1659     gAggressivesState &= ~kAggressivesStateBusy;
1660 
1661 unlock_done:
1662     AGGRESSIVES_UNLOCK();
1663 
1664     // Root domain is interested in system and display sleep slider changes.
1665     // Submit a power event to handle those changes on the PM work loop.
1666 
1667     if (pingSelf && pmPowerStateQueue) {
1668         pmPowerStateQueue->submitPowerEvent(
1669             kPowerEventPolicyStimulus,
1670             (void *) kStimulusAggressivenessChanged );
1671     }
1672 }
1673 
1674 //******************************************************************************
1675 // synchronizeAggressives
1676 //
1677 // Push all known aggressiveness records to one or more IOService.
1678 //******************************************************************************
1679 
1680 void IOPMrootDomain::synchronizeAggressives(
1681     queue_head_t *              joinedQueue,
1682     const AggressivesRecord *   array,
1683     int                         count )
1684 {
1685     IOService *                 service;
1686     AggressivesRequest *        request;
1687     const AggressivesRecord *   record;
1688     IOPMDriverCallEntry         callEntry;
1689     uint32_t                    value;
1690     int                         i;
1691 
1692     while (!queue_empty(joinedQueue))
1693     {
1694         queue_remove_first(joinedQueue, request, AggressivesRequest *, chain);
1695         if (request->dataType == kAggressivesRequestTypeService)
1696             service = request->data.service;
1697         else
1698             service = 0;
1699 
1700         IODelete(request, AggressivesRequest, 1);
1701         request = 0;
1702 
1703         if (service)
1704         {
1705             if (service->assertPMDriverCall(&callEntry))
1706             {
1707                 for (i = 0, record = array; i < count; i++, record++)
1708                 {
1709                     value = record->value;
1710                     if (record->flags & kAggressivesRecordFlagMinValue)
1711                         value = kAggressivesMinValue;
1712 
1713                     _LOG("synchronizeAggressives 0x%x = %u to %s\n",
1714                         record->type, value, service->getName());
1715                     service->setAggressiveness(record->type, value);
1716                 }
1717                 service->deassertPMDriverCall(&callEntry);
1718             }
1719             service->release();     // retained by joinAggressiveness()
1720         }
1721     }
1722 }
1723 
1724 //******************************************************************************
1725 // broadcastAggressives
1726 //
1727 // Traverse PM tree and call setAggressiveness() for records that have changed.
1728 //******************************************************************************
1729 
1730 void IOPMrootDomain::broadcastAggressives(
1731     const AggressivesRecord *   array,
1732     int                         count )
1733 {
1734     IORegistryIterator *        iter;
1735     IORegistryEntry *           entry;
1736     IOPowerConnection *         connect;
1737     IOService *                 service;
1738     const AggressivesRecord *   record;
1739     IOPMDriverCallEntry         callEntry;
1740     uint32_t                    value;
1741     int                         i;
1742 
1743     iter = IORegistryIterator::iterateOver(
1744             this, gIOPowerPlane, kIORegistryIterateRecursively);
1745     if (iter)
1746     {
1747         do
1748         {
1749             iter->reset();
1750             while ((entry = iter->getNextObject()))
1751             {
1752                 connect = OSDynamicCast(IOPowerConnection, entry);
1753                 if (!connect || !connect->getReadyFlag())
1754                     continue;
1755 
1756                 if ((service = (IOService *) connect->copyChildEntry(gIOPowerPlane)))
1757                 {
1758                     if (service->assertPMDriverCall(&callEntry))
1759                     {
1760                         for (i = 0, record = array; i < count; i++, record++)
1761                         {
1762                             if (record->flags & kAggressivesRecordFlagModified)
1763                             {
1764                                 value = record->value;
1765                                 if (record->flags & kAggressivesRecordFlagMinValue)
1766                                     value = kAggressivesMinValue;
1767                                 _LOG("broadcastAggressives %x = %u to %s\n",
1768                                     record->type, value, service->getName());
1769                                 service->setAggressiveness(record->type, value);
1770                             }
1771                         }
1772                         service->deassertPMDriverCall(&callEntry);
1773                     }
1774                     service->release();
1775                 }
1776             }
1777         }
1778         while (!entry && !iter->isValid());
1779         iter->release();
1780     }
1781 }
1782 
1783 // MARK: -
1784 // MARK: System Sleep
1785 
1786 //******************************************************************************
1787 // startIdleSleepTimer
1788 //
1789 //******************************************************************************
1790 
1791 void IOPMrootDomain::startIdleSleepTimer( uint32_t inSeconds )
1792 {
1793     AbsoluteTime deadline;
1794 
1795     ASSERT_GATED();
1796     if (inSeconds)
1797     {
1798         clock_interval_to_deadline(inSeconds, kSecondScale, &deadline);
1799         thread_call_enter_delayed(extraSleepTimer, deadline);
1800         idleSleepTimerPending = true;
1801     }
1802     else
1803     {
1804         thread_call_enter(extraSleepTimer);
1805     }
1806     DLOG("idle timer set for %u seconds\n", inSeconds);
1807 }
1808 
1809 //******************************************************************************
1810 // cancelIdleSleepTimer
1811 //
1812 //******************************************************************************
1813 
1814 void IOPMrootDomain::cancelIdleSleepTimer( void )
1815 {
1816     ASSERT_GATED();
1817     if (idleSleepTimerPending)
1818     {
1819         DLOG("idle timer cancelled\n");
1820         thread_call_cancel(extraSleepTimer);
1821         idleSleepTimerPending = false;
1822     }
1823 }
1824 
1825 //******************************************************************************
1826 // idleSleepTimerExpired
1827 //
1828 //******************************************************************************
1829 
1830 static void idleSleepTimerExpired(
1831     thread_call_param_t us, thread_call_param_t )
1832 {
1833     ((IOPMrootDomain *)us)->handleSleepTimerExpiration();
1834 }
1835 
1836 //******************************************************************************
1837 // handleSleepTimerExpiration
1838 //
1839 // The time between the sleep idle timeout and the next longest one has elapsed.
1840 // It's time to sleep. Start that by removing the clamp that's holding us awake.
1841 //******************************************************************************
1842 
1843 void IOPMrootDomain::handleSleepTimerExpiration( void )
1844 {
1845     if (!getPMworkloop()->inGate())
1846     {
1847         getPMworkloop()->runAction(
1848             OSMemberFunctionCast(IOWorkLoop::Action, this,
1849                 &IOPMrootDomain::handleSleepTimerExpiration),
1850             this);
1851         return;
1852     }
1853 
1854     AbsoluteTime time;
1855 
1856     DLOG("sleep timer expired\n");
1857     ASSERT_GATED();
1858 
1859     idleSleepTimerPending = false;
1860 
1861     clock_get_uptime(&time);
1862     if ((AbsoluteTime_to_scalar(&time) > autoWakeStart) &&
1863         (AbsoluteTime_to_scalar(&time) < autoWakeEnd))
1864     {
1865         thread_call_enter_delayed(extraSleepTimer, *((AbsoluteTime *) &autoWakeEnd));
1866         return;
1867     }
1868 
1869     setQuickSpinDownTimeout();
1870     adjustPowerState(true);
1871 }
1872 
1873 //******************************************************************************
1874 // getTimeToIdleSleep
1875 //
1876 // Returns number of seconds left before going into idle sleep.
1877 // Caller has to make sure that idle sleep is allowed at the time of calling
1878 // this function
1879 //******************************************************************************
1880 
1881 uint32_t IOPMrootDomain::getTimeToIdleSleep( void )
1882 {
1883 
1884     AbsoluteTime    now, lastActivityTime;
1885     uint64_t        nanos;
1886     uint32_t        minutesSinceUserInactive = 0;
1887     uint32_t         sleepDelay = 0;
1888 
1889     if (sleepSlider == 0)
1890         return 0xffffffff;
1891 
1892     if (userActivityTime)
1893         lastActivityTime = userActivityTime;
1894     else
1895         lastActivityTime = userBecameInactiveTime;
1896 
1897     clock_get_uptime(&now);
1898     if (CMP_ABSOLUTETIME(&now, &lastActivityTime) > 0)
1899     {
1900         SUB_ABSOLUTETIME(&now, &lastActivityTime);
1901         absolutetime_to_nanoseconds(now, &nanos);
1902         minutesSinceUserInactive = nanos / (60000000000ULL);
1903 
1904         if (minutesSinceUserInactive >= sleepSlider)
1905             sleepDelay = 0;
1906         else
1907             sleepDelay = sleepSlider - minutesSinceUserInactive;
1908     }
1909     else
1910     {
1911         sleepDelay = sleepSlider;
1912     }
1913 
1914     DLOG("user inactive %u min, time to idle sleep %u min\n",
1915         minutesSinceUserInactive, sleepDelay);
1916 
1917     return (sleepDelay * 60);
1918 }
1919 
1920 //******************************************************************************
1921 // setQuickSpinDownTimeout
1922 //
1923 //******************************************************************************
1924 
1925 void IOPMrootDomain::setQuickSpinDownTimeout( void )
1926 {
1927     ASSERT_GATED();
1928     setAggressiveness(
1929         kPMMinutesToSpinDown, 0, kAggressivesOptionQuickSpindownEnable );
1930 }
1931 
1932 //******************************************************************************
1933 // restoreUserSpinDownTimeout
1934 //
1935 //******************************************************************************
1936 
1937 void IOPMrootDomain::restoreUserSpinDownTimeout( void )
1938 {
1939     ASSERT_GATED();
1940     setAggressiveness(
1941         kPMMinutesToSpinDown, 0, kAggressivesOptionQuickSpindownDisable );
1942 }
1943 
1944 //******************************************************************************
1945 // sleepSystem
1946 //
1947 //******************************************************************************
1948 
1949 /* public */
1950 IOReturn IOPMrootDomain::sleepSystem( void )
1951 {
1952     return sleepSystemOptions(NULL);
1953 }
1954 
1955 /* private */
1956 IOReturn IOPMrootDomain::sleepSystemOptions( OSDictionary *options )
1957 {
1958     OSObject *obj = NULL;
1959     OSString *reason = NULL;
1960     /* sleepSystem is a public function, and may be called by any kernel driver.
1961      * And that's bad - drivers should sleep the system by calling
1962      * receivePowerNotification() instead. Drivers should not use sleepSystem.
1963      *
1964      * Note that user space app calls to IOPMSleepSystem() will also travel
1965      * this code path and thus be correctly identified as software sleeps.
1966      */
1967 
1968     if (options && options->getObject("OSSwitch"))
1969     {
1970         // Log specific sleep cause for OS Switch hibernation
1971         return privateSleepSystem( kIOPMSleepReasonOSSwitchHibernate);
1972     }
1973 
1974     if (options && (obj = options->getObject("Sleep Reason")))
1975     {
1976         reason = OSDynamicCast(OSString, obj);
1977         if (reason && reason->isEqualTo(kIOPMDarkWakeThermalEmergencyKey))
1978             return privateSleepSystem(kIOPMSleepReasonDarkWakeThermalEmergency);
1979     }
1980 
1981     return privateSleepSystem( kIOPMSleepReasonSoftware);
1982 }
1983 
1984 /* private */
1985 IOReturn IOPMrootDomain::privateSleepSystem( uint32_t sleepReason )
1986 {
1987     /* Called from both gated and non-gated context */
1988 
1989     if (!checkSystemSleepEnabled() || !pmPowerStateQueue)
1990     {
1991         return kIOReturnNotPermitted;
1992     }
1993 
1994     pmPowerStateQueue->submitPowerEvent(
1995                             kPowerEventPolicyStimulus,
1996                             (void *) kStimulusDemandSystemSleep,
1997                             sleepReason);
1998 
1999     return kIOReturnSuccess;
2000 }
2001 
2002 //******************************************************************************
2003 // powerChangeDone
2004 //
2005 // This overrides powerChangeDone in IOService.
2006 //******************************************************************************
2007 
2008 void IOPMrootDomain::powerChangeDone( unsigned long previousPowerState )
2009 {
2010     ASSERT_GATED();
2011     DLOG("PowerChangeDone: %u->%u\n",
2012         (uint32_t) previousPowerState, (uint32_t) getPowerState());
2013 
2014     switch ( getPowerState() )
2015     {
2016         case SLEEP_STATE: {
2017             if (previousPowerState != ON_STATE)
2018                 break;
2019 
2020             acceptSystemWakeEvents(true);
2021 
2022             // re-enable this timer for next sleep
2023             cancelIdleSleepTimer();
2024 
2025             clock_sec_t     secs;
2026             clock_usec_t    microsecs;
2027             clock_get_calendar_microtime(&secs, &microsecs);
2028             logtime(secs);
2029             gIOLastSleepTime.tv_sec  = secs;
2030             gIOLastSleepTime.tv_usec = microsecs;
2031             gIOLastWakeTime.tv_sec = 0;
2032             gIOLastWakeTime.tv_usec = 0;
2033 
2034 #if HIBERNATION
2035             LOG("System %sSleep\n", gIOHibernateState ? "Safe" : "");
2036 
2037             IOHibernateSystemHasSlept();
2038 
2039             evaluateSystemSleepPolicyFinal();
2040 #else
2041             LOG("System Sleep\n");
2042 #endif
2043 
2044             ((IOService *)this)->stop_watchdog_timer(); //14456299
2045             getPlatform()->sleepKernel();
2046 
2047             // The CPU(s) are off at this point,
2048             // Code will resume execution here upon wake.
2049 
2050             clock_get_uptime(&systemWakeTime);
2051             _highestCapability = 0;
2052 
2053             ((IOService *)this)->start_watchdog_timer(); //14456299
2054 #if HIBERNATION
2055             IOHibernateSystemWake();
2056 #endif
2057 
2058             // sleep transition complete
2059             gSleepOrShutdownPending = 0;
2060 
2061             // trip the reset of the calendar clock
2062             clock_wakeup_calendar();
2063 
2064 #if HIBERNATION
2065             LOG("System %sWake\n", gIOHibernateState ? "SafeSleep " : "");
2066 #endif
2067 
2068             // log system wake
2069             PMDebug(kPMLogSystemWake, 0, 0);
2070             lowBatteryCondition = false;
2071             lastSleepReason = 0;
2072 
2073             _lastDebugWakeSeconds = _debugWakeSeconds;
2074             _debugWakeSeconds = 0;
2075             _scheduledAlarms = 0;
2076 
2077 #ifndef __LP64__
2078             systemWake();
2079 #endif
2080 
2081 #if defined(__i386__) || defined(__x86_64__)
2082             wranglerTickled         = false;
2083             graphicsSuppressed      = false;
2084             darkWakePostTickle      = false;
2085             darkWakeHibernateError  = false;
2086             darkWakeToSleepASAP     = true;
2087             logGraphicsClamp        = true;
2088             sleepTimerMaintenance   = false;
2089             sleepToStandby          = false;
2090             wranglerTickleLatched   = false;
2091             userWasActive           = false;
2092             fullWakeReason = kFullWakeReasonNone;
2093 
2094             OSString * wakeType = OSDynamicCast(
2095                 OSString, getProperty(kIOPMRootDomainWakeTypeKey));
2096             OSString * wakeReason = OSDynamicCast(
2097                 OSString, getProperty(kIOPMRootDomainWakeReasonKey));
2098 
2099             if (wakeReason && (wakeReason->getLength() >= 2) &&
2100                 gWakeReasonString[0] == '\0')
2101             {
2102                 // Until the platform driver can claim its wake reasons
2103                 strlcat(gWakeReasonString, wakeReason->getCStringNoCopy(),
2104                         sizeof(gWakeReasonString));
2105             }
2106 
2107             if (wakeType && wakeType->isEqualTo(kIOPMrootDomainWakeTypeLowBattery))
2108             {
2109                 lowBatteryCondition = true;
2110                 darkWakeMaintenance = true;
2111             }
2112             else if ((gDarkWakeFlags & kDarkWakeFlagHIDTickleMask) != 0)
2113             {
2114                 OSNumber * hibOptions = OSDynamicCast(
2115                     OSNumber, getProperty(kIOHibernateOptionsKey));
2116 
2117                 if (hibernateAborted || ((hibOptions &&
2118                     !(hibOptions->unsigned32BitValue() & kIOHibernateOptionDarkWake))))
2119                 {
2120                     // Hibernate aborted, or EFI brought up graphics
2121                     wranglerTickled = true;
2122                     DLOG("hibernation aborted %d, options 0x%x\n",
2123                         hibernateAborted,
2124                         hibOptions ? hibOptions->unsigned32BitValue() : 0);
2125                 }
2126                 else
2127                 if (wakeType && (
2128                     wakeType->isEqualTo(kIOPMRootDomainWakeTypeUser) ||
2129                     wakeType->isEqualTo(kIOPMRootDomainWakeTypeAlarm)))
2130                 {
2131                     // User wake or RTC alarm
2132                     wranglerTickled = true;
2133                 }
2134                 else
2135                 if (wakeType &&
2136                     wakeType->isEqualTo(kIOPMRootDomainWakeTypeSleepTimer))
2137                 {
2138                     // SMC standby timer trumps SleepX
2139                     darkWakeMaintenance = true;
2140                     sleepTimerMaintenance = true;
2141                 }
2142                 else
2143                 if ((_lastDebugWakeSeconds != 0) &&
2144                     ((gDarkWakeFlags & kDarkWakeFlagAlarmIsDark) == 0))
2145                 {
2146                     // SleepX before maintenance
2147                     wranglerTickled = true;
2148                 }
2149                 else
2150                 if (wakeType &&
2151                     wakeType->isEqualTo(kIOPMRootDomainWakeTypeMaintenance))
2152                 {
2153                     darkWakeMaintenance = true;
2154                 }
2155                 else
2156                 if (wakeType &&
2157                     wakeType->isEqualTo(kIOPMRootDomainWakeTypeSleepService))
2158                 {
2159                     darkWakeMaintenance = true;
2160                     darkWakeSleepService = true;
2161                     if (kIOHibernateStateWakingFromHibernate == gIOHibernateState) {
2162                         sleepToStandby = true;
2163                     }
2164                 }
2165                 else
2166                 if (wakeType &&
2167                     wakeType->isEqualTo(kIOPMRootDomainWakeTypeHibernateError))
2168                 {
2169                     darkWakeMaintenance = true;
2170                     darkWakeHibernateError = true;
2171                 }
2172                 else
2173                 {
2174                     // Unidentified wake source, resume to full wake if debug
2175                     // alarm is pending.
2176 
2177                     if (_lastDebugWakeSeconds &&
2178                         (!wakeReason || wakeReason->isEqualTo("")))
2179                         wranglerTickled = true;
2180                 }
2181             }
2182             else
2183             {
2184                 if (wakeType &&
2185                     wakeType->isEqualTo(kIOPMRootDomainWakeTypeSleepTimer))
2186                 {
2187                     darkWakeMaintenance = true;
2188                     sleepTimerMaintenance = true;
2189                 }
2190                 else if (hibernateAborted || !wakeType ||
2191                     !wakeType->isEqualTo(kIOPMRootDomainWakeTypeMaintenance) ||
2192                     !wakeReason || !wakeReason->isEqualTo("RTC"))
2193                 {
2194                     // Post a HID tickle immediately - except for RTC maintenance wake.
2195                     wranglerTickled = true;
2196                 }
2197                 else
2198                 {
2199                     darkWakeMaintenance = true;
2200                 }
2201             }
2202 
2203             if (wranglerTickled)
2204             {
2205                 darkWakeToSleepASAP = false;
2206                 fullWakeReason = kFullWakeReasonLocalUser;
2207                 reportUserInput();
2208             }
2209             else if (!darkWakeMaintenance)
2210             {
2211                 // Early/late tickle for non-maintenance wake.
2212                 if (((gDarkWakeFlags & kDarkWakeFlagHIDTickleMask) ==
2213                      kDarkWakeFlagHIDTickleEarly) ||
2214                     ((gDarkWakeFlags & kDarkWakeFlagHIDTickleMask) ==
2215                      kDarkWakeFlagHIDTickleLate))
2216                 {
2217                     darkWakePostTickle = true;
2218                 }
2219             }
2220 #else   /* !__i386__ && !__x86_64__ */
2221             // stay awake for at least 30 seconds
2222             wranglerTickled = true;
2223             fullWakeReason = kFullWakeReasonLocalUser;
2224             startIdleSleepTimer(30);
2225 #endif
2226             sleepCnt++;
2227 
2228             changePowerStateToPriv(ON_STATE);
2229         }   break;
2230 
2231     }
2232 }
2233 
2234 //******************************************************************************
2235 // requestPowerDomainState
2236 //
2237 // Extend implementation in IOService. Running on PM work loop thread.
2238 //******************************************************************************
2239 
2240 IOReturn IOPMrootDomain::requestPowerDomainState (
2241     IOPMPowerFlags      childDesire,
2242     IOPowerConnection * childConnection,
2243     unsigned long       specification )
2244 {
2245     // Idle and system sleep prevention flags affects driver desire.
2246     // Children desire are irrelevant so they are cleared.
2247 
2248     return super::requestPowerDomainState(0, childConnection, specification);
2249 }
2250 
2251 //******************************************************************************
2252 // updatePreventIdleSleepList
2253 //
2254 // Called by IOService on PM work loop.
2255 // Returns true if PM policy recognized the driver's desire to prevent idle
2256 // sleep and updated the list of idle sleep preventers. Returns false otherwise
2257 //******************************************************************************
2258 
2259 bool IOPMrootDomain::updatePreventIdleSleepList(
2260         IOService * service, bool addNotRemove )
2261 {
2262     unsigned int oldCount, newCount;
2263 
2264     ASSERT_GATED();
2265 
2266 #if defined(__i386__) || defined(__x86_64__)
2267     // Disregard disk I/O (besides the display wrangler) as a factor preventing
2268     // idle sleep, except in the case of legacy disk I/O
2269     if ((service != wrangler) && (service != this))
2270     {
2271         return false;
2272     }
2273 #endif
2274 
2275     oldCount = preventIdleSleepList->getCount();
2276     if (addNotRemove)
2277     {
2278         preventIdleSleepList->setObject(service);
2279         DLOG("prevent idle sleep list: %s+ (%u)\n",
2280             service->getName(), preventIdleSleepList->getCount());
2281     }
2282     else if (preventIdleSleepList->member(service))
2283     {
2284         preventIdleSleepList->removeObject(service);
2285         DLOG("prevent idle sleep list: %s- (%u)\n",
2286             service->getName(), preventIdleSleepList->getCount());
2287     }
2288     newCount = preventIdleSleepList->getCount();
2289 
2290     if ((oldCount == 0) && (newCount != 0))
2291     {
2292         // Driver added to empty prevent list.
2293         // Update the driver desire to prevent idle sleep.
2294         // Driver desire does not prevent demand sleep.
2295 
2296         changePowerStateTo(ON_STATE);
2297     }
2298     else if ((oldCount != 0) && (newCount == 0))
2299     {
2300         // Last driver removed from prevent list.
2301         // Drop the driver clamp to allow idle sleep.
2302 
2303         changePowerStateTo(SLEEP_STATE);
2304         evaluatePolicy( kStimulusNoIdleSleepPreventers );
2305     }
2306 
2307 #if defined(__i386__) || defined(__x86_64__)
2308     if (addNotRemove && (service == wrangler) && !checkSystemCanSustainFullWake())
2309     {
2310         return false;   // do not idle-cancel
2311     }
2312 #endif
2313 
2314     return true;
2315 }
2316 
2317 //******************************************************************************
2318 // preventSystemSleepListUpdate
2319 //
2320 // Called by IOService on PM work loop.
2321 //******************************************************************************
2322 
2323 void IOPMrootDomain::updatePreventSystemSleepList(
2324         IOService * service, bool addNotRemove )
2325 {
2326     unsigned int oldCount;
2327 
2328     ASSERT_GATED();
2329     if (this == service)
2330         return;
2331 
2332     oldCount = preventSystemSleepList->getCount();
2333     if (addNotRemove)
2334     {
2335         preventSystemSleepList->setObject(service);
2336         DLOG("prevent system sleep list: %s+ (%u)\n",
2337             service->getName(), preventSystemSleepList->getCount());
2338     }
2339     else if (preventSystemSleepList->member(service))
2340     {
2341         preventSystemSleepList->removeObject(service);
2342         DLOG("prevent system sleep list: %s- (%u)\n",
2343             service->getName(), preventSystemSleepList->getCount());
2344 
2345         if ((oldCount != 0) && (preventSystemSleepList->getCount() == 0))
2346         {
2347             // Lost all system sleep preventers.
2348             // Send stimulus if system sleep was blocked, and is in dark wake.
2349             evaluatePolicy( kStimulusDarkWakeEvaluate );
2350         }
2351     }
2352 }
2353 
2354 //******************************************************************************
2355 // tellChangeDown
2356 //
2357 // Override the superclass implementation to send a different message type.
2358 //******************************************************************************
2359 
2360 bool IOPMrootDomain::tellChangeDown( unsigned long stateNum )
2361 {
2362     DLOG("tellChangeDown %u->%u\n",
2363         (uint32_t) getPowerState(), (uint32_t) stateNum);
2364 
2365     if (SLEEP_STATE == stateNum)
2366     {
2367         // Legacy apps were already told in the full->dark transition
2368         if (!ignoreTellChangeDown)
2369             tracePoint( kIOPMTracePointSleepApplications );
2370         else
2371             tracePoint( kIOPMTracePointSleepPriorityClients );
2372     }
2373 
2374     if ((SLEEP_STATE == stateNum) && !ignoreTellChangeDown)
2375     {
2376         userActivityAtSleep = userActivityCount;
2377         hibernateAborted = false;
2378         DLOG("tellChangeDown::userActivityAtSleep %d\n", userActivityAtSleep);
2379 
2380         // Direct callout into OSKext so it can disable kext unloads
2381         // during sleep/wake to prevent deadlocks.
2382         OSKextSystemSleepOrWake( kIOMessageSystemWillSleep );
2383 
2384         IOService::updateConsoleUsers(NULL, kIOMessageSystemWillSleep);
2385 
2386         // Two change downs are sent by IOServicePM. Ignore the 2nd.
2387         // But tellClientsWithResponse() must be called for both.
2388         ignoreTellChangeDown = true;
2389     }
2390 
2391     return super::tellClientsWithResponse( kIOMessageSystemWillSleep );
2392 }
2393 
2394 //******************************************************************************
2395 // askChangeDown
2396 //
2397 // Override the superclass implementation to send a different message type.
2398 // This must be idle sleep since we don't ask during any other power change.
2399 //******************************************************************************
2400 
2401 bool IOPMrootDomain::askChangeDown( unsigned long stateNum )
2402 {
2403     DLOG("askChangeDown %u->%u\n",
2404         (uint32_t) getPowerState(), (uint32_t) stateNum);
2405 
2406     // Don't log for dark wake entry
2407     if (kSystemTransitionSleep == _systemTransitionType)
2408         tracePoint( kIOPMTracePointSleepApplications );
2409 
2410     return super::tellClientsWithResponse( kIOMessageCanSystemSleep );
2411 }
2412 
2413 //******************************************************************************
2414 // askChangeDownDone
2415 //
2416 // An opportunity for root domain to cancel the power transition,
2417 // possibily due to an assertion created by powerd in response to
2418 // kIOMessageCanSystemSleep.
2419 //
2420 // Idle sleep:
2421 //   full -> dark wake transition
2422 //     1. Notify apps and powerd with kIOMessageCanSystemSleep
2423 //     2. askChangeDownDone()
2424 //   dark -> sleep transition
2425 //     1. Notify powerd with kIOMessageCanSystemSleep
2426 //     2. askChangeDownDone()
2427 //
2428 // Demand sleep:
2429 //   full -> dark wake transition
2430 //     1. Notify powerd with kIOMessageCanSystemSleep
2431 //     2. askChangeDownDone()
2432 //   dark -> sleep transition
2433 //     1. Notify powerd with kIOMessageCanSystemSleep
2434 //     2. askChangeDownDone()
2435 //******************************************************************************
2436 
2437 void IOPMrootDomain::askChangeDownDone(
2438         IOPMPowerChangeFlags * inOutChangeFlags, bool * cancel )
2439 {
2440     DLOG("askChangeDownDone(0x%x, %u) type %x, cap %x->%x\n",
2441         *inOutChangeFlags, *cancel,
2442         _systemTransitionType,
2443         _currentCapability, _pendingCapability);
2444 
2445     if ((false == *cancel) && (kSystemTransitionSleep == _systemTransitionType))
2446     {
2447         // Dark->Sleep transition.
2448         // Check if there are any deny sleep assertions.
2449         // lastSleepReason already set by handleOurPowerChangeStart()
2450 
2451         if (!checkSystemCanSleep(lastSleepReason))
2452         {
2453             // Cancel dark wake to sleep transition.
2454             // Must re-scan assertions upon entering dark wake.
2455 
2456             *cancel = true;
2457             DLOG("cancel dark->sleep\n");
2458         }
2459     }
2460 }
2461 
2462 //******************************************************************************
2463 // systemDidNotSleep
2464 //
2465 // Work common to both canceled or aborted sleep.
2466 //******************************************************************************
2467 
2468 void IOPMrootDomain::systemDidNotSleep( void )
2469 {
2470     if (!wrangler)
2471     {
2472         if (idleSeconds)
2473         {
2474             // stay awake for at least idleSeconds
2475             startIdleSleepTimer(idleSeconds);
2476         }
2477     }
2478     else
2479     {
2480         if (sleepSlider && !userIsActive)
2481         {
2482             // Manually start the idle sleep timer besides waiting for
2483             // the user to become inactive.
2484             startIdleSleepTimer( kIdleSleepRetryInterval );
2485         }
2486     }
2487 
2488     preventTransitionToUserActive(false);
2489     IOService::setAdvisoryTickleEnable( true );
2490 }
2491 
2492 //******************************************************************************
2493 // tellNoChangeDown
2494 //
2495 // Notify registered applications and kernel clients that we are not dropping
2496 // power.
2497 //
2498 // We override the superclass implementation so we can send a different message
2499 // type to the client or application being notified.
2500 //
2501 // This must be a vetoed idle sleep, since no other power change can be vetoed.
2502 //******************************************************************************
2503 
2504 void IOPMrootDomain::tellNoChangeDown( unsigned long stateNum )
2505 {
2506     DLOG("tellNoChangeDown %u->%u\n",
2507         (uint32_t) getPowerState(), (uint32_t) stateNum);
2508 
2509     // Sleep canceled, clear the sleep trace point.
2510     tracePoint(kIOPMTracePointSystemUp);
2511 
2512     systemDidNotSleep();
2513     return tellClients( kIOMessageSystemWillNotSleep );
2514 }
2515 
2516 //******************************************************************************
2517 // tellChangeUp
2518 //
2519 // Notify registered applications and kernel clients that we are raising power.
2520 //
2521 // We override the superclass implementation so we can send a different message
2522 // type to the client or application being notified.
2523 //******************************************************************************
2524 
2525 void IOPMrootDomain::tellChangeUp( unsigned long stateNum )
2526 {
2527 
2528     DLOG("tellChangeUp %u->%u\n",
2529         (uint32_t) getPowerState(), (uint32_t) stateNum);
2530 
2531     ignoreTellChangeDown = false;
2532 
2533     if ( stateNum == ON_STATE )
2534     {
2535         // Direct callout into OSKext so it can disable kext unloads
2536         // during sleep/wake to prevent deadlocks.
2537         OSKextSystemSleepOrWake( kIOMessageSystemHasPoweredOn );
2538 
2539         // Notify platform that sleep was cancelled or resumed.
2540         getPlatform()->callPlatformFunction(
2541                         sleepMessagePEFunction, false,
2542                         (void *)(uintptr_t) kIOMessageSystemHasPoweredOn,
2543                         NULL, NULL, NULL);
2544 
2545         if (getPowerState() == ON_STATE)
2546         {
2547             // this is a quick wake from aborted sleep
2548             systemDidNotSleep();
2549             tellClients( kIOMessageSystemWillPowerOn );
2550         }
2551 
2552 
2553         tracePoint( kIOPMTracePointWakeApplications );
2554         tellClients( kIOMessageSystemHasPoweredOn );
2555     }
2556 }
2557 
2558 //******************************************************************************
2559 // sysPowerDownHandler
2560 //
2561 // Perform a vfs sync before system sleep.
2562 //******************************************************************************
2563 
2564 IOReturn IOPMrootDomain::sysPowerDownHandler(
2565     void * target, void * refCon,
2566     UInt32 messageType, IOService * service,
2567     void * messageArgs, vm_size_t argSize )
2568 {
2569     IOReturn    ret = 0;
2570 
2571     DLOG("sysPowerDownHandler message %s\n", getIOMessageString(messageType));
2572 
2573     if (!gRootDomain)
2574         return kIOReturnUnsupported;
2575 
2576     if (messageType == kIOMessageSystemWillSleep)
2577     {
2578 #if HIBERNATION
2579         uint32_t mem_only = 0;
2580         IOPowerStateChangeNotification *notify =
2581                     (IOPowerStateChangeNotification *)messageArgs;
2582 
2583        PE_parse_boot_argn("swd_mem_only", &mem_only, sizeof(mem_only));
2584        if ((mem_only != 1) && (gRootDomain->sleepWakeDebugIsWdogEnabled()))
2585        {
2586            notify->returnValue = 30 * 1000 * 1000;
2587            thread_call_enter1(
2588                               gRootDomain->hibDebugSetupEntry,
2589                               (thread_call_param_t)(uintptr_t) notify->powerRef);
2590        }
2591 #endif
2592     }
2593     else if (messageType == kIOMessageSystemCapabilityChange)
2594     {
2595         IOPMSystemCapabilityChangeParameters * params =
2596             (IOPMSystemCapabilityChangeParameters *) messageArgs;
2597 
2598         // Interested applications have been notified of an impending power
2599         // change and have acked (when applicable).
2600         // This is our chance to save whatever state we can before powering
2601         // down.
2602         // We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c,
2603         // via callout
2604 
2605         DLOG("sysPowerDownHandler cap %x -> %x (flags %x)\n",
2606             params->fromCapabilities, params->toCapabilities,
2607             params->changeFlags);
2608 
2609         if ((params->changeFlags & kIOPMSystemCapabilityWillChange) &&
2610             (params->fromCapabilities & kIOPMSystemCapabilityCPU) &&
2611             (params->toCapabilities & kIOPMSystemCapabilityCPU) == 0)
2612         {
2613             // We will ack within 20 seconds
2614             params->maxWaitForReply = 20 * 1000 * 1000;
2615 #if HIBERNATION
2616             gRootDomain->evaluateSystemSleepPolicyEarly();
2617 
2618             // add in time we could spend freeing pages
2619             if (gRootDomain->hibernateMode && !gRootDomain->hibernateDisabled)
2620             {
2621                 params->maxWaitForReply = kCapabilityClientMaxWait;
2622             }
2623             DLOG("sysPowerDownHandler max wait %d s\n",
2624                 (int) (params->maxWaitForReply / 1000 / 1000));
2625 #endif
2626 
2627             // Notify platform that sleep has begun, after the early
2628             // sleep policy evaluation.
2629             getPlatform()->callPlatformFunction(
2630                             sleepMessagePEFunction, false,
2631                             (void *)(uintptr_t) kIOMessageSystemWillSleep,
2632                             NULL, NULL, NULL);
2633 
2634             if ( !OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending ) )
2635             {
2636                 // Purposely delay the ack and hope that shutdown occurs quickly.
2637                 // Another option is not to schedule the thread and wait for
2638                 // ack timeout...
2639                 AbsoluteTime deadline;
2640                 clock_interval_to_deadline( 30, kSecondScale, &deadline );
2641                 thread_call_enter1_delayed(
2642                     gRootDomain->diskSyncCalloutEntry,
2643                     (thread_call_param_t)(uintptr_t) params->notifyRef,
2644                     deadline );
2645             }
2646             else
2647                 thread_call_enter1(
2648                     gRootDomain->diskSyncCalloutEntry,
2649                     (thread_call_param_t)(uintptr_t) params->notifyRef);
2650         }
2651         else
2652         if ((params->changeFlags & kIOPMSystemCapabilityDidChange) &&
2653             (params->toCapabilities & kIOPMSystemCapabilityCPU) &&
2654             (params->fromCapabilities & kIOPMSystemCapabilityCPU) == 0)
2655         {
2656 #if HIBERNATION
2657             // We will ack within 110 seconds
2658             params->maxWaitForReply = 110 * 1000 * 1000;
2659 
2660             thread_call_enter1(
2661                 gRootDomain->diskSyncCalloutEntry,
2662                 (thread_call_param_t)(uintptr_t) params->notifyRef);
2663 #endif
2664         }
2665         ret = kIOReturnSuccess;
2666     }
2667 
2668     return ret;
2669 }
2670 
2671 //******************************************************************************
2672 // handleQueueSleepWakeUUID
2673 //
2674 // Called from IOPMrootDomain when we're initiating a sleep,
2675 // or indirectly from PM configd when PM decides to clear the UUID.
2676 // PM clears the UUID several minutes after successful wake from sleep,
2677 // so that we might associate App spindumps with the immediately previous
2678 // sleep/wake.
2679 //
2680 // @param   obj has a retain on it. We're responsible for releasing that retain.
2681 //******************************************************************************
2682 
2683 void IOPMrootDomain::handleQueueSleepWakeUUID(OSObject *obj)
2684 {
2685     OSString    *str = NULL;
2686 
2687     if (kOSBooleanFalse == obj)
2688     {
2689         handlePublishSleepWakeUUID(NULL);
2690     }
2691     else if ((str = OSDynamicCast(OSString, obj)))
2692     {
2693         // This branch caches the UUID for an upcoming sleep/wake
2694         if (queuedSleepWakeUUIDString) {
2695             queuedSleepWakeUUIDString->release();
2696             queuedSleepWakeUUIDString = NULL;
2697         }
2698         queuedSleepWakeUUIDString = str;
2699         queuedSleepWakeUUIDString->retain();
2700 
2701         DLOG("SleepWake UUID queued: %s\n", queuedSleepWakeUUIDString->getCStringNoCopy());
2702     }
2703 
2704     if (obj) {
2705         obj->release();
2706     }
2707     return;
2708 
2709 }
2710 //******************************************************************************
2711 // handlePublishSleepWakeUUID
2712 //
2713 // Called from IOPMrootDomain when we're initiating a sleep,
2714 // or indirectly from PM configd when PM decides to clear the UUID.
2715 // PM clears the UUID several minutes after successful wake from sleep,
2716 // so that we might associate App spindumps with the immediately previous
2717 // sleep/wake.
2718 //******************************************************************************
2719 
2720 void IOPMrootDomain::handlePublishSleepWakeUUID( bool shouldPublish )
2721 {
2722    ASSERT_GATED();
2723 
2724    /*
2725     * Clear the current UUID
2726     */
2727    if (gSleepWakeUUIDIsSet)
2728    {
2729         DLOG("SleepWake UUID cleared\n");
2730 
2731         gSleepWakeUUIDIsSet = false;
2732 
2733         removeProperty(kIOPMSleepWakeUUIDKey);
2734         messageClients(kIOPMMessageSleepWakeUUIDChange, kIOPMMessageSleepWakeUUIDCleared);
2735     }
2736 
2737     /*
2738      * Optionally, publish a new UUID
2739      */
2740     if (queuedSleepWakeUUIDString && shouldPublish) {
2741 
2742         OSString  *publishThisUUID = NULL;
2743 
2744         publishThisUUID = queuedSleepWakeUUIDString;
2745         publishThisUUID->retain();
2746 
2747         if (publishThisUUID)
2748         {
2749             setProperty(kIOPMSleepWakeUUIDKey, publishThisUUID);
2750             publishThisUUID->release();
2751         }
2752 
2753         gSleepWakeUUIDIsSet = true;
2754         messageClients(kIOPMMessageSleepWakeUUIDChange, kIOPMMessageSleepWakeUUIDSet);
2755 
2756         queuedSleepWakeUUIDString->release();
2757         queuedSleepWakeUUIDString = NULL;
2758     }
2759 }
2760 
2761 //******************************************************************************
2762 // initializeBootSessionUUID
2763 //
2764 // Initialize the boot session uuid at boot up and sets it into registry.
2765 //******************************************************************************
2766 
2767 void IOPMrootDomain::initializeBootSessionUUID(void)
2768 {
2769     uuid_t          new_uuid;
2770     uuid_string_t   new_uuid_string;
2771 
2772     uuid_generate(new_uuid);
2773     uuid_unparse_upper(new_uuid, new_uuid_string);
2774     memcpy(bootsessionuuid_string, new_uuid_string, sizeof(uuid_string_t));
2775 
2776     setProperty(kIOPMBootSessionUUIDKey, new_uuid_string);
2777 }
2778 
2779 //******************************************************************************
2780 // changePowerStateTo & changePowerStateToPriv
2781 //
2782 // Override of these methods for logging purposes.
2783 //******************************************************************************
2784 
2785 IOReturn IOPMrootDomain::changePowerStateTo( unsigned long ordinal )
2786 {
2787     DLOG("changePowerStateTo(%lu)\n", ordinal);
2788 
2789     if ((ordinal != ON_STATE) && (ordinal != SLEEP_STATE))
2790         return kIOReturnUnsupported;
2791 
2792     return super::changePowerStateTo(ordinal);
2793 }
2794 
2795 IOReturn IOPMrootDomain::changePowerStateToPriv( unsigned long ordinal )
2796 {
2797     DLOG("changePowerStateToPriv(%lu)\n", ordinal);
2798 
2799     if ((ordinal != ON_STATE) && (ordinal != SLEEP_STATE))
2800         return kIOReturnUnsupported;
2801 
2802     return super::changePowerStateToPriv(ordinal);
2803 }
2804 
2805 //******************************************************************************
2806 // activity detect
2807 //
2808 //******************************************************************************
2809 
2810 bool IOPMrootDomain::activitySinceSleep(void)
2811 {
2812     return (userActivityCount != userActivityAtSleep);
2813 }
2814 
2815 bool IOPMrootDomain::abortHibernation(void)
2816 {
2817     bool ret = activitySinceSleep();
2818 
2819     if (ret && !hibernateAborted && checkSystemCanSustainFullWake())
2820     {
2821         DLOG("activitySinceSleep ABORT [%d, %d]\n", userActivityCount, userActivityAtSleep);
2822         hibernateAborted = true;
2823     }
2824     return (ret);
2825 }
2826 
2827 extern "C" int
2828 hibernate_should_abort(void)
2829 {
2830     if (gRootDomain)
2831         return (gRootDomain->abortHibernation());
2832     else
2833         return (0);
2834 }
2835 
2836 //******************************************************************************
2837 // willNotifyPowerChildren
2838 //
2839 // Called after all interested drivers have all acknowledged the power change,
2840 // but before any power children is informed. Dispatched though a thread call,
2841 // so it is safe to perform work that might block on a sleeping disk. PM state
2842 // machine (not thread) will block w/o timeout until this function returns.
2843 //******************************************************************************
2844 
2845 void IOPMrootDomain::willNotifyPowerChildren( IOPMPowerStateIndex newPowerState )
2846 {
2847 #if HIBERNATION
2848     if (SLEEP_STATE == newPowerState)
2849     {
2850         IOHibernateSystemSleep();
2851         IOHibernateIOKitSleep();
2852     }
2853 #endif
2854 }
2855 
2856 //******************************************************************************
2857 // sleepOnClamshellClosed
2858 //
2859 // contains the logic to determine if the system should sleep when the clamshell
2860 // is closed.
2861 //******************************************************************************
2862 
2863 bool IOPMrootDomain::shouldSleepOnClamshellClosed( void )
2864 {
2865     if (!clamshellExists)
2866         return false;
2867 
2868     DLOG("clamshell closed %d, disabled %d, desktopMode %d, ac %d sleepDisabled %d\n",
2869         clamshellClosed, clamshellDisabled, desktopMode, acAdaptorConnected, clamshellSleepDisabled);
2870 
2871     return ( !clamshellDisabled && !(desktopMode && acAdaptorConnected) && !clamshellSleepDisabled );
2872 }
2873 
2874 void IOPMrootDomain::sendClientClamshellNotification( void )
2875 {
2876     /* Only broadcast clamshell alert if clamshell exists. */
2877     if (!clamshellExists)
2878         return;
2879 
2880     setProperty(kAppleClamshellStateKey,
2881         clamshellClosed ? kOSBooleanTrue : kOSBooleanFalse);
2882 
2883     setProperty(kAppleClamshellCausesSleepKey,
2884         shouldSleepOnClamshellClosed() ? kOSBooleanTrue : kOSBooleanFalse);
2885 
2886     /* Argument to message is a bitfiel of
2887      *      ( kClamshellStateBit | kClamshellSleepBit )
2888      */
2889     messageClients(kIOPMMessageClamshellStateChange,
2890         (void *)(uintptr_t) ( (clamshellClosed ? kClamshellStateBit : 0)
2891              | ( shouldSleepOnClamshellClosed() ? kClamshellSleepBit : 0)) );
2892 }
2893 
2894 //******************************************************************************
2895 // getSleepSupported
2896 //
2897 // Deprecated
2898 //******************************************************************************
2899 
2900 IOOptionBits IOPMrootDomain::getSleepSupported( void )
2901 {
2902     return( platformSleepSupport );
2903 }
2904 
2905 //******************************************************************************
2906 // setSleepSupported
2907 //
2908 // Deprecated
2909 //******************************************************************************
2910 
2911 void IOPMrootDomain::setSleepSupported( IOOptionBits flags )
2912 {
2913     DLOG("setSleepSupported(%x)\n", (uint32_t) flags);
2914     OSBitOrAtomic(flags, &platformSleepSupport);
2915 }
2916 
2917 //******************************************************************************
2918 // setDisableClamShellSleep
2919 //
2920 //******************************************************************************
2921 
2922 void IOPMrootDomain::setDisableClamShellSleep( bool val )
2923 {
2924     if (gIOPMWorkLoop->inGate() == false) {
2925 
2926        gIOPMWorkLoop->runAction(
2927                OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::setDisableClamShellSleep),
2928                (OSObject *)this,
2929                (void *)val);
2930 
2931        return;
2932     }
2933     else {
2934        DLOG("setDisableClamShellSleep(%x)\n", (uint32_t) val);
2935        if ( clamshellSleepDisabled != val )
2936        {
2937            clamshellSleepDisabled = val;
2938            // If clamshellSleepDisabled is reset to 0, reevaluate if
2939            // system need to go to sleep due to clamshell state
2940            if ( !clamshellSleepDisabled && clamshellClosed)
2941               handlePowerNotification(kLocalEvalClamshellCommand);
2942        }
2943     }
2944 }
2945 
2946 //******************************************************************************
2947 // wakeFromDoze
2948 //
2949 // Deprecated.
2950 //******************************************************************************
2951 
2952 void IOPMrootDomain::wakeFromDoze( void )
2953 {
2954     // Preserve symbol for familes (IOUSBFamily and IOGraphics)
2955 }
2956 
2957 // MARK: -
2958 // MARK: Features
2959 
2960 //******************************************************************************
2961 // publishFeature
2962 //
2963 // Adds a new feature to the supported features dictionary
2964 //******************************************************************************
2965 
2966 void IOPMrootDomain::publishFeature( const char * feature )
2967 {
2968     publishFeature(feature, kRD_AllPowerSources, NULL);
2969 }
2970 
2971 //******************************************************************************
2972 // publishFeature (with supported power source specified)
2973 //
2974 // Adds a new feature to the supported features dictionary
2975 //******************************************************************************
2976 
2977 void IOPMrootDomain::publishFeature(
2978     const char *feature,
2979     uint32_t supportedWhere,
2980     uint32_t *uniqueFeatureID)
2981 {
2982     static uint16_t     next_feature_id = 500;
2983 
2984     OSNumber            *new_feature_data = NULL;
2985     OSNumber            *existing_feature = NULL;
2986     OSArray             *existing_feature_arr = NULL;
2987     OSObject            *osObj = NULL;
2988     uint32_t            feature_value = 0;
2989 
2990     supportedWhere &= kRD_AllPowerSources; // mask off any craziness!
2991 
2992     if(!supportedWhere) {
2993         // Feature isn't supported anywhere!
2994         return;
2995     }
2996 
2997     if(next_feature_id > 5000) {
2998         // Far, far too many features!
2999         return;
3000     }
3001 
3002     if(featuresDictLock) IOLockLock(featuresDictLock);
3003 
3004     OSDictionary *features =
3005         (OSDictionary *) getProperty(kRootDomainSupportedFeatures);
3006 
3007     // Create new features dict if necessary
3008     if ( features && OSDynamicCast(OSDictionary, features)) {
3009         features = OSDictionary::withDictionary(features);
3010     } else {
3011         features = OSDictionary::withCapacity(1);
3012     }
3013 
3014     // Create OSNumber to track new feature
3015 
3016     next_feature_id += 1;
3017     if( uniqueFeatureID ) {
3018         // We don't really mind if the calling kext didn't give us a place
3019         // to stash their unique id. Many kexts don't plan to unload, and thus
3020         // have no need to remove themselves later.
3021         *uniqueFeatureID = next_feature_id;
3022     }
3023 
3024     feature_value = (uint32_t)next_feature_id;
3025     feature_value <<= 16;
3026     feature_value += supportedWhere;
3027 
3028     new_feature_data = OSNumber::withNumber(
3029                                 (unsigned long long)feature_value, 32);
3030 
3031     // Does features object already exist?
3032     if( (osObj = features->getObject(feature)) )
3033     {
3034         if(( existing_feature = OSDynamicCast(OSNumber, osObj) ))
3035         {
3036             // We need to create an OSArray to hold the now 2 elements.
3037             existing_feature_arr = OSArray::withObjects(
3038                             (const OSObject **)&existing_feature, 1, 2);
3039         } else if(( existing_feature_arr = OSDynamicCast(OSArray, osObj) ))
3040         {
3041             // Add object to existing array
3042             existing_feature_arr = OSArray::withArray(
3043                             existing_feature_arr,
3044                             existing_feature_arr->getCount() + 1);
3045         }
3046 
3047         if (existing_feature_arr)
3048         {
3049             existing_feature_arr->setObject(new_feature_data);
3050             features->setObject(feature, existing_feature_arr);
3051             existing_feature_arr->release();
3052             existing_feature_arr = 0;
3053         }
3054     } else {
3055         // The easy case: no previously existing features listed. We simply
3056         // set the OSNumber at key 'feature' and we're on our way.
3057         features->setObject(feature, new_feature_data);
3058     }
3059 
3060     new_feature_data->release();
3061 
3062     setProperty(kRootDomainSupportedFeatures, features);
3063 
3064     features->release();
3065 
3066     if(featuresDictLock) IOLockUnlock(featuresDictLock);
3067 
3068     // Notify EnergySaver and all those in user space so they might
3069     // re-populate their feature specific UI
3070     if(pmPowerStateQueue) {
3071         pmPowerStateQueue->submitPowerEvent( kPowerEventFeatureChanged );
3072     }
3073 }
3074 
3075 //******************************************************************************
3076 // removePublishedFeature
3077 //
3078 // Removes previously published feature
3079 //******************************************************************************
3080 
3081 IOReturn IOPMrootDomain::removePublishedFeature( uint32_t removeFeatureID )
3082 {
3083     IOReturn                ret = kIOReturnError;
3084     uint32_t                feature_value = 0;
3085     uint16_t                feature_id = 0;
3086     bool                    madeAChange = false;
3087 
3088     OSSymbol                *dictKey = NULL;
3089     OSCollectionIterator    *dictIterator = NULL;
3090     OSArray                 *arrayMember  = NULL;
3091     OSNumber                *numberMember = NULL;
3092     OSObject                *osObj        = NULL;
3093     OSNumber                *osNum        = NULL;
3094     OSArray                 *arrayMemberCopy;
3095 
3096     if (kBadPMFeatureID == removeFeatureID)
3097         return kIOReturnNotFound;
3098 
3099     if(featuresDictLock) IOLockLock(featuresDictLock);
3100 
3101     OSDictionary *features =
3102         (OSDictionary *) getProperty(kRootDomainSupportedFeatures);
3103 
3104     if ( features && OSDynamicCast(OSDictionary, features) )
3105     {
3106         // Any modifications to the dictionary are made to the copy to prevent
3107         // races & crashes with userland clients. Dictionary updated
3108         // automically later.
3109         features = OSDictionary::withDictionary(features);
3110     } else {
3111         features = NULL;
3112         ret = kIOReturnNotFound;
3113         goto exit;
3114     }
3115 
3116     // We iterate 'features' dictionary looking for an entry tagged
3117     // with 'removeFeatureID'. If found, we remove it from our tracking
3118     // structures and notify the OS via a general interest message.
3119 
3120     dictIterator = OSCollectionIterator::withCollection(features);
3121     if(!dictIterator) {
3122         goto exit;
3123     }
3124 
3125     while( (dictKey = OSDynamicCast(OSSymbol, dictIterator->getNextObject())) )
3126     {
3127         osObj = features->getObject(dictKey);
3128 
3129         // Each Feature is either tracked by an OSNumber
3130         if( osObj && (numberMember = OSDynamicCast(OSNumber, osObj)) )
3131         {
3132             feature_value = numberMember->unsigned32BitValue();
3133             feature_id = (uint16_t)(feature_value >> 16);
3134 
3135             if( feature_id == (uint16_t)removeFeatureID )
3136             {
3137                 // Remove this node
3138                 features->removeObject(dictKey);
3139                 madeAChange = true;
3140                 break;
3141             }
3142 
3143         // Or tracked by an OSArray of OSNumbers
3144         } else if( osObj && (arrayMember = OSDynamicCast(OSArray, osObj)) )
3145         {
3146             unsigned int arrayCount = arrayMember->getCount();
3147 
3148             for(unsigned int i=0; i<arrayCount; i++)
3149             {
3150                 osNum = OSDynamicCast(OSNumber, arrayMember->getObject(i));
3151                 if(!osNum) {
3152                     continue;
3153                 }
3154 
3155                 feature_value = osNum->unsigned32BitValue();
3156                 feature_id = (uint16_t)(feature_value >> 16);
3157 
3158                 if( feature_id == (uint16_t)removeFeatureID )
3159                 {
3160                     // Remove this node
3161                     if( 1 == arrayCount ) {
3162                         // If the array only contains one element, remove
3163                         // the whole thing.
3164                         features->removeObject(dictKey);
3165                     } else {
3166                         // Otherwise remove the element from a copy of the array.
3167                         arrayMemberCopy = OSArray::withArray(arrayMember);
3168                         if (arrayMemberCopy)
3169                         {
3170                             arrayMemberCopy->removeObject(i);
3171                             features->setObject(dictKey, arrayMemberCopy);
3172                             arrayMemberCopy->release();
3173                         }
3174                     }
3175 
3176                     madeAChange = true;
3177                     break;
3178                 }
3179             }
3180         }
3181     }
3182 
3183     dictIterator->release();
3184 
3185     if( madeAChange )
3186     {
3187         ret = kIOReturnSuccess;
3188 
3189         setProperty(kRootDomainSupportedFeatures, features);
3190 
3191         // Notify EnergySaver and all those in user space so they might
3192         // re-populate their feature specific UI
3193         if(pmPowerStateQueue) {
3194             pmPowerStateQueue->submitPowerEvent( kPowerEventFeatureChanged );
3195         }
3196     } else {
3197         ret = kIOReturnNotFound;
3198     }
3199 
3200 exit:
3201     if(features)    features->release();
3202     if(featuresDictLock) IOLockUnlock(featuresDictLock);
3203     return ret;
3204 }
3205 
3206 //******************************************************************************
3207 // publishPMSetting (private)
3208 //
3209 // Should only be called by PMSettingObject to publish a PM Setting as a
3210 // supported feature.
3211 //******************************************************************************
3212 
3213 void IOPMrootDomain::publishPMSetting(
3214     const OSSymbol * feature, uint32_t where, uint32_t * featureID )
3215 {
3216     if (noPublishPMSettings &&
3217         (noPublishPMSettings->getNextIndexOfObject(feature, 0) != (unsigned int)-1))
3218     {
3219         // Setting found in noPublishPMSettings array
3220         *featureID = kBadPMFeatureID;
3221         return;
3222     }
3223 
3224     publishFeature(
3225         feature->getCStringNoCopy(), where, featureID);
3226 }
3227 
3228 //******************************************************************************
3229 // setPMSetting (private)
3230 //
3231 // Internal helper to relay PM settings changes from user space to individual
3232 // drivers. Should be called only by IOPMrootDomain::setProperties.
3233 //******************************************************************************
3234 
3235 IOReturn IOPMrootDomain::setPMSetting(
3236     const OSSymbol  *type,
3237     OSObject        *object )
3238 {
3239     PMSettingCallEntry  *entries = 0;
3240     OSArray             *chosen  = 0;
3241     const OSArray       *array;
3242     PMSettingObject     *pmso;
3243     thread_t            thisThread;
3244     int                 i, j, count, capacity;
3245 
3246     if (NULL == type)
3247         return kIOReturnBadArgument;
3248 
3249     PMSETTING_LOCK();
3250 
3251     // Update settings dict so changes are visible from copyPMSetting().
3252     fPMSettingsDict->setObject(type, object);
3253 
3254     // Prep all PMSetting objects with the given 'type' for callout.
3255     array = (const OSArray *) settingsCallbacks->getObject(type);
3256     if (!array || ((capacity = array->getCount()) == 0))
3257         goto unlock_exit;
3258 
3259     // Array to retain PMSetting objects targeted for callout.
3260     chosen = OSArray::withCapacity(capacity);
3261     if (!chosen)
3262         goto unlock_exit;   // error
3263 
3264     entries = IONew(PMSettingCallEntry, capacity);
3265     if (!entries)
3266         goto unlock_exit;   // error
3267     memset(entries, 0, sizeof(PMSettingCallEntry) * capacity);
3268 
3269     thisThread = current_thread();
3270 
3271     for (i = 0, j = 0; i<capacity; i++)
3272     {
3273         pmso = (PMSettingObject *) array->getObject(i);
3274         if (pmso->disabled)
3275             continue;
3276         entries[j].thread = thisThread;
3277         queue_enter(&pmso->calloutQueue, &entries[j], PMSettingCallEntry *, link);
3278         chosen->setObject(pmso);
3279         j++;
3280     }
3281     count = j;
3282     if (!count)
3283         goto unlock_exit;
3284 
3285     PMSETTING_UNLOCK();
3286 
3287     // Call each pmso in the chosen array.
3288     for (i=0; i<count; i++)
3289     {
3290         pmso = (PMSettingObject *) chosen->getObject(i);
3291         pmso->dispatchPMSetting(type, object);
3292     }
3293 
3294     PMSETTING_LOCK();
3295     for (i=0; i<count; i++)
3296     {
3297         pmso = (PMSettingObject *) chosen->getObject(i);
3298         queue_remove(&pmso->calloutQueue, &entries[i], PMSettingCallEntry *, link);
3299         if (pmso->waitThread)
3300         {
3301             PMSETTING_WAKEUP(pmso);
3302         }
3303     }
3304 unlock_exit:
3305     PMSETTING_UNLOCK();
3306 
3307     if (chosen)  chosen->release();
3308     if (entries) IODelete(entries, PMSettingCallEntry, capacity);
3309 
3310     return kIOReturnSuccess;
3311 }
3312 
3313 //******************************************************************************
3314 // copyPMSetting (public)
3315 //
3316 // Allows kexts to safely read setting values, without being subscribed to
3317 // notifications.
3318 //******************************************************************************
3319 
3320 OSObject * IOPMrootDomain::copyPMSetting(
3321     OSSymbol *whichSetting)
3322 {
3323     OSObject *obj = NULL;
3324 
3325     if(!whichSetting) return NULL;
3326 
3327     PMSETTING_LOCK();
3328     obj = fPMSettingsDict->getObject(whichSetting);
3329     if(obj) {
3330         obj->retain();
3331     }
3332     PMSETTING_UNLOCK();
3333 
3334     return obj;
3335 }
3336 
3337 //******************************************************************************
3338 // registerPMSettingController (public)
3339 //
3340 // direct wrapper to registerPMSettingController with uint32_t power source arg
3341 //******************************************************************************
3342 
3343 IOReturn IOPMrootDomain::registerPMSettingController(
3344     const OSSymbol *                settings[],
3345     IOPMSettingControllerCallback   func,
3346     OSObject                        *target,
3347     uintptr_t                       refcon,
3348     OSObject                        **handle)
3349 {
3350     return registerPMSettingController(
3351             settings,
3352             (kIOPMSupportedOnAC | kIOPMSupportedOnBatt | kIOPMSupportedOnUPS),
3353             func, target, refcon, handle);
3354 }
3355 
3356 //******************************************************************************
3357 // registerPMSettingController (public)
3358 //
3359 // Kexts may register for notifications when a particular setting is changed.
3360 // A list of settings is available in IOPM.h.
3361 // Arguments:
3362 //  * settings - An OSArray containing OSSymbols. Caller should populate this
3363 //          array with a list of settings caller wants notifications from.
3364 //  * func - A C function callback of the type IOPMSettingControllerCallback
3365 //  * target - caller may provide an OSObject *, which PM will pass as an
3366 //          target to calls to "func"
3367 //  * refcon - caller may provide an void *, which PM will pass as an
3368 //          argument to calls to "func"
3369 //  * handle - This is a return argument. We will populate this pointer upon
3370 //          call success. Hold onto this and pass this argument to
3371 //          IOPMrootDomain::deRegisterPMSettingCallback when unloading your kext
3372 // Returns:
3373 //      kIOReturnSuccess on success
3374 //******************************************************************************
3375 
3376 IOReturn IOPMrootDomain::registerPMSettingController(
3377     const OSSymbol *                settings[],
3378     uint32_t                        supportedPowerSources,
3379     IOPMSettingControllerCallback   func,
3380     OSObject                        *target,
3381     uintptr_t                       refcon,
3382     OSObject                        **handle)
3383 {
3384     PMSettingObject *pmso = NULL;
3385     OSObject        *pmsh = NULL;
3386     OSArray         *list = NULL;
3387     int             i;
3388 
3389     if (NULL == settings ||
3390         NULL == func     ||
3391         NULL == handle)
3392     {
3393         return kIOReturnBadArgument;
3394     }
3395 
3396     pmso = PMSettingObject::pmSettingObject(
3397                 (IOPMrootDomain *) this, func, target,
3398                 refcon, supportedPowerSources, settings, &pmsh);
3399 
3400     if (!pmso) {
3401         *handle = NULL;
3402         return kIOReturnInternalError;
3403     }
3404 
3405     PMSETTING_LOCK();
3406     for (i=0; settings[i]; i++)
3407     {
3408         list = (OSArray *) settingsCallbacks->getObject(settings[i]);
3409         if (!list) {
3410             // New array of callbacks for this setting
3411             list = OSArray::withCapacity(1);
3412             settingsCallbacks->setObject(settings[i], list);
3413             list->release();
3414         }
3415 
3416         // Add caller to the callback list
3417         list->setObject(pmso);
3418     }
3419     PMSETTING_UNLOCK();
3420 
3421     // Return handle to the caller, the setting object is private.
3422     *handle = pmsh;
3423 
3424     return kIOReturnSuccess;
3425 }
3426 
3427 //******************************************************************************
3428 // deregisterPMSettingObject (private)
3429 //
3430 // Only called from PMSettingObject.
3431 //******************************************************************************
3432 
3433 void IOPMrootDomain::deregisterPMSettingObject( PMSettingObject * pmso )
3434 {
3435     thread_t                thisThread = current_thread();
3436     PMSettingCallEntry      *callEntry;
3437     OSCollectionIterator    *iter;
3438     OSSymbol                *sym;
3439     OSArray                 *array;
3440     int                     index;
3441     bool                    wait;
3442 
3443     PMSETTING_LOCK();
3444 
3445     pmso->disabled = true;
3446 
3447     // Wait for all callout threads to finish.
3448     do {
3449         wait = false;
3450         queue_iterate(&pmso->calloutQueue, callEntry, PMSettingCallEntry *, link)
3451         {
3452             if (callEntry->thread != thisThread)
3453             {
3454                 wait = true;
3455                 break;
3456             }
3457         }
3458         if (wait)
3459         {
3460             assert(0 == pmso->waitThread);
3461             pmso->waitThread = thisThread;
3462             PMSETTING_WAIT(pmso);
3463             pmso->waitThread = 0;
3464         }
3465     } while (wait);
3466 
3467     // Search each PM settings array in the kernel.
3468     iter = OSCollectionIterator::withCollection(settingsCallbacks);
3469     if (iter)
3470     {
3471         while ((sym = OSDynamicCast(OSSymbol, iter->getNextObject())))
3472         {
3473             array = (OSArray *) settingsCallbacks->getObject(sym);
3474             index = array->getNextIndexOfObject(pmso, 0);
3475             if (-1 != index) {
3476                 array->removeObject(index);
3477             }
3478         }
3479         iter->release();
3480     }
3481 
3482     PMSETTING_UNLOCK();
3483 
3484     pmso->release();
3485 }
3486 
3487 //******************************************************************************
3488 // informCPUStateChange
3489 //
3490 // Call into PM CPU code so that CPU power savings may dynamically adjust for
3491 // running on battery, with the lid closed, etc.
3492 //
3493 // informCPUStateChange is a no-op on non x86 systems
3494 // only x86 has explicit support in the IntelCPUPowerManagement kext
3495 //******************************************************************************
3496 
3497 void IOPMrootDomain::informCPUStateChange(
3498     uint32_t type,
3499     uint32_t value )
3500 {
3501 #if defined(__i386__) || defined(__x86_64__)
3502 
3503     pmioctlVariableInfo_t varInfoStruct;
3504     int                 pmCPUret = 0;
3505     const char          *varNameStr = NULL;
3506     int32_t             *varIndex   = NULL;
3507 
3508     if (kInformAC == type) {
3509         varNameStr = kIOPMRootDomainBatPowerCString;
3510         varIndex = &idxPMCPULimitedPower;
3511     } else if (kInformLid == type) {
3512         varNameStr = kIOPMRootDomainLidCloseCString;
3513         varIndex = &idxPMCPUClamshell;
3514     } else {
3515         return;
3516     }
3517 
3518     // Set the new value!
3519     // pmCPUControl will assign us a new ID if one doesn't exist yet
3520     bzero(&varInfoStruct, sizeof(pmioctlVariableInfo_t));
3521     varInfoStruct.varID         = *varIndex;
3522     varInfoStruct.varType       = vBool;
3523     varInfoStruct.varInitValue  = value;
3524     varInfoStruct.varCurValue   = value;
3525     strncpy( (char *)varInfoStruct.varName,
3526              (const char *)varNameStr,
3527              strlen(varNameStr) + 1 );
3528 
3529     // Set!
3530     pmCPUret = pmCPUControl( PMIOCSETVARINFO, (void *)&varInfoStruct );
3531 
3532     // pmCPU only assigns numerical id's when a new varName is specified
3533     if ((0 == pmCPUret)
3534         && (*varIndex == kCPUUnknownIndex))
3535     {
3536         // pmCPUControl has assigned us a new variable ID.
3537         // Let's re-read the structure we just SET to learn that ID.
3538         pmCPUret = pmCPUControl( PMIOCGETVARNAMEINFO, (void *)&varInfoStruct );
3539 
3540         if (0 == pmCPUret)
3541         {
3542             // Store it in idxPMCPUClamshell or idxPMCPULimitedPower
3543             *varIndex = varInfoStruct.varID;
3544         }
3545     }
3546 
3547     return;
3548 
3549 #endif /* __i386__ || __x86_64__ */
3550 }
3551 
3552 // MARK: -
3553 // MARK: Deep Sleep Policy
3554 
3555 #if HIBERNATION
3556 
3557 //******************************************************************************
3558 // evaluateSystemSleepPolicy
3559 //******************************************************************************
3560 
3561 #define kIOPlatformSystemSleepPolicyKey     "IOPlatformSystemSleepPolicy"
3562 
3563 // Sleep flags
3564 enum {
3565     kIOPMSleepFlagHibernate         = 0x00000001,
3566     kIOPMSleepFlagSleepTimerEnable  = 0x00000002
3567 };
3568 
3569 struct IOPMSystemSleepPolicyEntry
3570 {
3571     uint32_t    factorMask;
3572     uint32_t    factorBits;
3573     uint32_t    sleepFlags;
3574     uint32_t    wakeEvents;
3575 } __attribute__((packed));
3576 
3577 struct IOPMSystemSleepPolicyTable
3578 {
3579     uint32_t    signature;
3580     uint16_t    version;
3581     uint16_t    entryCount;
3582     IOPMSystemSleepPolicyEntry  entries[];
3583 } __attribute__((packed));
3584 
3585 enum {
3586     kIOPMSleepAttributeHibernateSetup   = 0x00000001,
3587     kIOPMSleepAttributeHibernateSleep   = 0x00000002
3588 };
3589 
3590 static uint32_t
3591 getSleepTypeAttributes( uint32_t sleepType )
3592 {
3593     static const uint32_t sleepTypeAttributes[ kIOPMSleepTypeLast ] =
3594     {
3595     /* invalid   */ 0,
3596     /* abort     */ 0,
3597     /* normal    */ 0,
3598     /* safesleep */ kIOPMSleepAttributeHibernateSetup,
3599     /* hibernate */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
3600     /* standby   */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
3601     /* poweroff  */ kIOPMSleepAttributeHibernateSetup | kIOPMSleepAttributeHibernateSleep,
3602     /* deepidle  */ 0
3603     };
3604 
3605     if (sleepType >= kIOPMSleepTypeLast)
3606         return 0;
3607 
3608     return sleepTypeAttributes[sleepType];
3609 }
3610 
3611 bool IOPMrootDomain::evaluateSystemSleepPolicy(
3612     IOPMSystemSleepParameters * params, int sleepPhase, uint32_t * hibMode )
3613 {
3614     const IOPMSystemSleepPolicyTable * pt;
3615     OSObject *  prop = 0;
3616     OSData *    policyData;
3617     uint64_t    currentFactors = 0;
3618     uint32_t    standbyDelay   = 0;
3619     uint32_t    powerOffDelay  = 0;
3620     uint32_t    powerOffTimer  = 0;
3621     uint32_t    mismatch;
3622     bool        standbyEnabled;
3623     bool        powerOffEnabled;
3624     bool        found = false;
3625 
3626     // Get platform's sleep policy table
3627     if (!gSleepPolicyHandler)
3628     {
3629         prop = getServiceRoot()->copyProperty(kIOPlatformSystemSleepPolicyKey);
3630         if (!prop) goto done;
3631     }
3632 
3633     // Fetch additional settings
3634     standbyEnabled = (getSleepOption(kIOPMDeepSleepDelayKey, &standbyDelay)
3635         && (getProperty(kIOPMDeepSleepEnabledKey) == kOSBooleanTrue));
3636     powerOffEnabled = (getSleepOption(kIOPMAutoPowerOffDelayKey, &powerOffDelay)
3637         && (getProperty(kIOPMAutoPowerOffEnabledKey) == kOSBooleanTrue));
3638     if (!getSleepOption(kIOPMAutoPowerOffTimerKey, &powerOffTimer))
3639         powerOffTimer = powerOffDelay;
3640 
3641     DLOG("phase %d, standby %d delay %u, poweroff %d delay %u timer %u, hibernate 0x%x\n",
3642         sleepPhase, standbyEnabled, standbyDelay,
3643         powerOffEnabled, powerOffDelay, powerOffTimer, *hibMode);
3644 
3645     // pmset level overrides
3646     if ((*hibMode & kIOHibernateModeOn) == 0)
3647     {
3648         if (!gSleepPolicyHandler)
3649         {
3650             standbyEnabled  = false;
3651             powerOffEnabled = false;
3652         }
3653     }
3654     else if (!(*hibMode & kIOHibernateModeSleep))
3655     {
3656         // Force hibernate (i.e. mode 25)
3657         // If standby is enabled, force standy.
3658         // If poweroff is enabled, force poweroff.
3659         if (standbyEnabled)
3660             currentFactors |= kIOPMSleepFactorStandbyForced;
3661         else if (powerOffEnabled)
3662             currentFactors |= kIOPMSleepFactorAutoPowerOffForced;
3663         else
3664             currentFactors |= kIOPMSleepFactorHibernateForced;
3665     }
3666 
3667     // Current factors based on environment and assertions
3668     if (sleepTimerMaintenance)
3669         currentFactors |= kIOPMSleepFactorSleepTimerWake;
3670     if (standbyEnabled && sleepToStandby && !gSleepPolicyHandler)
3671         currentFactors |= kIOPMSleepFactorSleepTimerWake;
3672     if (!clamshellClosed)
3673         currentFactors |= kIOPMSleepFactorLidOpen;
3674     if (acAdaptorConnected)
3675         currentFactors |= kIOPMSleepFactorACPower;
3676     if (lowBatteryCondition)
3677         currentFactors |= kIOPMSleepFactorBatteryLow;
3678     if (!standbyDelay)
3679         currentFactors |= kIOPMSleepFactorStandbyNoDelay;
3680     if (!standbyEnabled)
3681         currentFactors |= kIOPMSleepFactorStandbyDisabled;
3682     if (getPMAssertionLevel(kIOPMDriverAssertionUSBExternalDeviceBit) !=
3683         kIOPMDriverAssertionLevelOff)
3684         currentFactors |= kIOPMSleepFactorUSBExternalDevice;
3685     if (getPMAssertionLevel(kIOPMDriverAssertionBluetoothHIDDevicePairedBit) !=
3686         kIOPMDriverAssertionLevelOff)
3687         currentFactors |= kIOPMSleepFactorBluetoothHIDDevice;
3688     if (getPMAssertionLevel(kIOPMDriverAssertionExternalMediaMountedBit) !=
3689         kIOPMDriverAssertionLevelOff)
3690         currentFactors |= kIOPMSleepFactorExternalMediaMounted;
3691     if (getPMAssertionLevel(kIOPMDriverAssertionReservedBit5) !=
3692         kIOPMDriverAssertionLevelOff)
3693         currentFactors |= kIOPMSleepFactorThunderboltDevice;
3694     if (_scheduledAlarms != 0)
3695         currentFactors |= kIOPMSleepFactorRTCAlarmScheduled;
3696     if (getPMAssertionLevel(kIOPMDriverAssertionMagicPacketWakeEnabledBit) !=
3697         kIOPMDriverAssertionLevelOff)
3698         currentFactors |= kIOPMSleepFactorMagicPacketWakeEnabled;
3699 #define TCPKEEPALIVE 1
3700 #if TCPKEEPALIVE
3701     if (getPMAssertionLevel(kIOPMDriverAssertionNetworkKeepAliveActiveBit) !=
3702         kIOPMDriverAssertionLevelOff)
3703         currentFactors |= kIOPMSleepFactorNetworkKeepAliveActive;
3704 #endif
3705     if (!powerOffEnabled)
3706         currentFactors |= kIOPMSleepFactorAutoPowerOffDisabled;
3707     if (desktopMode)
3708         currentFactors |= kIOPMSleepFactorExternalDisplay;
3709     if (userWasActive)
3710         currentFactors |= kIOPMSleepFactorLocalUserActivity;
3711     if (darkWakeHibernateError && !CAP_HIGHEST(kIOPMSystemCapabilityGraphics))
3712         currentFactors |= kIOPMSleepFactorHibernateFailed;
3713 
3714     DLOG("sleep factors 0x%llx\n", currentFactors);
3715 
3716     if (gSleepPolicyHandler)
3717     {
3718         uint32_t    savedHibernateMode;
3719         IOReturn    result;
3720 
3721         if (!gSleepPolicyVars)
3722         {
3723             gSleepPolicyVars = IONew(IOPMSystemSleepPolicyVariables, 1);
3724             if (!gSleepPolicyVars)
3725                 goto done;
3726             bzero(gSleepPolicyVars, sizeof(*gSleepPolicyVars));
3727         }
3728         gSleepPolicyVars->signature = kIOPMSystemSleepPolicySignature;
3729         gSleepPolicyVars->version   = kIOPMSystemSleepPolicyVersion;
3730         gSleepPolicyVars->currentCapability = _currentCapability;
3731         gSleepPolicyVars->highestCapability = _highestCapability;
3732         gSleepPolicyVars->sleepFactors      = currentFactors;
3733         gSleepPolicyVars->sleepReason       = lastSleepReason;
3734         gSleepPolicyVars->sleepPhase        = sleepPhase;
3735         gSleepPolicyVars->standbyDelay      = standbyDelay;
3736         gSleepPolicyVars->poweroffDelay     = powerOffDelay;
3737         gSleepPolicyVars->scheduledAlarms   = _scheduledAlarms | _userScheduledAlarm;
3738         gSleepPolicyVars->poweroffTimer     = powerOffTimer;
3739 
3740         if (kIOPMSleepPhase0 == sleepPhase)
3741         {
3742             // preserve hibernateMode
3743             savedHibernateMode = gSleepPolicyVars->hibernateMode;
3744             gSleepPolicyVars->hibernateMode = *hibMode;
3745         }
3746         else if (kIOPMSleepPhase1 == sleepPhase)
3747         {
3748             // use original hibernateMode for phase2
3749             gSleepPolicyVars->hibernateMode = *hibMode;
3750         }
3751 
3752         result = gSleepPolicyHandler(gSleepPolicyTarget, gSleepPolicyVars, params);
3753 
3754         if (kIOPMSleepPhase0 == sleepPhase)
3755         {
3756             // restore hibernateMode
3757             gSleepPolicyVars->hibernateMode = savedHibernateMode;
3758         }
3759 
3760         if ((result != kIOReturnSuccess) ||
3761              (kIOPMSleepTypeInvalid == params->sleepType) ||
3762              (params->sleepType >= kIOPMSleepTypeLast) ||
3763              (kIOPMSystemSleepParametersVersion != params->version))
3764         {
3765             MSG("sleep policy handler error\n");
3766             goto done;
3767         }
3768 
3769         if ((getSleepTypeAttributes(params->sleepType) &
3770              kIOPMSleepAttributeHibernateSetup) &&
3771             ((*hibMode & kIOHibernateModeOn) == 0))
3772         {
3773             *hibMode |= (kIOHibernateModeOn | kIOHibernateModeSleep);
3774         }
3775 
3776         DLOG("sleep params v%u, type %u, flags 0x%x, wake 0x%x, timer %u, poweroff %u\n",
3777             params->version, params->sleepType, params->sleepFlags,
3778             params->ecWakeEvents, params->ecWakeTimer, params->ecPoweroffTimer);
3779         found = true;
3780         goto done;
3781     }
3782 
3783     // Policy table is meaningless without standby enabled
3784     if (!standbyEnabled)
3785         goto done;
3786 
3787     // Validate the sleep policy table
3788     policyData = OSDynamicCast(OSData, prop);
3789     if (!policyData || (policyData->getLength() <= sizeof(IOPMSystemSleepPolicyTable)))
3790         goto done;
3791 
3792     pt = (const IOPMSystemSleepPolicyTable *) policyData->getBytesNoCopy();
3793     if ((pt->signature != kIOPMSystemSleepPolicySignature) ||
3794         (pt->version != 1) || (0 == pt->entryCount))
3795         goto done;
3796 
3797     if (((policyData->getLength() - sizeof(IOPMSystemSleepPolicyTable)) !=
3798          (sizeof(IOPMSystemSleepPolicyEntry) * pt->entryCount)))
3799         goto done;
3800 
3801     for (uint32_t i = 0; i < pt->entryCount; i++)
3802     {
3803         const IOPMSystemSleepPolicyEntry * entry = &pt->entries[i];
3804         mismatch = (((uint32_t)currentFactors ^ entry->factorBits) & entry->factorMask);
3805 
3806         DLOG("mask 0x%08x, bits 0x%08x, flags 0x%08x, wake 0x%08x, mismatch 0x%08x\n",
3807             entry->factorMask, entry->factorBits,
3808             entry->sleepFlags, entry->wakeEvents, mismatch);
3809         if (mismatch)
3810             continue;
3811 
3812         DLOG("^ found match\n");
3813         found = true;
3814 
3815         params->version = kIOPMSystemSleepParametersVersion;
3816         params->reserved1 = 1;
3817         if (entry->sleepFlags & kIOPMSleepFlagHibernate)
3818             params->sleepType = kIOPMSleepTypeStandby;
3819         else
3820             params->sleepType = kIOPMSleepTypeNormalSleep;
3821 
3822         params->ecWakeEvents = entry->wakeEvents;
3823         if (entry->sleepFlags & kIOPMSleepFlagSleepTimerEnable)
3824         {
3825             if (kIOPMSleepPhase2 == sleepPhase)
3826             {
3827                 clock_sec_t now_secs = gIOLastSleepTime.tv_sec;
3828 
3829                 if (!_standbyTimerResetSeconds ||
3830                     (now_secs <= _standbyTimerResetSeconds))
3831                 {
3832                     // Reset standby timer adjustment
3833                     _standbyTimerResetSeconds = now_secs;
3834                     DLOG("standby delay %u, reset %u\n",
3835                         standbyDelay, (uint32_t) _standbyTimerResetSeconds);
3836                 }
3837                 else if (standbyDelay)
3838                 {
3839                     // Shorten the standby delay timer
3840                     clock_sec_t elapsed = now_secs - _standbyTimerResetSeconds;
3841                     if (standbyDelay > elapsed)
3842                         standbyDelay -= elapsed;
3843                     else
3844                         standbyDelay = 1; // must be > 0
3845 
3846                     DLOG("standby delay %u, elapsed %u\n",
3847                         standbyDelay, (uint32_t) elapsed);
3848                 }
3849             }
3850             params->ecWakeTimer = standbyDelay;
3851         }
3852         else if (kIOPMSleepPhase2 == sleepPhase)
3853         {
3854             // A sleep that does not enable the sleep timer will reset
3855             // the standby delay adjustment.
3856             _standbyTimerResetSeconds = 0;
3857         }
3858         break;
3859     }
3860 
3861 done:
3862     if (prop)
3863         prop->release();
3864 
3865     return found;
3866 }
3867 
3868 static IOPMSystemSleepParameters gEarlySystemSleepParams;
3869 
3870 void IOPMrootDomain::evaluateSystemSleepPolicyEarly( void )
3871 {
3872     // Evaluate early (priority interest phase), before drivers sleep.
3873 
3874     DLOG("%s\n", __FUNCTION__);
3875     removeProperty(kIOPMSystemSleepParametersKey);
3876 
3877     // Full wake resets the standby timer delay adjustment
3878     if (_highestCapability & kIOPMSystemCapabilityGraphics)
3879         _standbyTimerResetSeconds = 0;
3880 
3881     hibernateDisabled = false;
3882     hibernateMode = 0;
3883     getSleepOption(kIOHibernateModeKey, &hibernateMode);
3884 
3885     // Save for late evaluation if sleep is aborted
3886     bzero(&gEarlySystemSleepParams, sizeof(gEarlySystemSleepParams));
3887 
3888     if (evaluateSystemSleepPolicy(&gEarlySystemSleepParams, kIOPMSleepPhase1,
3889                                   &hibernateMode))
3890     {
3891         if (!hibernateRetry &&
3892             ((getSleepTypeAttributes(gEarlySystemSleepParams.sleepType) &
3893               kIOPMSleepAttributeHibernateSetup) == 0))
3894         {
3895             // skip hibernate setup
3896             hibernateDisabled = true;
3897         }
3898     }
3899 
3900     // Publish IOPMSystemSleepType
3901     uint32_t sleepType = gEarlySystemSleepParams.sleepType;
3902     if (sleepType == kIOPMSleepTypeInvalid)
3903     {
3904         // no sleep policy
3905         sleepType = kIOPMSleepTypeNormalSleep;
3906         if (hibernateMode & kIOHibernateModeOn)
3907             sleepType = (hibernateMode & kIOHibernateModeSleep) ?
3908                         kIOPMSleepTypeSafeSleep : kIOPMSleepTypeHibernate;
3909     }
3910     else if ((sleepType == kIOPMSleepTypeStandby) &&
3911              (gEarlySystemSleepParams.ecPoweroffTimer))
3912     {
3913         // report the lowest possible sleep state
3914         sleepType = kIOPMSleepTypePowerOff;
3915     }
3916 
3917     setProperty(kIOPMSystemSleepTypeKey, sleepType, 32);
3918 }
3919 
3920 void IOPMrootDomain::evaluateSystemSleepPolicyFinal( void )
3921 {
3922     IOPMSystemSleepParameters   params;
3923     OSData *                    paramsData;
3924 
3925     // Evaluate sleep policy after sleeping drivers but before platform sleep.
3926 
3927     DLOG("%s\n", __FUNCTION__);
3928 
3929     bzero(&params, sizeof(params));
3930     if (evaluateSystemSleepPolicy(&params, kIOPMSleepPhase2, &hibernateMode))
3931     {
3932         if ((hibernateDisabled || hibernateAborted) &&
3933             (getSleepTypeAttributes(params.sleepType) &
3934              kIOPMSleepAttributeHibernateSetup))
3935         {
3936             // Final evaluation picked a state requiring hibernation,
3937             // but hibernate setup was skipped. Arm a short sleep using
3938             // the early non-hibernate sleep parameters.
3939             // Set hibernateRetry flag to force hibernate setup on the
3940             // next sleep.
3941 
3942             bcopy(&gEarlySystemSleepParams, &params, sizeof(params));
3943             params.sleepType = kIOPMSleepTypeAbortedSleep;
3944             params.ecWakeTimer = 1;
3945             hibernateRetry = true;
3946             DLOG("wake in %u secs for hibernateDisabled %d, hibernateAborted %d\n",
3947                 params.ecWakeTimer, hibernateDisabled, hibernateAborted);
3948         }
3949         else
3950         {
3951             hibernateRetry = false;
3952         }
3953 
3954         paramsData = OSData::withBytes(&params, sizeof(params));
3955         if (paramsData)
3956         {
3957             setProperty(kIOPMSystemSleepParametersKey, paramsData);
3958             paramsData->release();
3959         }
3960 
3961         if (getSleepTypeAttributes(params.sleepType) &
3962             kIOPMSleepAttributeHibernateSleep)
3963         {
3964             // Disable sleep to force hibernation
3965             gIOHibernateMode &= ~kIOHibernateModeSleep;
3966         }
3967     }
3968 }
3969 
3970 bool IOPMrootDomain::getHibernateSettings(
3971     uint32_t *  hibernateModePtr,
3972     uint32_t *  hibernateFreeRatio,
3973     uint32_t *  hibernateFreeTime )
3974 {
3975     // Called by IOHibernateSystemSleep() after evaluateSystemSleepPolicyEarly()
3976     // has updated the hibernateDisabled flag.
3977 
3978     bool ok = getSleepOption(kIOHibernateModeKey, hibernateModePtr);
3979     getSleepOption(kIOHibernateFreeRatioKey, hibernateFreeRatio);
3980     getSleepOption(kIOHibernateFreeTimeKey, hibernateFreeTime);
3981     if (hibernateDisabled)
3982         *hibernateModePtr = 0;
3983     else if (gSleepPolicyHandler)
3984         *hibernateModePtr = hibernateMode;
3985     DLOG("hibernateMode 0x%x\n", *hibernateModePtr);
3986     return ok;
3987 }
3988 
3989 bool IOPMrootDomain::getSleepOption( const char * key, uint32_t * option )
3990 {
3991     OSObject *      optionsProp;
3992     OSDictionary *  optionsDict;
3993     OSObject *      obj = 0;
3994     OSNumber *      num;
3995     bool            ok = false;
3996 
3997     optionsProp = copyProperty(kRootDomainSleepOptionsKey);
3998     optionsDict = OSDynamicCast(OSDictionary, optionsProp);
3999 
4000     if (optionsDict)
4001     {
4002         obj = optionsDict->getObject(key);
4003         if (obj) obj->retain();
4004     }
4005     if (!obj)
4006     {
4007         obj = copyProperty(key);
4008     }
4009     if (obj && (num = OSDynamicCast(OSNumber, obj)))
4010     {
4011         *option = num->unsigned32BitValue();
4012         ok = true;
4013     }
4014 
4015     if (obj)
4016         obj->release();
4017     if (optionsProp)
4018         optionsProp->release();
4019 
4020     return true;
4021 }
4022 #endif /* HIBERNATION */
4023 
4024 IOReturn IOPMrootDomain::getSystemSleepType( uint32_t * sleepType )
4025 {
4026 #if HIBERNATION
4027     IOPMSystemSleepParameters   params;
4028     uint32_t                    hibMode = 0;
4029     bool                        ok;
4030 
4031     if (gIOPMWorkLoop->inGate() == false)
4032     {
4033         IOReturn ret = gIOPMWorkLoop->runAction(
4034                         OSMemberFunctionCast(IOWorkLoop::Action, this,
4035                             &IOPMrootDomain::getSystemSleepType),
4036                         (OSObject *) this,
4037                         (void *) sleepType);
4038         return ret;
4039     }
4040 
4041     getSleepOption(kIOHibernateModeKey, &hibMode);
4042     bzero(&params, sizeof(params));
4043 
4044     ok = evaluateSystemSleepPolicy(&params, kIOPMSleepPhase0, &hibMode);
4045     if (ok)
4046     {
4047         *sleepType = params.sleepType;
4048         return kIOReturnSuccess;
4049     }
4050 #endif
4051 
4052     return kIOReturnUnsupported;
4053 }
4054 
4055 // MARK: -
4056 // MARK: Shutdown and Restart
4057 
4058 //******************************************************************************
4059 // handlePlatformHaltRestart
4060 //
4061 //******************************************************************************
4062 
4063 struct HaltRestartApplierContext {
4064     IOPMrootDomain *    RootDomain;
4065     unsigned long       PowerState;
4066     IOPMPowerFlags      PowerFlags;
4067     UInt32              MessageType;
4068     UInt32              Counter;
4069 };
4070 
4071 static void
4072 platformHaltRestartApplier( OSObject * object, void * context )
4073 {
4074     IOPowerStateChangeNotification  notify;
4075     HaltRestartApplierContext *     ctx;
4076     AbsoluteTime                    startTime;
4077     UInt32                          deltaTime;
4078 
4079     ctx = (HaltRestartApplierContext *) context;
4080 
4081     memset(&notify, 0, sizeof(notify));
4082     notify.powerRef    = (void *)(uintptr_t)ctx->Counter;
4083     notify.returnValue = 0;
4084     notify.stateNumber = ctx->PowerState;
4085     notify.stateFlags  = ctx->PowerFlags;
4086 
4087     clock_get_uptime(&startTime);
4088     ctx->RootDomain->messageClient( ctx->MessageType, object, (void *)&notify );
4089     deltaTime = computeDeltaTimeMS(&startTime);
4090 
4091     if ((deltaTime > kPMHaltTimeoutMS) ||
4092         (gIOKitDebug & kIOLogPMRootDomain))
4093     {
4094         _IOServiceInterestNotifier * notifier;
4095         notifier = OSDynamicCast(_IOServiceInterestNotifier, object);
4096 
4097         // IOService children of IOPMrootDomain are not instrumented.
4098         // Only IORootParent currently falls under that group.
4099 
4100         if (notifier)
4101         {
4102             LOG("%s handler %p took %u ms\n",
4103                 (ctx->MessageType == kIOMessageSystemWillPowerOff) ? "PowerOff" :
4104                      (ctx->MessageType == kIOMessageSystemPagingOff) ? "PagingOff" : "Restart",
4105                 OBFUSCATE(notifier->handler), (uint32_t) deltaTime );
4106         }
4107     }
4108 
4109     ctx->Counter++;
4110 }
4111 
4112 void IOPMrootDomain::handlePlatformHaltRestart( UInt32 pe_type )
4113 {
4114     HaltRestartApplierContext   ctx;
4115     AbsoluteTime                startTime;
4116     UInt32                      deltaTime;
4117 
4118     memset(&ctx, 0, sizeof(ctx));
4119     ctx.RootDomain = this;
4120 
4121     clock_get_uptime(&startTime);
4122     switch (pe_type)
4123     {
4124         case kPEHaltCPU:
4125         case kPEUPSDelayHaltCPU:
4126             ctx.PowerState  = OFF_STATE;
4127             ctx.MessageType = kIOMessageSystemWillPowerOff;
4128             break;
4129 
4130         case kPERestartCPU:
4131             ctx.PowerState  = RESTART_STATE;
4132             ctx.MessageType = kIOMessageSystemWillRestart;
4133             break;
4134 
4135         case kPEPagingOff:
4136             ctx.PowerState  = ON_STATE;
4137             ctx.MessageType = kIOMessageSystemPagingOff;
4138             IOService::updateConsoleUsers(NULL, kIOMessageSystemPagingOff);
4139 #if HIBERNATION
4140             IOHibernateSystemRestart();
4141 #endif
4142             break;
4143 
4144         default:
4145             return;
4146     }
4147 
4148     // Notify legacy clients
4149     applyToInterested(gIOPriorityPowerStateInterest, platformHaltRestartApplier, &ctx);
4150 
4151     // For normal shutdown, turn off File Server Mode.
4152     if (kPEHaltCPU == pe_type)
4153     {
4154         const OSSymbol * setting = OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey);
4155         OSNumber * num = OSNumber::withNumber((unsigned long long) 0, 32);
4156         if (setting && num)
4157         {
4158             setPMSetting(setting, num);
4159             setting->release();
4160             num->release();
4161         }
4162     }
4163 
4164     if (kPEPagingOff != pe_type)
4165     {
4166         // Notify in power tree order
4167         notifySystemShutdown(this, ctx.MessageType);
4168     }
4169 
4170     IOCPURunPlatformHaltRestartActions(pe_type);
4171 
4172     deltaTime = computeDeltaTimeMS(&startTime);
4173     LOG("%s all drivers took %u ms\n",
4174         (ctx.MessageType == kIOMessageSystemWillPowerOff) ? "PowerOff" :
4175             (ctx.MessageType == kIOMessageSystemPagingOff) ? "PagingOff" : "Restart",
4176         (uint32_t) deltaTime );
4177 }
4178 
4179 //******************************************************************************
4180 // shutdownSystem
4181 //
4182 //******************************************************************************
4183 
4184 IOReturn IOPMrootDomain::shutdownSystem( void )
4185 {
4186     return kIOReturnUnsupported;
4187 }
4188 
4189 //******************************************************************************
4190 // restartSystem
4191 //
4192 //******************************************************************************
4193 
4194 IOReturn IOPMrootDomain::restartSystem( void )
4195 {
4196     return kIOReturnUnsupported;
4197 }
4198 
4199 // MARK: -
4200 // MARK: System Capability
4201 
4202 //******************************************************************************
4203 // tagPowerPlaneService
4204 //
4205 // Running on PM work loop thread.
4206 //******************************************************************************
4207 
4208 void IOPMrootDomain::tagPowerPlaneService(
4209         IOService *     service,
4210         IOPMActions *   actions )
4211 {
4212     uint32_t    flags = 0;
4213     bool        isDisplayWrangler;
4214 
4215     memset(actions, 0, sizeof(*actions));
4216     actions->target = this;
4217 
4218     if (service == this)
4219     {
4220         actions->actionPowerChangeStart =
4221             OSMemberFunctionCast(
4222                 IOPMActionPowerChangeStart, this,
4223                 &IOPMrootDomain::handleOurPowerChangeStart);
4224 
4225         actions->actionPowerChangeDone =
4226             OSMemberFunctionCast(
4227                 IOPMActionPowerChangeDone, this,
4228                 &IOPMrootDomain::handleOurPowerChangeDone);
4229 
4230         actions->actionPowerChangeOverride =
4231             OSMemberFunctionCast(
4232                 IOPMActionPowerChangeOverride, this,
4233                 &IOPMrootDomain::overrideOurPowerChange);
4234         return;
4235     }
4236 
4237 #if !NO_KERNEL_HID
4238     isDisplayWrangler = (0 != service->metaCast("IODisplayWrangler"));
4239     if (isDisplayWrangler)
4240     {
4241         wrangler = service;
4242     }
4243 #else
4244     isDisplayWrangler = false;
4245 #endif
4246 
4247 #if defined(__i386__) || defined(__x86_64__)
4248     if (isDisplayWrangler)
4249         flags |= kPMActionsFlagIsDisplayWrangler;
4250     if (service->getProperty("IOPMStrictTreeOrder"))
4251         flags |= kPMActionsFlagIsGraphicsDevice;
4252     if (service->getProperty("IOPMUnattendedWakePowerState"))
4253         flags |= kPMActionsFlagIsAudioDevice;
4254 #endif
4255 
4256     // Find the power connection object that is a child of the PCI host
4257     // bridge, and has a graphics/audio device attached below. Mark the
4258     // power branch for delayed child notifications.
4259 
4260     if (flags)
4261     {
4262         IORegistryEntry * child  = service;
4263         IORegistryEntry * parent = child->getParentEntry(gIOPowerPlane);
4264 
4265         while (child != this)
4266         {
4267             if ((parent == pciHostBridgeDriver) ||
4268                 (parent == this))
4269             {
4270                 if (OSDynamicCast(IOPowerConnection, child))
4271                 {
4272                     IOPowerConnection * conn = (IOPowerConnection *) child;
4273                     conn->delayChildNotification = true;
4274                 }
4275                 break;
4276             }
4277             child = parent;
4278             parent = child->getParentEntry(gIOPowerPlane);
4279         }
4280     }
4281 
4282     if (flags)
4283     {
4284         DLOG("%s tag flags %x\n", service->getName(), flags);
4285         actions->parameter |= flags;
4286         actions->actionPowerChangeOverride =
4287             OSMemberFunctionCast(
4288                 IOPMActionPowerChangeOverride, this,
4289                 &IOPMrootDomain::overridePowerChangeForUIService);
4290 
4291         if (flags & kPMActionsFlagIsDisplayWrangler)
4292         {
4293             actions->actionActivityTickle =
4294                 OSMemberFunctionCast(
4295                     IOPMActionActivityTickle, this,
4296                     &IOPMrootDomain::handleActivityTickleForDisplayWrangler);
4297 
4298             actions->actionUpdatePowerClient =
4299                 OSMemberFunctionCast(
4300                     IOPMActionUpdatePowerClient, this,
4301                     &IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler);
4302         }
4303         return;
4304     }
4305 
4306     // Locate the first PCI host bridge for PMTrace.
4307     if (!pciHostBridgeDevice && service->metaCast("IOPCIBridge"))
4308     {
4309         IOService * provider = service->getProvider();
4310         if (OSDynamicCast(IOPlatformDevice, provider) &&
4311             provider->inPlane(gIODTPlane))
4312         {
4313             pciHostBridgeDevice = provider;
4314             pciHostBridgeDriver = service;
4315             DLOG("PMTrace found PCI host bridge %s->%s\n",
4316                 provider->getName(), service->getName());
4317         }
4318     }
4319 
4320     // Tag top-level PCI devices. The order of PMinit() call does not
4321     // change across boots and is used as the PCI bit number.
4322     if (pciHostBridgeDevice && service->metaCast("IOPCIDevice"))
4323     {
4324         // Would prefer to check built-in property, but tagPowerPlaneService()
4325         // is called before pciDevice->registerService().
4326         IORegistryEntry * parent = service->getParentEntry(gIODTPlane);
4327         if ((parent == pciHostBridgeDevice) && service->getProperty("acpi-device"))
4328         {
4329             int bit = pmTracer->recordTopLevelPCIDevice( service );
4330             if (bit >= 0)
4331             {
4332                 // Save the assigned bit for fast lookup.
4333                 actions->parameter |= (bit & kPMActionsPCIBitNumberMask);
4334 
4335                 actions->actionPowerChangeStart =
4336                     OSMemberFunctionCast(
4337                         IOPMActionPowerChangeStart, this,
4338                         &IOPMrootDomain::handlePowerChangeStartForPCIDevice);
4339 
4340                 actions->actionPowerChangeDone =
4341                     OSMemberFunctionCast(
4342                         IOPMActionPowerChangeDone, this,
4343                         &IOPMrootDomain::handlePowerChangeDoneForPCIDevice);
4344             }
4345         }
4346     }
4347 }
4348 
4349 //******************************************************************************
4350 // PM actions for root domain
4351 //******************************************************************************
4352 
4353 void IOPMrootDomain::overrideOurPowerChange(
4354     IOService *             service,
4355     IOPMActions *           actions,
4356     IOPMPowerStateIndex *   inOutPowerState,
4357     IOPMPowerChangeFlags *  inOutChangeFlags,
4358     IOPMRequestTag          requestTag )
4359 {
4360     uint32_t powerState  = (uint32_t) *inOutPowerState;
4361     uint32_t changeFlags = *inOutChangeFlags;
4362     uint32_t currentPowerState = (uint32_t) getPowerState();
4363 
4364     if (changeFlags & kIOPMParentInitiated)
4365     {
4366         // Root parent is permanently pegged at max power,
4367         // a parent initiated power change is unexpected.
4368         *inOutChangeFlags |= kIOPMNotDone;
4369         return;
4370     }
4371 
4372     if (powerState < currentPowerState)
4373     {
4374         if (CAP_CURRENT(kIOPMSystemCapabilityGraphics))
4375         {
4376             // Root domain is dropping power state ON->SLEEP.
4377             // If system is in full wake, first enter dark wake by
4378             // converting the power drop to a capability change.
4379             // Once in dark wake, transition to sleep state ASAP.
4380 
4381             darkWakeToSleepASAP = true;
4382 
4383             // Drop graphics and audio capability
4384             _desiredCapability &= ~(
4385                 kIOPMSystemCapabilityGraphics |
4386                 kIOPMSystemCapabilityAudio    );
4387 
4388             // Convert to capability change (ON->ON)
4389             *inOutPowerState = ON_STATE;
4390             *inOutChangeFlags |= kIOPMSynchronize;
4391 
4392             // Revert device desire from SLEEP to ON
4393             changePowerStateToPriv(ON_STATE);
4394         }
4395         else
4396         {
4397             // System is in dark wake, ok to drop power state.
4398             // Broadcast root powering down to entire tree.
4399             *inOutChangeFlags |= kIOPMRootChangeDown;
4400         }
4401     }
4402     else if (powerState > currentPowerState)
4403     {
4404         if ((_currentCapability & kIOPMSystemCapabilityCPU) == 0)
4405         {
4406             // Broadcast power up when waking from sleep, but not for the
4407             // initial power change at boot by checking for cpu capability.
4408             *inOutChangeFlags |= kIOPMRootChangeUp;
4409         }
4410     }
4411 }
4412 
4413 void IOPMrootDomain::handleOurPowerChangeStart(
4414     IOService *             service,
4415     IOPMActions *           actions,
4416     IOPMPowerStateIndex     powerState,
4417     IOPMPowerChangeFlags *  inOutChangeFlags,
4418     IOPMRequestTag          requestTag )
4419 {
4420     uint32_t changeFlags        = *inOutChangeFlags;
4421     uint32_t currentPowerState  = (uint32_t) getPowerState();
4422     uint32_t sleepReason        = requestTag ? requestTag : kIOPMSleepReasonIdle;
4423     bool     publishSleepReason = false;
4424 
4425     _systemTransitionType    = kSystemTransitionNone;
4426     _systemMessageClientMask = 0;
4427     capabilityLoss           = false;
4428 
4429     if (lowBatteryCondition)
4430     {
4431         // Low battery notification may arrive after the initial sleep request
4432         // has been queued. Override the sleep reason so powerd and others can
4433         // treat this as an emergency sleep.
4434         sleepReason = kIOPMSleepReasonLowPower;
4435     }
4436 
4437     // 1. Explicit capability change.
4438 
4439     if (changeFlags & kIOPMSynchronize)
4440     {
4441         if (powerState == ON_STATE)
4442         {
4443             if (changeFlags & kIOPMSyncNoChildNotify)
4444                 _systemTransitionType = kSystemTransitionNewCapClient;
4445             else
4446                 _systemTransitionType = kSystemTransitionCapability;
4447         }
4448     }
4449 
4450     // 2. Going to sleep (cancellation still possible).
4451 
4452     else if (powerState < currentPowerState)
4453         _systemTransitionType = kSystemTransitionSleep;
4454 
4455     // 3. Woke from (idle or demand) sleep.
4456 
4457     else if (!systemBooting &&
4458              (changeFlags & kIOPMSelfInitiated) &&
4459              (powerState > currentPowerState))
4460     {
4461         _systemTransitionType = kSystemTransitionWake;
4462         _desiredCapability = kIOPMSystemCapabilityCPU |
4463                              kIOPMSystemCapabilityNetwork;
4464 
4465         // Early exit from dark wake to full (e.g. LID open)
4466         if (kFullWakeReasonNone != fullWakeReason)
4467         {
4468             _desiredCapability |= (
4469                 kIOPMSystemCapabilityGraphics |
4470                 kIOPMSystemCapabilityAudio );
4471         }
4472 #if HIBERNATION
4473     IOHibernateSetWakeCapabilities(_desiredCapability);
4474 #endif
4475     }
4476 
4477     // Update pending wake capability at the beginning of every
4478     // state transition (including synchronize). This will become
4479     // the current capability at the end of the transition.
4480 
4481     if (kSystemTransitionSleep == _systemTransitionType)
4482     {
4483         _pendingCapability = 0;
4484         capabilityLoss = true;
4485 
4486         // Clear previous stats
4487         IOLockLock(pmStatsLock);
4488         if (pmStatsAppResponses)
4489         {
4490             pmStatsAppResponses->release();
4491             pmStatsAppResponses = OSArray::withCapacity(5);
4492         }
4493         IOLockUnlock(pmStatsLock);
4494 
4495     }
4496     else if (kSystemTransitionNewCapClient != _systemTransitionType)
4497     {
4498         _pendingCapability = _desiredCapability |
4499                              kIOPMSystemCapabilityCPU |
4500                              kIOPMSystemCapabilityNetwork;
4501 
4502         if (_pendingCapability & kIOPMSystemCapabilityGraphics)
4503             _pendingCapability |= kIOPMSystemCapabilityAudio;
4504 
4505         if ((kSystemTransitionCapability == _systemTransitionType) &&
4506             (_pendingCapability == _currentCapability))
4507         {
4508             // Cancel the PM state change.
4509             _systemTransitionType = kSystemTransitionNone;
4510             *inOutChangeFlags |= kIOPMNotDone;
4511         }
4512         if (__builtin_popcount(_pendingCapability) <
4513             __builtin_popcount(_currentCapability))
4514             capabilityLoss = true;
4515     }
4516 
4517     // 1. Capability change.
4518 
4519     if (kSystemTransitionCapability == _systemTransitionType)
4520     {
4521         // Dark to Full transition.
4522         if (CAP_GAIN(kIOPMSystemCapabilityGraphics))
4523         {
4524             tracePoint( kIOPMTracePointDarkWakeExit );
4525 
4526             willEnterFullWake();
4527         }
4528 
4529         // Full to Dark transition.
4530         if (CAP_LOSS(kIOPMSystemCapabilityGraphics))
4531         {
4532             tracePoint( kIOPMTracePointDarkWakeEntry );
4533             *inOutChangeFlags |= kIOPMSyncTellPowerDown;
4534             _systemMessageClientMask = kSystemMessageClientPowerd |
4535                                        kSystemMessageClientLegacyApp;
4536 
4537 
4538             // rdar://15971327
4539             // Prevent user active transitions before notifying clients
4540             // that system will sleep.
4541             preventTransitionToUserActive(true);
4542 
4543             IOService::setAdvisoryTickleEnable( false );
4544 
4545             // Publish the sleep reason for full to dark wake
4546             publishSleepReason = true;
4547             lastSleepReason = fullToDarkReason = sleepReason;
4548 
4549             // Publish a UUID for the Sleep --> Wake cycle
4550             handlePublishSleepWakeUUID(true);
4551         }
4552     }
4553 
4554     // 2. System sleep.
4555 
4556     else if (kSystemTransitionSleep == _systemTransitionType)
4557     {
4558         // Beginning of a system sleep transition.
4559         // Cancellation is still possible.
4560         tracePoint( kIOPMTracePointSleepStarted, sleepReason );
4561 
4562         _systemMessageClientMask = kSystemMessageClientAll;
4563         if ((_currentCapability & kIOPMSystemCapabilityGraphics) == 0)
4564             _systemMessageClientMask &= ~kSystemMessageClientLegacyApp;
4565         if ((_highestCapability & kIOPMSystemCapabilityGraphics) == 0)
4566             _systemMessageClientMask &= ~kSystemMessageClientKernel;
4567 
4568         // Record the reason for dark wake back to sleep
4569         // System may not have ever achieved full wake
4570 
4571         publishSleepReason = true;
4572         lastSleepReason = sleepReason;
4573     }
4574 
4575     // 3. System wake.
4576 
4577     else if (kSystemTransitionWake == _systemTransitionType)
4578     {
4579         tracePoint( kIOPMTracePointWakeWillPowerOnClients );
4580         // Clear stats about sleep
4581 
4582         if (_pendingCapability & kIOPMSystemCapabilityGraphics)
4583         {
4584             willEnterFullWake();
4585         }
4586         else
4587         {
4588             // Message powerd only
4589             _systemMessageClientMask = kSystemMessageClientPowerd;
4590             tellClients(kIOMessageSystemWillPowerOn);
4591         }
4592     }
4593 
4594     // The only location where the sleep reason is published. At this point
4595     // sleep can still be cancelled, but sleep reason should be published
4596     // early for logging purposes.
4597 
4598     if (publishSleepReason)
4599     {
4600         static const char * IOPMSleepReasons[] =
4601         {
4602             kIOPMClamshellSleepKey,
4603             kIOPMPowerButtonSleepKey,
4604             kIOPMSoftwareSleepKey,
4605             kIOPMOSSwitchHibernationKey,
4606             kIOPMIdleSleepKey,
4607             kIOPMLowPowerSleepKey,
4608             kIOPMThermalEmergencySleepKey,
4609             kIOPMMaintenanceSleepKey,
4610             kIOPMSleepServiceExitKey,
4611             kIOPMDarkWakeThermalEmergencyKey
4612         };
4613 
4614         // Record sleep cause in IORegistry
4615         uint32_t reasonIndex = sleepReason - kIOPMSleepReasonClamshell;
4616         if (reasonIndex < sizeof(IOPMSleepReasons)/sizeof(IOPMSleepReasons[0])) {
4617             DLOG("sleep reason %s\n", IOPMSleepReasons[reasonIndex]);
4618             setProperty(kRootDomainSleepReasonKey, IOPMSleepReasons[reasonIndex]);
4619         }
4620     }
4621 
4622     if ((kSystemTransitionNone != _systemTransitionType) &&
4623         (kSystemTransitionNewCapClient != _systemTransitionType))
4624     {
4625         _systemStateGeneration++;
4626         systemDarkWake = false;
4627 
4628         DLOG("=== START (%u->%u, 0x%x) type %u, gen %u, msg %x, "
4629              "dcp %x:%x:%x\n",
4630             currentPowerState, (uint32_t) powerState, *inOutChangeFlags,
4631             _systemTransitionType, _systemStateGeneration,
4632             _systemMessageClientMask,
4633             _desiredCapability, _currentCapability, _pendingCapability);
4634     }
4635 }
4636 
4637 void IOPMrootDomain::handleOurPowerChangeDone(
4638     IOService *             service,
4639     IOPMActions *           actions,
4640     IOPMPowerStateIndex     powerState,
4641     IOPMPowerChangeFlags    changeFlags,
4642     IOPMRequestTag          requestTag __unused )
4643 {
4644     if (kSystemTransitionNewCapClient == _systemTransitionType)
4645     {
4646         _systemTransitionType = kSystemTransitionNone;
4647         return;
4648     }
4649 
4650     if (_systemTransitionType != kSystemTransitionNone)
4651     {
4652         uint32_t currentPowerState = (uint32_t) getPowerState();
4653 
4654         if (changeFlags & kIOPMNotDone)
4655         {
4656             // Power down was cancelled or vetoed.
4657             _pendingCapability = _currentCapability;
4658             lastSleepReason = 0;
4659 
4660             if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics) &&
4661                  CAP_CURRENT(kIOPMSystemCapabilityCPU))
4662             {
4663                 pmPowerStateQueue->submitPowerEvent(
4664                     kPowerEventPolicyStimulus,
4665                     (void *) kStimulusDarkWakeReentry,
4666                     _systemStateGeneration );
4667             }
4668 
4669             // Revert device desire to max.
4670             changePowerStateToPriv(ON_STATE);
4671         }
4672         else
4673         {
4674             // Send message on dark wake to full wake promotion.
4675             // tellChangeUp() handles the normal SLEEP->ON case.
4676 
4677             if (kSystemTransitionCapability == _systemTransitionType)
4678             {
4679                 if (CAP_GAIN(kIOPMSystemCapabilityGraphics))
4680                 {
4681                     lastSleepReason = 0; // stop logging wrangler tickles
4682                     tellClients(kIOMessageSystemHasPoweredOn);
4683                 }
4684                 if (CAP_LOSS(kIOPMSystemCapabilityGraphics))
4685                 {
4686                     // Going dark, reset full wake state
4687                     // userIsActive will be cleared by wrangler powering down
4688                     wranglerTickled = false;
4689                     fullWakeReason = kFullWakeReasonNone;
4690                 }
4691             }
4692 
4693             // Reset state after exiting from dark wake.
4694 
4695             if (CAP_GAIN(kIOPMSystemCapabilityGraphics) ||
4696                 CAP_LOSS(kIOPMSystemCapabilityCPU))
4697             {
4698                 darkWakeMaintenance = false;
4699                 darkWakeToSleepASAP = false;
4700                 pciCantSleepValid   = false;
4701                 darkWakeSleepService = false;
4702 
4703                 if (CAP_LOSS(kIOPMSystemCapabilityCPU))
4704                 {
4705                     // Remove the influence of display power assertion
4706                     // before next system wake.
4707                     if (wrangler) wrangler->changePowerStateForRootDomain(
4708                                                 kWranglerPowerStateMin );
4709                     removeProperty(gIOPMUserTriggeredFullWakeKey);
4710                 }
4711             }
4712 
4713             // Entered dark mode.
4714 
4715             if (((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
4716                  (_pendingCapability & kIOPMSystemCapabilityCPU))
4717             {
4718                 // Queue an evaluation of whether to remain in dark wake,
4719                 // and for how long. This serves the purpose of draining
4720                 // any assertions from the queue.
4721 
4722                 pmPowerStateQueue->submitPowerEvent(
4723                     kPowerEventPolicyStimulus,
4724                     (void *) kStimulusDarkWakeEntry,
4725                     _systemStateGeneration );
4726             }
4727         }
4728 
4729         DLOG("=== FINISH (%u->%u, 0x%x) type %u, gen %u, msg %x, "
4730              "dcp %x:%x:%x, dbgtimer %u\n",
4731             currentPowerState, (uint32_t) powerState, changeFlags,
4732             _systemTransitionType, _systemStateGeneration,
4733             _systemMessageClientMask,
4734             _desiredCapability, _currentCapability, _pendingCapability,
4735             _lastDebugWakeSeconds);
4736 
4737         if (_pendingCapability & kIOPMSystemCapabilityGraphics)
4738         {
4739             displayWakeCnt++;
4740 #if DARK_TO_FULL_EVALUATE_CLAMSHELL
4741             if (clamshellExists && fullWakeThreadCall &&
4742                 CAP_HIGHEST(kIOPMSystemCapabilityGraphics))
4743             {
4744                 // Not the initial graphics full power, graphics won't
4745                 // send a power notification to trigger a lid state
4746                 // evaluation.
4747 
4748                 AbsoluteTime deadline;
4749                 clock_interval_to_deadline(45, kSecondScale, &deadline);
4750                 thread_call_enter_delayed(fullWakeThreadCall, deadline);
4751             }
4752 #endif
4753         }
4754         else if (CAP_GAIN(kIOPMSystemCapabilityCPU))
4755             darkWakeCnt++;
4756 
4757         // Update current system capability.
4758         if (_currentCapability != _pendingCapability)
4759             _currentCapability = _pendingCapability;
4760 
4761         // Update highest system capability.
4762 
4763         _highestCapability |= _currentCapability;
4764 
4765         if (darkWakePostTickle &&
4766             (kSystemTransitionWake == _systemTransitionType) &&
4767             (gDarkWakeFlags & kDarkWakeFlagHIDTickleMask) ==
4768              kDarkWakeFlagHIDTickleLate)
4769         {
4770             darkWakePostTickle = false;
4771             reportUserInput();
4772         }
4773 
4774         // Reset tracepoint at completion of capability change,
4775         // completion of wake transition, and aborted sleep transition.
4776 
4777         if ((_systemTransitionType == kSystemTransitionCapability) ||
4778             (_systemTransitionType == kSystemTransitionWake) ||
4779             ((_systemTransitionType == kSystemTransitionSleep) &&
4780              (changeFlags & kIOPMNotDone)))
4781         {
4782             setProperty(kIOPMSystemCapabilitiesKey, _currentCapability, 64);
4783             tracePoint( kIOPMTracePointSystemUp, 0 );
4784         }
4785 
4786         _systemTransitionType = kSystemTransitionNone;
4787         _systemMessageClientMask = 0;
4788 
4789         logGraphicsClamp = false;
4790     }
4791 }
4792 
4793 //******************************************************************************
4794 // PM actions for graphics and audio.
4795 //******************************************************************************
4796 
4797 void IOPMrootDomain::overridePowerChangeForUIService(
4798     IOService *             service,
4799     IOPMActions *           actions,
4800     IOPMPowerStateIndex *   inOutPowerState,
4801     IOPMPowerChangeFlags *  inOutChangeFlags )
4802 {
4803     uint32_t powerState  = (uint32_t) *inOutPowerState;
4804     uint32_t changeFlags = (uint32_t) *inOutChangeFlags;
4805 
4806     if (kSystemTransitionNone == _systemTransitionType)
4807     {
4808         // Not in midst of a system transition.
4809         // Do not modify power limit enable state.
4810     }
4811     else if ((actions->parameter & kPMActionsFlagLimitPower) == 0)
4812     {
4813         // Activate power limiter.
4814 
4815         if ((actions->parameter & kPMActionsFlagIsDisplayWrangler) &&
4816             ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0) &&
4817             (changeFlags & kIOPMSynchronize))
4818         {
4819             actions->parameter |= kPMActionsFlagLimitPower;
4820         }
4821         else if ((actions->parameter & kPMActionsFlagIsAudioDevice) &&
4822                  ((gDarkWakeFlags & kDarkWakeFlagAudioNotSuppressed) == 0) &&
4823                  ((_pendingCapability & kIOPMSystemCapabilityAudio) == 0) &&
4824                  (changeFlags & kIOPMSynchronize))
4825         {
4826             actions->parameter |= kPMActionsFlagLimitPower;
4827         }
4828         else if ((actions->parameter & kPMActionsFlagIsGraphicsDevice) &&
4829                  (_systemTransitionType == kSystemTransitionSleep))
4830         {
4831             // For graphics devices, arm the limiter when entering
4832             // system sleep. Not when dropping to dark wake.
4833             actions->parameter |= kPMActionsFlagLimitPower;
4834         }
4835 
4836         if (actions->parameter & kPMActionsFlagLimitPower)
4837         {
4838             DLOG("+ plimit %s %p\n",
4839                 service->getName(), OBFUSCATE(service));
4840         }
4841     }
4842     else
4843     {
4844         // Remove power limit.
4845 
4846         if ((actions->parameter & (
4847             kPMActionsFlagIsDisplayWrangler |
4848             kPMActionsFlagIsGraphicsDevice )) &&
4849             (_pendingCapability & kIOPMSystemCapabilityGraphics))
4850         {
4851             actions->parameter &= ~kPMActionsFlagLimitPower;
4852         }
4853         else if ((actions->parameter & kPMActionsFlagIsAudioDevice) &&
4854                  (_pendingCapability & kIOPMSystemCapabilityAudio))
4855         {
4856             actions->parameter &= ~kPMActionsFlagLimitPower;
4857         }
4858 
4859         if ((actions->parameter & kPMActionsFlagLimitPower) == 0)
4860         {
4861             DLOG("- plimit %s %p\n",
4862                 service->getName(), OBFUSCATE(service));
4863         }
4864     }
4865 
4866     if (actions->parameter & kPMActionsFlagLimitPower)
4867     {
4868         uint32_t maxPowerState = (uint32_t)(-1);
4869 
4870         if (changeFlags & (kIOPMDomainDidChange | kIOPMDomainWillChange))
4871         {
4872             // Enforce limit for system power/cap transitions.
4873 
4874             maxPowerState = 0;
4875             if ((service->getPowerState() > maxPowerState) &&
4876                 (actions->parameter & kPMActionsFlagIsDisplayWrangler))
4877             {
4878                 maxPowerState++;
4879 
4880                 // Remove lingering effects of any tickle before entering
4881                 // dark wake. It will take a new tickle to return to full
4882                 // wake, so the existing tickle state is useless.
4883 
4884                 if (changeFlags & kIOPMDomainDidChange)
4885                     *inOutChangeFlags |= kIOPMExpireIdleTimer;
4886             }
4887             else if (actions->parameter & kPMActionsFlagIsGraphicsDevice)
4888             {
4889                 maxPowerState++;
4890             }
4891         }
4892         else
4893         {
4894             // Deny all self-initiated changes when power is limited.
4895             // Wrangler tickle should never defeat the limiter.
4896 
4897             maxPowerState = service->getPowerState();
4898         }
4899 
4900         if (powerState > maxPowerState)
4901         {
4902             DLOG("> plimit %s %p (%u->%u, 0x%x)\n",
4903                 service->getName(), OBFUSCATE(service), powerState, maxPowerState,
4904                 changeFlags);
4905             *inOutPowerState = maxPowerState;
4906 
4907             if (darkWakePostTickle &&
4908                 (actions->parameter & kPMActionsFlagIsDisplayWrangler) &&
4909                 (changeFlags & kIOPMDomainWillChange) &&
4910                 ((gDarkWakeFlags & kDarkWakeFlagHIDTickleMask) ==
4911                  kDarkWakeFlagHIDTickleEarly))
4912             {
4913                 darkWakePostTickle = false;
4914                 reportUserInput();
4915             }
4916         }
4917 
4918         if (!graphicsSuppressed && (changeFlags & kIOPMDomainDidChange))
4919         {
4920             if (logGraphicsClamp)
4921             {
4922                 AbsoluteTime    now;
4923                 uint64_t        nsec;
4924 
4925                 clock_get_uptime(&now);
4926                 SUB_ABSOLUTETIME(&now, &systemWakeTime);
4927                 absolutetime_to_nanoseconds(now, &nsec);
4928                 if (kIOLogPMRootDomain & gIOKitDebug)
4929                     MSG("Graphics suppressed %u ms\n",
4930                         ((int)((nsec) / 1000000ULL)));
4931             }
4932             graphicsSuppressed = true;
4933         }
4934     }
4935 }
4936 
4937 void IOPMrootDomain::handleActivityTickleForDisplayWrangler(
4938     IOService *     service,
4939     IOPMActions *   actions )
4940 {
4941 #if !NO_KERNEL_HID
4942     // Warning: Not running in PM work loop context - don't modify state !!!
4943     // Trap tickle directed to IODisplayWrangler while running with graphics
4944     // capability suppressed.
4945 
4946     assert(service == wrangler);
4947 
4948     clock_get_uptime(&userActivityTime);
4949     bool aborting = ((lastSleepReason == kIOPMSleepReasonIdle)
4950                   || (lastSleepReason == kIOPMSleepReasonMaintenance));
4951     if (aborting) {
4952         userActivityCount++;
4953         DLOG("display wrangler tickled1 %d lastSleepReason %d\n",
4954             userActivityCount, lastSleepReason);
4955     }
4956 
4957     if (!wranglerTickled &&
4958         ((_pendingCapability & kIOPMSystemCapabilityGraphics) == 0))
4959     {
4960         DLOG("display wrangler tickled\n");
4961         if (kIOLogPMRootDomain & gIOKitDebug)
4962             OSReportWithBacktrace("Dark wake display tickle");
4963         if (pmPowerStateQueue)
4964         {
4965             pmPowerStateQueue->submitPowerEvent(
4966                 kPowerEventPolicyStimulus,
4967                 (void *) kStimulusDarkWakeActivityTickle,
4968                 true /* set wake type */ );
4969         }
4970     }
4971 #endif
4972 }
4973 
4974 void IOPMrootDomain::handleUpdatePowerClientForDisplayWrangler(
4975     IOService *             service,
4976     IOPMActions *           actions,
4977     const OSSymbol *        powerClient,
4978     IOPMPowerStateIndex     oldPowerState,
4979     IOPMPowerStateIndex     newPowerState )
4980 {
4981 #if !NO_KERNEL_HID
4982     assert(service == wrangler);
4983 
4984     // This function implements half of the user active detection
4985     // by monitoring changes to the display wrangler's device desire.
4986     //
4987     // User becomes active when either:
4988     // 1. Wrangler's DeviceDesire increases to max, but wrangler is already
4989     //    in max power state. This desire change in absence of a power state
4990     //    change is detected within. This handles the case when user becomes
4991     //    active while the display is already lit by setDisplayPowerOn().
4992     //
4993     // 2. Power state change to max, and DeviceDesire is also at max.
4994     //    Handled by displayWranglerNotification().
4995     //
4996     // User becomes inactive when DeviceDesire drops to sleep state or below.
4997 
4998     DLOG("wrangler %s (ps %u, %u->%u)\n",
4999         powerClient->getCStringNoCopy(),
5000         (uint32_t) service->getPowerState(),
5001         (uint32_t) oldPowerState, (uint32_t) newPowerState);
5002 
5003     if (powerClient == gIOPMPowerClientDevice)
5004     {
5005         if ((newPowerState > oldPowerState) &&
5006             (newPowerState == kWranglerPowerStateMax) &&
5007             (service->getPowerState() == kWranglerPowerStateMax))
5008         {
5009             evaluatePolicy( kStimulusEnterUserActiveState );
5010         }
5011         else
5012         if ((newPowerState < oldPowerState) &&
5013             (newPowerState <= kWranglerPowerStateSleep))
5014         {
5015             evaluatePolicy( kStimulusLeaveUserActiveState );
5016         }
5017     }
5018 #endif
5019 }
5020 
5021 //******************************************************************************
5022 // User active state management
5023 //******************************************************************************
5024 
5025 void IOPMrootDomain::preventTransitionToUserActive( bool prevent )
5026 {
5027 #if !NO_KERNEL_HID
5028     _preventUserActive = prevent;
5029     if (wrangler && !_preventUserActive)
5030     {
5031         // Allowing transition to user active, but the wrangler may have
5032         // already powered ON in case of sleep cancel/revert. Poll the
5033         // same conditions checked for in displayWranglerNotification()
5034         // to bring the user active state up to date.
5035 
5036         if ((wrangler->getPowerState() == kWranglerPowerStateMax) &&
5037             (wrangler->getPowerStateForClient(gIOPMPowerClientDevice) ==
5038              kWranglerPowerStateMax))
5039         {
5040             evaluatePolicy( kStimulusEnterUserActiveState );
5041         }
5042     }
5043 #endif
5044 }
5045 
5046 //******************************************************************************
5047 // Approve usage of delayed child notification by PM.
5048 //******************************************************************************
5049 
5050 bool IOPMrootDomain::shouldDelayChildNotification(
5051     IOService * service )
5052 {
5053     if (((gDarkWakeFlags & kDarkWakeFlagHIDTickleMask) != 0) &&
5054         (kFullWakeReasonNone == fullWakeReason) &&
5055         (kSystemTransitionWake == _systemTransitionType))
5056     {
5057         DLOG("%s: delay child notify\n", service->getName());
5058         return true;
5059     }
5060     return false;
5061 }
5062 
5063 //******************************************************************************
5064 // PM actions for PCI device.
5065 //******************************************************************************
5066 
5067 void IOPMrootDomain::handlePowerChangeStartForPCIDevice(
5068     IOService *             service,
5069     IOPMActions *           actions,
5070     IOPMPowerStateIndex     powerState,
5071     IOPMPowerChangeFlags *  inOutChangeFlags )
5072 {
5073     pmTracer->tracePCIPowerChange(
5074         PMTraceWorker::kPowerChangeStart,
5075         service, *inOutChangeFlags,
5076         (actions->parameter & kPMActionsPCIBitNumberMask));
5077 }
5078 
5079 void IOPMrootDomain::handlePowerChangeDoneForPCIDevice(
5080     IOService *             service,
5081     IOPMActions *           actions,
5082     IOPMPowerStateIndex     powerState,
5083     IOPMPowerChangeFlags    changeFlags )
5084 {
5085     pmTracer->tracePCIPowerChange(
5086         PMTraceWorker::kPowerChangeCompleted,
5087         service, changeFlags,
5088         (actions->parameter & kPMActionsPCIBitNumberMask));
5089 }
5090 
5091 //******************************************************************************
5092 // registerInterest
5093 //
5094 // Override IOService::registerInterest() to intercept special clients.
5095 //******************************************************************************
5096 
5097 class IOPMServiceInterestNotifier: public _IOServiceInterestNotifier
5098 {
5099 
5100     friend class IOPMrootDomain;
5101     OSDeclareDefaultStructors(IOPMServiceInterestNotifier)
5102 
5103 protected:
5104     uint32_t    ackTimeoutCnt;
5105 
5106 };
5107 
5108 OSDefineMetaClassAndStructors(IOPMServiceInterestNotifier, _IOServiceInterestNotifier)
5109 
5110 IONotifier * IOPMrootDomain::registerInterest(
5111                 const OSSymbol * typeOfInterest,
5112                 IOServiceInterestHandler handler,
5113                 void * target, void * ref )
5114 {
5115     IOPMServiceInterestNotifier *notifier = 0;
5116     bool            isSystemCapabilityClient;
5117     bool            isKernelCapabilityClient;
5118     IOReturn        rc = kIOReturnError;;
5119 
5120     isSystemCapabilityClient =
5121         typeOfInterest &&
5122         typeOfInterest->isEqualTo(kIOPMSystemCapabilityInterest);
5123 
5124     isKernelCapabilityClient =
5125         typeOfInterest &&
5126         typeOfInterest->isEqualTo(gIOPriorityPowerStateInterest);
5127 
5128     if (isSystemCapabilityClient)
5129         typeOfInterest = gIOAppPowerStateInterest;
5130 
5131     notifier = new IOPMServiceInterestNotifier;
5132     if (!notifier) return NULL;
5133 
5134     if (notifier->init()) {
5135         rc  = super::registerInterestForNotifer(notifier, typeOfInterest, handler, target, ref);
5136     }
5137     if (rc != kIOReturnSuccess) {
5138         notifier->release();
5139         notifier = 0;
5140     }
5141     if (pmPowerStateQueue)
5142     {
5143         notifier->ackTimeoutCnt = 0;
5144         if (isSystemCapabilityClient)
5145         {
5146             notifier->retain();
5147             if (pmPowerStateQueue->submitPowerEvent(
5148                 kPowerEventRegisterSystemCapabilityClient, notifier) == false)
5149                 notifier->release();
5150         }
5151 
5152         if (isKernelCapabilityClient)
5153         {
5154             notifier->retain();
5155             if (pmPowerStateQueue->submitPowerEvent(
5156                 kPowerEventRegisterKernelCapabilityClient, notifier) == false)
5157                 notifier->release();
5158         }
5159     }
5160 
5161     return notifier;
5162 }
5163 
5164 //******************************************************************************
5165 // systemMessageFilter
5166 //
5167 //******************************************************************************
5168 
5169 bool IOPMrootDomain::systemMessageFilter(
5170     void * object, void * arg1, void * arg2, void * arg3 )
5171 {
5172     const IOPMInterestContext * context = (const IOPMInterestContext *) arg1;
5173     bool  isCapMsg = (context->messageType == kIOMessageSystemCapabilityChange);
5174     bool  isCapClient = false;
5175     bool  allow = false;
5176 
5177     do {
5178         if ((kSystemTransitionNewCapClient == _systemTransitionType) &&
5179             (!isCapMsg || !_joinedCapabilityClients ||
5180              !_joinedCapabilityClients->containsObject((OSObject *) object)))
5181             break;
5182 
5183         // Capability change message for app and kernel clients.
5184 
5185         if (isCapMsg)
5186         {
5187             if ((context->notifyType == kNotifyPriority) ||
5188                 (context->notifyType == kNotifyCapabilityChangePriority))
5189                 isCapClient = true;
5190 
5191             if ((context->notifyType == kNotifyCapabilityChangeApps) &&
5192                 (object == (void *) systemCapabilityNotifier))
5193                 isCapClient = true;
5194         }
5195 
5196         if (isCapClient)
5197         {
5198             IOPMSystemCapabilityChangeParameters * capArgs =
5199                 (IOPMSystemCapabilityChangeParameters *) arg2;
5200 
5201             if (kSystemTransitionNewCapClient == _systemTransitionType)
5202             {
5203                 capArgs->fromCapabilities = 0;
5204                 capArgs->toCapabilities = _currentCapability;
5205                 capArgs->changeFlags = 0;
5206             }
5207             else
5208             {
5209                 capArgs->fromCapabilities = _currentCapability;
5210                 capArgs->toCapabilities = _pendingCapability;
5211 
5212                 if (context->isPreChange)
5213                     capArgs->changeFlags = kIOPMSystemCapabilityWillChange;
5214                 else
5215                     capArgs->changeFlags = kIOPMSystemCapabilityDidChange;
5216             }
5217 
5218             // Capability change messages only go to the PM configd plugin.
5219             // Wait for response post-change if capabilitiy is increasing.
5220             // Wait for response pre-change if capability is decreasing.
5221 
5222             if ((context->notifyType == kNotifyCapabilityChangeApps) && arg3 &&
5223                 ( (capabilityLoss && context->isPreChange) ||
5224                   (!capabilityLoss && !context->isPreChange) ) )
5225             {
5226                 // app has not replied yet, wait for it
5227                 *((OSObject **) arg3) = kOSBooleanFalse;
5228             }
5229 
5230             allow = true;
5231             break;
5232         }
5233 
5234         // Capability client will always see kIOMessageCanSystemSleep,
5235         // even for demand sleep. It will also have a chance to veto
5236         // sleep one last time after all clients have responded to
5237         // kIOMessageSystemWillSleep
5238 
5239         if ((kIOMessageCanSystemSleep == context->messageType) ||
5240             (kIOMessageSystemWillNotSleep == context->messageType))
5241         {
5242             if (object == (OSObject *) systemCapabilityNotifier)
5243             {
5244                 allow = true;
5245                 break;
5246             }
5247 
5248             // Not idle sleep, don't ask apps.
5249             if (context->changeFlags & kIOPMSkipAskPowerDown)
5250             {
5251                 break;
5252             }
5253         }
5254 
5255         if (kIOPMMessageLastCallBeforeSleep == context->messageType)
5256         {
5257             if ((object == (OSObject *) systemCapabilityNotifier) &&
5258                 CAP_HIGHEST(kIOPMSystemCapabilityGraphics) &&
5259                 (fullToDarkReason == kIOPMSleepReasonIdle))
5260                 allow = true;
5261             break;
5262         }
5263 
5264         // Reject capability change messages for legacy clients.
5265         // Reject legacy system sleep messages for capability client.
5266 
5267         if (isCapMsg || (object == (OSObject *) systemCapabilityNotifier))
5268         {
5269             break;
5270         }
5271 
5272         // Filter system sleep messages.
5273 
5274         if ((context->notifyType == kNotifyApps) &&
5275             (_systemMessageClientMask & kSystemMessageClientLegacyApp))
5276         {
5277             IOPMServiceInterestNotifier *notify;
5278             allow = true;
5279 
5280             if ((notify = OSDynamicCast(IOPMServiceInterestNotifier, (OSObject *)object))
5281                 && arg3) {
5282 
5283                 if (notify->ackTimeoutCnt >= 3)
5284                     *((OSObject **) arg3) = kOSBooleanFalse;
5285                 else
5286                     *((OSObject **) arg3) = kOSBooleanTrue;
5287             }
5288         }
5289         else if ((context->notifyType == kNotifyPriority) &&
5290                  (_systemMessageClientMask & kSystemMessageClientKernel))
5291         {
5292             allow = true;
5293         }
5294     }
5295     while (false);
5296 
5297     if (allow && isCapMsg && _joinedCapabilityClients)
5298     {
5299         _joinedCapabilityClients->removeObject((OSObject *) object);
5300         if (_joinedCapabilityClients->getCount() == 0)
5301         {
5302             DLOG("destroyed capability client set %p\n",
5303                 OBFUSCATE(_joinedCapabilityClients));
5304             _joinedCapabilityClients->release();
5305             _joinedCapabilityClients = 0;
5306         }
5307     }
5308 
5309     return allow;
5310 }
5311 
5312 //******************************************************************************
5313 // setMaintenanceWakeCalendar
5314 //
5315 //******************************************************************************
5316 
5317 IOReturn IOPMrootDomain::setMaintenanceWakeCalendar(
5318     const IOPMCalendarStruct * calendar )
5319 {
5320     OSData * data;
5321     IOReturn ret = 0;
5322 
5323     if (!calendar)
5324         return kIOReturnBadArgument;
5325 
5326     data = OSData::withBytesNoCopy((void *) calendar, sizeof(*calendar));
5327     if (!data)
5328         return kIOReturnNoMemory;
5329 
5330     if (kPMCalendarTypeMaintenance == calendar->selector) {
5331         ret = setPMSetting(gIOPMSettingMaintenanceWakeCalendarKey, data);
5332         if (kIOReturnSuccess == ret)
5333             OSBitOrAtomic(kIOPMAlarmBitMaintenanceWake, &_scheduledAlarms);
5334     } else
5335     if (kPMCalendarTypeSleepService == calendar->selector)
5336     {
5337         ret = setPMSetting(gIOPMSettingSleepServiceWakeCalendarKey, data);
5338         if (kIOReturnSuccess == ret)
5339             OSBitOrAtomic(kIOPMAlarmBitSleepServiceWake, &_scheduledAlarms);
5340     }
5341     DLOG("_scheduledAlarms = 0x%x\n", (uint32_t) _scheduledAlarms);
5342 
5343     data->release();
5344     return ret;
5345 }
5346 
5347 // MARK: -
5348 // MARK: Display Wrangler
5349 
5350 //******************************************************************************
5351 // displayWranglerNotification
5352 //
5353 // Handle the notification when the IODisplayWrangler changes power state.
5354 //******************************************************************************
5355 
5356 IOReturn IOPMrootDomain::displayWranglerNotification(
5357     void * target, void * refCon,
5358     UInt32 messageType, IOService * service,
5359     void * messageArgument, vm_size_t argSize )
5360 {
5361 #if !NO_KERNEL_HID
5362     int                                 displayPowerState;
5363     IOPowerStateChangeNotification *    params =
5364             (IOPowerStateChangeNotification *) messageArgument;
5365 
5366     if ((messageType != kIOMessageDeviceWillPowerOff) &&
5367         (messageType != kIOMessageDeviceHasPoweredOn))
5368         return kIOReturnUnsupported;
5369 
5370     ASSERT_GATED();
5371     if (!gRootDomain)
5372         return kIOReturnUnsupported;
5373 
5374     displayPowerState = params->stateNumber;
5375     DLOG("wrangler %s ps %d\n",
5376          getIOMessageString(messageType), displayPowerState);
5377 
5378     switch (messageType) {
5379        case kIOMessageDeviceWillPowerOff:
5380             // Display wrangler has dropped power due to display idle
5381             // or force system sleep.
5382             //
5383             // 4 Display ON             kWranglerPowerStateMax
5384             // 3 Display Dim            kWranglerPowerStateDim
5385             // 2 Display Sleep          kWranglerPowerStateSleep
5386             // 1 Not visible to user
5387             // 0 Not visible to user    kWranglerPowerStateMin
5388 
5389             if (displayPowerState <= kWranglerPowerStateSleep)
5390                 gRootDomain->evaluatePolicy( kStimulusDisplayWranglerSleep );
5391             break;
5392 
5393         case kIOMessageDeviceHasPoweredOn:
5394             // Display wrangler has powered on due to user activity
5395             // or wake from sleep.
5396 
5397             if (kWranglerPowerStateMax == displayPowerState)
5398             {
5399                 gRootDomain->evaluatePolicy( kStimulusDisplayWranglerWake );
5400 
5401                 // See comment in handleUpdatePowerClientForDisplayWrangler
5402                 if (service->getPowerStateForClient(gIOPMPowerClientDevice) ==
5403                     kWranglerPowerStateMax)
5404                 {
5405                     gRootDomain->evaluatePolicy( kStimulusEnterUserActiveState );
5406                 }
5407             }
5408             break;
5409     }
5410 #endif
5411     return kIOReturnUnsupported;
5412 }
5413 
5414 //******************************************************************************
5415 // displayWranglerMatchPublished
5416 //
5417 // Receives a notification when the IODisplayWrangler is published.
5418 // When it's published we install a power state change handler.
5419 //******************************************************************************
5420 
5421 bool IOPMrootDomain::displayWranglerMatchPublished(
5422     void * target,
5423     void * refCon,
5424     IOService * newService,
5425     IONotifier * notifier __unused)
5426 {
5427 #if !NO_KERNEL_HID
5428     // found the display wrangler, now install a handler
5429     if( !newService->registerInterest( gIOGeneralInterest,
5430                             &displayWranglerNotification, target, 0) )
5431     {
5432         return false;
5433     }
5434 #endif
5435     return true;
5436 }
5437 
5438 #if defined(__i386__) || defined(__x86_64__)
5439 
5440 bool IOPMrootDomain::IONVRAMMatchPublished(
5441     void * target,
5442     void * refCon,
5443     IOService * newService,
5444     IONotifier * notifier)
5445 {
5446     unsigned int     len = 0;
5447     IOPMrootDomain *rd = (IOPMrootDomain *)target;
5448     OSNumber    *statusCode = NULL;
5449 
5450     if (PEReadNVRAMProperty(kIOSleepWakeDebugKey, NULL, &len))
5451     {
5452         statusCode = OSDynamicCast(OSNumber, rd->getProperty(kIOPMSleepWakeFailureCodeKey));
5453         if (statusCode != NULL) {
5454             if (statusCode->unsigned64BitValue() != 0) {
5455                 rd->swd_flags |= SWD_BOOT_BY_SW_WDOG;
5456                 MSG("System was rebooted due to Sleep/Wake failure\n");
5457             }
5458             else {
5459                 rd->swd_flags |= SWD_BOOT_BY_OSX_WDOG;
5460                 MSG("System was non-responsive and was rebooted by watchdog\n");
5461             }
5462         }
5463 
5464         rd->swd_logBufMap = rd->sleepWakeDebugRetrieve();
5465     }
5466     if (notifier) notifier->remove();
5467     return true;
5468 }
5469 
5470 #else
5471 bool IOPMrootDomain::IONVRAMMatchPublished(
5472     void * target,
5473     void * refCon,
5474     IOService * newService,
5475     IONotifier * notifier __unused)
5476 {
5477     return false;
5478 }
5479 
5480 #endif
5481 
5482 //******************************************************************************
5483 // reportUserInput
5484 //
5485 //******************************************************************************
5486 
5487 void IOPMrootDomain::reportUserInput( void )
5488 {
5489 #if !NO_KERNEL_HID
5490     OSIterator * iter;
5491 
5492     if(!wrangler)
5493     {
5494         iter = getMatchingServices(serviceMatching("IODisplayWrangler"));
5495         if(iter)
5496         {
5497             wrangler = (IOService *) iter->getNextObject();
5498             iter->release();
5499         }
5500     }
5501 
5502     if(wrangler)
5503         wrangler->activityTickle(0,0);
5504 #endif
5505 }
5506 
5507 //******************************************************************************
5508 // latchDisplayWranglerTickle
5509 //******************************************************************************
5510 
5511 bool IOPMrootDomain::latchDisplayWranglerTickle( bool latch )
5512 {
5513 #if !NO_KERNEL_HID
5514     if (latch)
5515     {
5516         if (!(_currentCapability & kIOPMSystemCapabilityGraphics) &&
5517             !(_pendingCapability & kIOPMSystemCapabilityGraphics) &&
5518             !checkSystemCanSustainFullWake())
5519         {
5520             // Currently in dark wake, and not transitioning to full wake.
5521             // Full wake is unsustainable, so latch the tickle to prevent
5522             // the display from lighting up momentarily.
5523             wranglerTickleLatched = true;
5524         }
5525         else
5526         {
5527             wranglerTickleLatched = false;
5528         }
5529     }
5530     else if (wranglerTickleLatched && checkSystemCanSustainFullWake())
5531     {
5532         wranglerTickleLatched = false;
5533 
5534         pmPowerStateQueue->submitPowerEvent(
5535             kPowerEventPolicyStimulus,
5536             (void *) kStimulusDarkWakeActivityTickle );
5537     }
5538 
5539     return wranglerTickleLatched;
5540 #else
5541     return false;
5542 #endif
5543 }
5544 
5545 //******************************************************************************
5546 // setDisplayPowerOn
5547 //
5548 // For root domain user client
5549 //******************************************************************************
5550 
5551 void IOPMrootDomain::setDisplayPowerOn( uint32_t options )
5552 {
5553     if (checkSystemCanSustainFullWake())
5554     {
5555         pmPowerStateQueue->submitPowerEvent( kPowerEventSetDisplayPowerOn,
5556                                              (void *) 0, options );
5557     }
5558 }
5559 
5560 // MARK: -
5561 // MARK: Battery
5562 
5563 //******************************************************************************
5564 // batteryPublished
5565 //
5566 // Notification on battery class IOPowerSource appearance
5567 //******************************************************************************
5568 
5569 bool IOPMrootDomain::batteryPublished(
5570     void * target,
5571     void * root_domain,
5572     IOService * resourceService,
5573     IONotifier * notifier __unused )
5574 {
5575     // rdar://2936060&4435589
5576     // All laptops have dimmable LCD displays
5577     // All laptops have batteries
5578     // So if this machine has a battery, publish the fact that the backlight
5579     // supports dimming.
5580     ((IOPMrootDomain *)root_domain)->publishFeature("DisplayDims");
5581 
5582     return (true);
5583 }
5584 
5585 // MARK: -
5586 // MARK: System PM Policy
5587 
5588 //******************************************************************************
5589 // checkSystemSleepAllowed
5590 //
5591 //******************************************************************************
5592 
5593 bool IOPMrootDomain::checkSystemSleepAllowed( IOOptionBits options,
5594                                               uint32_t     sleepReason )
5595 {
5596     int err = 0;
5597 
5598     // Conditions that prevent idle and demand system sleep.
5599 
5600     do {
5601         if (userDisabledAllSleep)
5602         {
5603             err = 1;        // 1. user-space sleep kill switch
5604             break;
5605         }
5606 
5607         if (systemBooting || systemShutdown || gWillShutdown)
5608         {
5609             err = 2;        // 2. restart or shutdown in progress
5610             break;
5611         }
5612 
5613         if (options == 0)
5614             break;
5615 
5616         // Conditions above pegs the system at full wake.
5617         // Conditions below prevent system sleep but does not prevent
5618         // dark wake, and must be called from gated context.
5619 
5620 #if !CONFIG_SLEEP
5621         err = 3;            // 3. config does not support sleep
5622         break;
5623 #endif
5624 
5625         if (lowBatteryCondition)
5626         {
5627             break;          // always sleep on low battery
5628         }
5629 
5630         if (sleepReason == kIOPMSleepReasonDarkWakeThermalEmergency)
5631         {
5632             break;          // always sleep on dark wake thermal emergencies
5633         }
5634 
5635         if (preventSystemSleepList->getCount() != 0)
5636         {
5637             err = 4;        // 4. child prevent system sleep clamp
5638             break;
5639         }
5640 
5641         if (getPMAssertionLevel( kIOPMDriverAssertionCPUBit ) ==
5642             kIOPMDriverAssertionLevelOn)
5643         {
5644             err = 5;        // 5. CPU assertion
5645             break;
5646         }
5647 
5648         if (pciCantSleepValid)
5649         {
5650             if (pciCantSleepFlag)
5651                 err = 6;    // 6. PCI card does not support PM (cached)
5652             break;
5653         }
5654         else if (sleepSupportedPEFunction &&
5655                  CAP_HIGHEST(kIOPMSystemCapabilityGraphics))
5656         {
5657             IOReturn ret;
5658             OSBitAndAtomic(~kPCICantSleep, &platformSleepSupport);
5659             ret = getPlatform()->callPlatformFunction(
5660                                     sleepSupportedPEFunction, false,
5661                                     NULL, NULL, NULL, NULL);
5662             pciCantSleepValid = true;
5663             pciCantSleepFlag  = false;
5664             if ((platformSleepSupport & kPCICantSleep) ||
5665                 ((ret != kIOReturnSuccess) && (ret != kIOReturnUnsupported)))
5666             {
5667                 err = 6;    // 6. PCI card does not support PM
5668                 pciCantSleepFlag = true;
5669                 break;
5670             }
5671         }
5672     }
5673     while (false);
5674 
5675     if (err)
5676     {
5677         DLOG("System sleep prevented by %d\n", err);
5678         return false;
5679     }
5680     return true;
5681 }
5682 
5683 bool IOPMrootDomain::checkSystemSleepEnabled( void )
5684 {
5685     return checkSystemSleepAllowed(0, 0);
5686 }
5687 
5688 bool IOPMrootDomain::checkSystemCanSleep( uint32_t sleepReason )
5689 {
5690     ASSERT_GATED();
5691     return checkSystemSleepAllowed(1, sleepReason);
5692 }
5693 
5694 //******************************************************************************
5695 // checkSystemCanSustainFullWake
5696 //******************************************************************************
5697 
5698 bool IOPMrootDomain::checkSystemCanSustainFullWake( void )
5699 {
5700 #if !NO_KERNEL_HID
5701     if (lowBatteryCondition)
5702     {
5703         // Low battery wake, or received a low battery notification
5704         // while system is awake. This condition will persist until
5705         // the following wake.
5706         return false;
5707     }
5708 
5709     if (clamshellExists && clamshellClosed && !clamshellSleepDisabled)
5710     {
5711         // Graphics state is unknown and external display might not be probed.
5712         // Do not incorporate state that requires graphics to be in max power
5713         // such as desktopMode or clamshellDisabled.
5714 
5715         if (!acAdaptorConnected)
5716         {
5717             DLOG("full wake check: no AC\n");
5718             return false;
5719         }
5720     }
5721 #endif
5722     return true;
5723 }
5724 
5725 //******************************************************************************
5726 // adjustPowerState
5727 //
5728 // Conditions that affect our wake/sleep decision has changed.
5729 // If conditions dictate that the system must remain awake, clamp power
5730 // state to max with changePowerStateToPriv(ON). Otherwise if sleepASAP
5731 // is TRUE, then remove the power clamp and allow the power state to drop
5732 // to SLEEP_STATE.
5733 //******************************************************************************
5734 
5735 void IOPMrootDomain::adjustPowerState( bool sleepASAP )
5736 {
5737     DLOG("adjustPowerState ps %u, asap %d, slider %ld\n",
5738         (uint32_t) getPowerState(), sleepASAP, sleepSlider);
5739 
5740     ASSERT_GATED();
5741 
5742     if ((sleepSlider == 0) || !checkSystemSleepEnabled())
5743     {
5744         changePowerStateToPriv(ON_STATE);
5745     }
5746     else if ( sleepASAP )
5747     {
5748         changePowerStateToPriv(SLEEP_STATE);
5749     }
5750 }
5751 
5752 //******************************************************************************
5753 // dispatchPowerEvent
5754 //
5755 // IOPMPowerStateQueue callback function. Running on PM work loop thread.
5756 //******************************************************************************
5757 
5758 void IOPMrootDomain::dispatchPowerEvent(
5759     uint32_t event, void * arg0, uint64_t arg1 )
5760 {
5761     DLOG("power event %u args %p 0x%llx\n", event, OBFUSCATE(arg0), arg1);
5762     ASSERT_GATED();
5763 
5764     switch (event)
5765     {
5766         case kPowerEventFeatureChanged:
5767             messageClients(kIOPMMessageFeatureChange, this);
5768             break;
5769 
5770         case kPowerEventReceivedPowerNotification:
5771             handlePowerNotification( (UInt32)(uintptr_t) arg0 );
5772             break;
5773 
5774         case kPowerEventSystemBootCompleted:
5775             if (systemBooting)
5776             {
5777                 systemBooting = false;
5778 
5779                 if (lowBatteryCondition)
5780                 {
5781                     privateSleepSystem (kIOPMSleepReasonLowPower);
5782 
5783                     // The rest is unnecessary since the system is expected
5784                     // to sleep immediately. The following wake will update
5785                     // everything.
5786                     break;
5787                 }
5788 
5789                 if (swd_flags & SWD_VALID_LOGS) {
5790                     if (swd_flags & SWD_LOGS_IN_MEM) {
5791                         sleepWakeDebugDumpFromMem(swd_logBufMap);
5792                         swd_logBufMap->release();
5793                         swd_logBufMap = 0;
5794                     }
5795                     else if (swd_flags & SWD_LOGS_IN_FILE)
5796                         sleepWakeDebugDumpFromFile();
5797                 }
5798                 else if (swd_flags & (SWD_BOOT_BY_SW_WDOG|SWD_BOOT_BY_OSX_WDOG)) {
5799                     // If logs are invalid, write the failure code
5800                     sleepWakeDebugDumpFromMem(NULL);
5801                 }
5802                 // If lid is closed, re-send lid closed notification
5803                 // now that booting is complete.
5804                 if ( clamshellClosed )
5805                 {
5806                     handlePowerNotification(kLocalEvalClamshellCommand);
5807                 }
5808                 evaluatePolicy( kStimulusAllowSystemSleepChanged );
5809 
5810             }
5811             break;
5812 
5813         case kPowerEventSystemShutdown:
5814             if (kOSBooleanTrue == (OSBoolean *) arg0)
5815             {
5816                 /* We set systemShutdown = true during shutdown
5817                    to prevent sleep at unexpected times while loginwindow is trying
5818                    to shutdown apps and while the OS is trying to transition to
5819                    complete power of.
5820 
5821                    Set to true during shutdown, as soon as loginwindow shows
5822                    the "shutdown countdown dialog", through individual app
5823                    termination, and through black screen kernel shutdown.
5824                  */
5825                 systemShutdown = true;
5826             } else {
5827                 /*
5828                  A shutdown was initiated, but then the shutdown
5829                  was cancelled, clearing systemShutdown to false here.
5830                 */
5831                 systemShutdown = false;
5832             }
5833             break;
5834 
5835         case kPowerEventUserDisabledSleep:
5836             userDisabledAllSleep = (kOSBooleanTrue == (OSBoolean *) arg0);
5837             break;
5838 
5839         case kPowerEventRegisterSystemCapabilityClient:
5840             if (systemCapabilityNotifier)
5841             {
5842                 systemCapabilityNotifier->release();
5843                 systemCapabilityNotifier = 0;
5844             }
5845             if (arg0)
5846             {
5847                 systemCapabilityNotifier = (IONotifier *) arg0;
5848                 systemCapabilityNotifier->retain();
5849             }
5850             /* intentional fall-through */
5851 
5852         case kPowerEventRegisterKernelCapabilityClient:
5853             if (!_joinedCapabilityClients)
5854                 _joinedCapabilityClients = OSSet::withCapacity(8);
5855             if (arg0)
5856             {
5857                 IONotifier * notify = (IONotifier *) arg0;
5858                 if (_joinedCapabilityClients)
5859                 {
5860                     _joinedCapabilityClients->setObject(notify);
5861                     synchronizePowerTree( kIOPMSyncNoChildNotify );
5862                 }
5863                 notify->release();
5864             }
5865             break;
5866 
5867         case kPowerEventPolicyStimulus:
5868             if (arg0)
5869             {
5870                 int stimulus = (uintptr_t) arg0;
5871                 evaluatePolicy( stimulus, (uint32_t) arg1 );
5872             }
5873             break;
5874 
5875         case kPowerEventAssertionCreate:
5876             if (pmAssertions) {
5877                 pmAssertions->handleCreateAssertion((OSData *)arg0);
5878             }
5879             break;
5880 
5881 
5882         case kPowerEventAssertionRelease:
5883             if (pmAssertions) {
5884                 pmAssertions->handleReleaseAssertion(arg1);
5885             }
5886             break;
5887 
5888         case kPowerEventAssertionSetLevel:
5889             if (pmAssertions) {
5890                 pmAssertions->handleSetAssertionLevel(arg1, (IOPMDriverAssertionLevel)(uintptr_t)arg0);
5891             }
5892             break;
5893 
5894         case kPowerEventQueueSleepWakeUUID:
5895             handleQueueSleepWakeUUID((OSObject *)arg0);
5896             break;
5897         case kPowerEventPublishSleepWakeUUID:
5898             handlePublishSleepWakeUUID((bool)arg0);
5899             break;
5900 
5901         case kPowerEventSetDisplayPowerOn:
5902             if (!wrangler) break;
5903             if (arg1 != 0)
5904             {
5905                 // Force wrangler to max power state. If system is in dark wake
5906                 // this alone won't raise the wrangler's power state.
5907 
5908                 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMax);
5909 
5910                 // System in dark wake, always requesting full wake should
5911                 // not have any bad side-effects, even if the request fails.
5912 
5913                 if (!CAP_CURRENT(kIOPMSystemCapabilityGraphics))
5914                 {
5915                     setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeNotification);
5916                     requestFullWake( kFullWakeReasonDisplayOn );
5917                 }
5918             }
5919             else
5920             {
5921                 // Relenquish desire to power up display.
5922                 // Must first transition to state 1 since wrangler doesn't
5923                 // power off the displays at state 0. At state 0 the root
5924                 // domain is removed from the wrangler's power client list.
5925 
5926                 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMin + 1);
5927                 wrangler->changePowerStateForRootDomain(kWranglerPowerStateMin);
5928             }
5929             break;
5930     }
5931 }
5932 
5933 //******************************************************************************
5934 // systemPowerEventOccurred
5935 //
5936 // The power controller is notifying us of a hardware-related power management
5937 // event that we must handle.
5938 //
5939 // systemPowerEventOccurred covers the same functionality that
5940 // receivePowerNotification does; it simply provides a richer API for conveying
5941 // more information.
5942 //******************************************************************************
5943 
5944 IOReturn IOPMrootDomain::systemPowerEventOccurred(
5945     const OSSymbol *event,
5946     uint32_t intValue)
5947 {
5948     IOReturn        attempt = kIOReturnSuccess;
5949     OSNumber        *newNumber = NULL;
5950 
5951     if (!event)
5952         return kIOReturnBadArgument;
5953 
5954     newNumber = OSNumber::withNumber(intValue, 8*sizeof(intValue));
5955     if (!newNumber)
5956         return kIOReturnInternalError;
5957 
5958     attempt = systemPowerEventOccurred(event, (OSObject *)newNumber);
5959 
5960     newNumber->release();
5961 
5962     return attempt;
5963 }
5964 
5965 IOReturn IOPMrootDomain::systemPowerEventOccurred(
5966     const OSSymbol *event,
5967     OSObject *value)
5968 {
5969     OSDictionary *thermalsDict = NULL;
5970     bool shouldUpdate = true;
5971 
5972     if (!event || !value)
5973         return kIOReturnBadArgument;
5974 
5975     // LOCK
5976     // We reuse featuresDict Lock because it already exists and guards
5977     // the very infrequently used publish/remove feature mechanism; so there's zero rsk
5978     // of stepping on that lock.
5979     if (featuresDictLock) IOLockLock(featuresDictLock);
5980 
5981     thermalsDict = (OSDictionary *)getProperty(kIOPMRootDomainPowerStatusKey);
5982 
5983     if (thermalsDict && OSDynamicCast(OSDictionary, thermalsDict)) {
5984         thermalsDict = OSDictionary::withDictionary(thermalsDict);
5985     } else {
5986         thermalsDict = OSDictionary::withCapacity(1);
5987     }
5988 
5989     if (!thermalsDict) {
5990         shouldUpdate = false;
5991         goto exit;
5992     }
5993 
5994     thermalsDict->setObject (event, value);
5995 
5996     setProperty (kIOPMRootDomainPowerStatusKey, thermalsDict);
5997 
5998     thermalsDict->release();
5999 
6000 exit:
6001     // UNLOCK
6002     if (featuresDictLock) IOLockUnlock(featuresDictLock);
6003 
6004     if (shouldUpdate)
6005         messageClients (kIOPMMessageSystemPowerEventOccurred, (void *)NULL);
6006 
6007     return kIOReturnSuccess;
6008 }
6009 
6010 //******************************************************************************
6011 // receivePowerNotification
6012 //
6013 // The power controller is notifying us of a hardware-related power management
6014 // event that we must handle. This may be a result of an 'environment' interrupt
6015 // from the power mgt micro.
6016 //******************************************************************************
6017 
6018 IOReturn IOPMrootDomain::receivePowerNotification( UInt32 msg )
6019 {
6020     pmPowerStateQueue->submitPowerEvent(
6021         kPowerEventReceivedPowerNotification, (void *)(uintptr_t) msg );
6022     return kIOReturnSuccess;
6023 }
6024 
6025 void IOPMrootDomain::handlePowerNotification( UInt32 msg )
6026 {
6027     bool        eval_clamshell = false;
6028 
6029     ASSERT_GATED();
6030 
6031     /*
6032      * Local (IOPMrootDomain only) eval clamshell command
6033      */
6034     if (msg & kLocalEvalClamshellCommand)
6035     {
6036         eval_clamshell = true;
6037     }
6038 
6039     /*
6040      * Overtemp
6041      */
6042     if (msg & kIOPMOverTemp)
6043     {
6044         MSG("PowerManagement emergency overtemp signal. Going to sleep!");
6045         privateSleepSystem (kIOPMSleepReasonThermalEmergency);
6046     }
6047 
6048     /*
6049      * Sleep if system is in dark wake
6050      */
6051     if (msg & kIOPMDWOverTemp)
6052     {
6053         DLOG("DarkWake thermal limits message received!\n");
6054 
6055         // Inform cap client that we're going to sleep
6056         messageClients(kIOPMMessageDarkWakeThermalEmergency);
6057 
6058     }
6059 
6060     /*
6061      * Sleep Now!
6062      */
6063     if (msg & kIOPMSleepNow)
6064     {
6065         privateSleepSystem (kIOPMSleepReasonSoftware);
6066     }
6067 
6068     /*
6069      * Power Emergency
6070      */
6071     if (msg & kIOPMPowerEmergency)
6072     {
6073         lowBatteryCondition = true;
6074         privateSleepSystem (kIOPMSleepReasonLowPower);
6075     }
6076 
6077     /*
6078      * Clamshell OPEN
6079      */
6080     if (msg & kIOPMClamshellOpened)
6081     {
6082         // Received clamshel open message from clamshell controlling driver
6083         // Update our internal state and tell general interest clients
6084         clamshellClosed = false;
6085         clamshellExists = true;
6086 
6087         // Don't issue a hid tickle when lid is open and polled on wake
6088         if (msg & kIOPMSetValue)
6089         {
6090             setProperty(kIOPMRootDomainWakeTypeKey, "Lid Open");
6091             reportUserInput();
6092         }
6093 
6094         // Tell PMCPU
6095         informCPUStateChange(kInformLid, 0);
6096 
6097         // Tell general interest clients
6098         sendClientClamshellNotification();
6099 
6100         bool aborting =  ((lastSleepReason == kIOPMSleepReasonClamshell)
6101                        || (lastSleepReason == kIOPMSleepReasonIdle)
6102                        || (lastSleepReason == kIOPMSleepReasonMaintenance));
6103         if (aborting) userActivityCount++;
6104         DLOG("clamshell tickled %d lastSleepReason %d\n", userActivityCount, lastSleepReason);
6105     }
6106 
6107     /*
6108      * Clamshell CLOSED
6109      * Send the clamshell interest notification since the lid is closing.
6110      */
6111     if (msg & kIOPMClamshellClosed)
6112     {
6113         // Received clamshel open message from clamshell controlling driver
6114         // Update our internal state and tell general interest clients
6115         clamshellClosed = true;
6116         clamshellExists = true;
6117 
6118         // Tell PMCPU
6119         informCPUStateChange(kInformLid, 1);
6120 
6121         // Tell general interest clients
6122         sendClientClamshellNotification();
6123 
6124         // And set eval_clamshell = so we can attempt
6125         eval_clamshell = true;
6126     }
6127 
6128     /*
6129      * Set Desktop mode (sent from graphics)
6130      *
6131      *  -> reevaluate lid state
6132      */
6133     if (msg & kIOPMSetDesktopMode)
6134     {
6135         desktopMode = (0 != (msg & kIOPMSetValue));
6136         msg &= ~(kIOPMSetDesktopMode | kIOPMSetValue);
6137 
6138         sendClientClamshellNotification();
6139 
6140         // Re-evaluate the lid state
6141         eval_clamshell = true;
6142     }
6143 
6144     /*
6145      * AC Adaptor connected
6146      *
6147      *  -> reevaluate lid state
6148      */
6149     if (msg & kIOPMSetACAdaptorConnected)
6150     {
6151         acAdaptorConnected = (0 != (msg & kIOPMSetValue));
6152         msg &= ~(kIOPMSetACAdaptorConnected | kIOPMSetValue);
6153 
6154         // Tell CPU PM
6155         informCPUStateChange(kInformAC, !acAdaptorConnected);
6156 
6157         // Tell BSD if AC is connected
6158         //      0 == external power source; 1 == on battery
6159         post_sys_powersource(acAdaptorConnected ? 0:1);
6160 
6161         sendClientClamshellNotification();
6162 
6163         // Re-evaluate the lid state
6164         eval_clamshell = true;
6165 
6166         // Lack of AC may have latched a display wrangler tickle.
6167         // This mirrors the hardware's USB wake event latch, where a latched
6168         // USB wake event followed by an AC attach will trigger a full wake.
6169         latchDisplayWranglerTickle( false );
6170 
6171 #if HIBERNATION
6172         // AC presence will reset the standy timer delay adjustment.
6173         _standbyTimerResetSeconds = 0;
6174 #endif
6175         if (!userIsActive) {
6176             // Reset userActivityTime when power supply is changed(rdr 13789330)
6177             clock_get_uptime(&userActivityTime);
6178         }
6179     }
6180 
6181     /*
6182      * Enable Clamshell (external display disappear)
6183      *
6184      *  -> reevaluate lid state
6185      */
6186     if (msg & kIOPMEnableClamshell)
6187     {
6188         // Re-evaluate the lid state
6189         // System should sleep on external display disappearance
6190         // in lid closed operation.
6191         if (true == clamshellDisabled)
6192         {
6193             eval_clamshell = true;
6194         }
6195 
6196         clamshellDisabled = false;
6197         sendClientClamshellNotification();
6198     }
6199 
6200     /*
6201      * Disable Clamshell (external display appeared)
6202      * We don't bother re-evaluating clamshell state. If the system is awake,
6203      * the lid is probably open.
6204      */
6205     if (msg & kIOPMDisableClamshell)
6206     {
6207         clamshellDisabled = true;
6208         sendClientClamshellNotification();
6209     }
6210 
6211     /*
6212      * Evaluate clamshell and SLEEP if appropiate
6213      */
6214     if (eval_clamshell && clamshellClosed)
6215     {
6216         if (shouldSleepOnClamshellClosed())
6217             privateSleepSystem (kIOPMSleepReasonClamshell);
6218         else
6219             evaluatePolicy( kStimulusDarkWakeEvaluate );
6220     }
6221 
6222     /*
6223      * Power Button
6224      */
6225     if (msg & kIOPMPowerButton)
6226     {
6227         if (!wranglerAsleep)
6228         {
6229             OSString *pbs = OSString::withCString("DisablePowerButtonSleep");
6230             // Check that power button sleep is enabled
6231             if( pbs ) {
6232                 if( kOSBooleanTrue != getProperty(pbs))
6233                     privateSleepSystem (kIOPMSleepReasonPowerButton);
6234             }
6235         }
6236         else
6237             reportUserInput();
6238     }
6239 }
6240 
6241 //******************************************************************************
6242 // evaluatePolicy
6243 //
6244 // Evaluate root-domain policy in response to external changes.
6245 //******************************************************************************
6246 
6247 void IOPMrootDomain::evaluatePolicy( int stimulus, uint32_t arg )
6248 {
6249     union {
6250         struct {
6251             int idleSleepEnabled    : 1;
6252             int idleSleepDisabled   : 1;
6253             int displaySleep        : 1;
6254             int sleepDelayChanged   : 1;
6255             int evaluateDarkWake    : 1;
6256             int adjustPowerState    : 1;
6257             int userBecameInactive  : 1;
6258         } bit;
6259         uint32_t u32;
6260     } flags;
6261 
6262     DLOG("evaluatePolicy( %d, 0x%x )\n", stimulus, arg);
6263 
6264     ASSERT_GATED();
6265     flags.u32 = 0;
6266 
6267     switch (stimulus)
6268     {
6269         case kStimulusDisplayWranglerSleep:
6270             if (!wranglerAsleep)
6271             {
6272                 // first transition to wrangler sleep or lower
6273                 wranglerAsleep = true;
6274                 flags.bit.displaySleep = true;
6275             }
6276             break;
6277 
6278         case kStimulusDisplayWranglerWake:
6279             displayIdleForDemandSleep = false;
6280             wranglerAsleep = false;
6281             break;
6282 
6283         case kStimulusEnterUserActiveState:
6284             if (_preventUserActive)
6285             {
6286                 DLOG("user active dropped\n");
6287                 break;
6288             }
6289             if (!userIsActive)
6290             {
6291                 userIsActive = true;
6292                 userWasActive = true;
6293 
6294                 // Stay awake after dropping demand for display power on
6295                 if (kFullWakeReasonDisplayOn == fullWakeReason)
6296                     fullWakeReason = fFullWakeReasonDisplayOnAndLocalUser;
6297 
6298                 setProperty(gIOPMUserIsActiveKey, kOSBooleanTrue);
6299                 messageClients(kIOPMMessageUserIsActiveChanged);
6300             }
6301             flags.bit.idleSleepDisabled = true;
6302             break;
6303 
6304         case kStimulusLeaveUserActiveState:
6305             if (userIsActive)
6306             {
6307                 userIsActive = false;
6308                 clock_get_uptime(&userBecameInactiveTime);
6309                 flags.bit.userBecameInactive = true;
6310 
6311                 setProperty(gIOPMUserIsActiveKey, kOSBooleanFalse);
6312                 messageClients(kIOPMMessageUserIsActiveChanged);
6313             }
6314             break;
6315 
6316         case kStimulusAggressivenessChanged:
6317         {
6318             unsigned long   minutesToIdleSleep  = 0;
6319             unsigned long   minutesToDisplayDim = 0;
6320             unsigned long   minutesDelta        = 0;
6321 
6322             // Fetch latest display and system sleep slider values.
6323             getAggressiveness(kPMMinutesToSleep, &minutesToIdleSleep);
6324             getAggressiveness(kPMMinutesToDim,   &minutesToDisplayDim);
6325             DLOG("aggressiveness changed: system %u->%u, display %u\n",
6326                 (uint32_t) sleepSlider,
6327                 (uint32_t) minutesToIdleSleep,
6328                 (uint32_t) minutesToDisplayDim);
6329 
6330             DLOG("idle time -> %ld secs (ena %d)\n",
6331                 idleSeconds, (minutesToIdleSleep != 0));
6332 
6333             if (0x7fffffff == minutesToIdleSleep)
6334                 minutesToIdleSleep = idleSeconds;
6335 
6336             // How long to wait before sleeping the system once
6337             // the displays turns off is indicated by 'extraSleepDelay'.
6338 
6339             if ( minutesToIdleSleep > minutesToDisplayDim )
6340                 minutesDelta = minutesToIdleSleep - minutesToDisplayDim;
6341             else if ( minutesToIdleSleep == minutesToDisplayDim )
6342                 minutesDelta = 1;
6343 
6344             if ((sleepSlider == 0) && (minutesToIdleSleep != 0))
6345                 flags.bit.idleSleepEnabled = true;
6346 
6347             if ((sleepSlider != 0) && (minutesToIdleSleep == 0))
6348                 flags.bit.idleSleepDisabled = true;
6349 
6350             if (((minutesDelta != extraSleepDelay) ||
6351                         (userActivityTime != userActivityTime_prev)) &&
6352                 !flags.bit.idleSleepEnabled && !flags.bit.idleSleepDisabled)
6353                 flags.bit.sleepDelayChanged = true;
6354 
6355             if (systemDarkWake && !darkWakeToSleepASAP &&
6356                 (flags.bit.idleSleepEnabled || flags.bit.idleSleepDisabled))
6357             {
6358                 // Reconsider decision to remain in dark wake
6359                 flags.bit.evaluateDarkWake = true;
6360             }
6361 
6362             sleepSlider = minutesToIdleSleep;
6363             extraSleepDelay = minutesDelta;
6364             userActivityTime_prev = userActivityTime;
6365         }   break;
6366 
6367         case kStimulusDemandSystemSleep:
6368             displayIdleForDemandSleep = true;
6369             if (wrangler && wranglerIdleSettings)
6370             {
6371                 // Request wrangler idle only when demand sleep is triggered
6372                 // from full wake.
6373                 if(CAP_CURRENT(kIOPMSystemCapabilityGraphics))
6374                 {
6375                     wrangler->setProperties(wranglerIdleSettings);
6376                     DLOG("Requested wrangler idle\n");
6377                 }
6378             }
6379             // arg = sleepReason
6380             changePowerStateWithOverrideTo( SLEEP_STATE, arg );
6381             break;
6382 
6383         case kStimulusAllowSystemSleepChanged:
6384             flags.bit.adjustPowerState = true;
6385             break;
6386 
6387         case kStimulusDarkWakeActivityTickle:
6388             // arg == true implies real and not self generated wrangler tickle.
6389             // Update wake type on PM work loop instead of the tickle thread to
6390             // eliminate the possibility of an early tickle clobbering the wake
6391             // type set by the platform driver.
6392             if (arg == true)
6393                 setProperty(kIOPMRootDomainWakeTypeKey, kIOPMRootDomainWakeTypeHIDActivity);
6394 
6395             if (false == wranglerTickled)
6396             {
6397                 if (latchDisplayWranglerTickle(true))
6398                 {
6399                     DLOG("latched tickle\n");
6400                     break;
6401                 }
6402 
6403                 wranglerTickled = true;
6404                 DLOG("Requesting full wake after dark wake activity tickle\n");
6405                 requestFullWake( kFullWakeReasonLocalUser );
6406             }
6407             break;
6408 
6409         case kStimulusDarkWakeEntry:
6410         case kStimulusDarkWakeReentry:
6411             // Any system transitions since the last dark wake transition
6412             // will invalid the stimulus.
6413 
6414             if (arg == _systemStateGeneration)
6415             {
6416                 DLOG("dark wake entry\n");
6417                 systemDarkWake = true;
6418 
6419                 // Keep wranglerAsleep an invariant when wrangler is absent
6420                 if (wrangler)
6421                     wranglerAsleep = true;
6422 
6423                 if (kStimulusDarkWakeEntry == stimulus)
6424                 {
6425                     clock_get_uptime(&userBecameInactiveTime);
6426                     flags.bit.evaluateDarkWake = true;
6427                 }
6428 
6429                 // Always accelerate disk spindown while in dark wake,
6430                 // even if system does not support/allow sleep.
6431 
6432                 cancelIdleSleepTimer();
6433                 setQuickSpinDownTimeout();
6434             }
6435             break;
6436 
6437         case kStimulusDarkWakeEvaluate:
6438             if (systemDarkWake)
6439             {
6440                 flags.bit.evaluateDarkWake = true;
6441             }
6442             break;
6443 
6444         case kStimulusNoIdleSleepPreventers:
6445             flags.bit.adjustPowerState = true;
6446             break;
6447 
6448     } /* switch(stimulus) */
6449 
6450     if (flags.bit.evaluateDarkWake && (kFullWakeReasonNone == fullWakeReason))
6451     {
6452         if (darkWakeToSleepASAP ||
6453             (clamshellClosed && !(desktopMode && acAdaptorConnected)))
6454         {
6455             uint32_t newSleepReason;
6456 
6457             if (CAP_HIGHEST(kIOPMSystemCapabilityGraphics))
6458             {
6459                 // System was previously in full wake. Sleep reason from
6460                 // full to dark already recorded in fullToDarkReason.
6461 
6462                 if (lowBatteryCondition)
6463                     newSleepReason = kIOPMSleepReasonLowPower;
6464                 else
6465                     newSleepReason = fullToDarkReason;
6466             }
6467             else
6468             {
6469                 // In dark wake from system sleep.
6470 
6471                 if (darkWakeSleepService)
6472                     newSleepReason = kIOPMSleepReasonSleepServiceExit;
6473                 else
6474                     newSleepReason = kIOPMSleepReasonMaintenance;
6475             }
6476 
6477             if (checkSystemCanSleep(newSleepReason))
6478             {
6479                 privateSleepSystem(newSleepReason);
6480             }
6481         }
6482         else // non-maintenance (network) dark wake
6483         {
6484             if (checkSystemCanSleep(kIOPMSleepReasonIdle))
6485             {
6486                 // Release power clamp, and wait for children idle.
6487                 adjustPowerState(true);
6488             }
6489             else
6490             {
6491                 changePowerStateToPriv(ON_STATE);
6492             }
6493         }
6494     }
6495 
6496     if (systemDarkWake)
6497     {
6498         // The rest are irrelevant while system is in dark wake.
6499         flags.u32 = 0;
6500     }
6501 
6502     if ((flags.bit.displaySleep) &&
6503         (kFullWakeReasonDisplayOn == fullWakeReason))
6504     {
6505         // kIOPMSleepReasonMaintenance?
6506         changePowerStateWithOverrideTo( SLEEP_STATE, kIOPMSleepReasonMaintenance );
6507     }
6508 
6509     if (flags.bit.userBecameInactive || flags.bit.sleepDelayChanged)
6510     {
6511         bool cancelQuickSpindown = false;
6512 
6513         if (flags.bit.sleepDelayChanged)
6514         {
6515             // Cancel existing idle sleep timer and quick disk spindown.
6516             // New settings will be applied by the idleSleepEnabled flag
6517             // handler below if idle sleep is enabled.
6518 
6519             DLOG("extra sleep timer changed\n");
6520             cancelIdleSleepTimer();
6521             cancelQuickSpindown = true;
6522         }
6523         else
6524         {
6525             DLOG("user inactive\n");
6526         }
6527 
6528         if (!userIsActive && sleepSlider)
6529         {
6530             startIdleSleepTimer(getTimeToIdleSleep());
6531         }
6532 
6533         if (cancelQuickSpindown)
6534             restoreUserSpinDownTimeout();
6535     }
6536 
6537     if (flags.bit.idleSleepEnabled)
6538     {
6539         DLOG("idle sleep timer enabled\n");
6540         if (!wrangler)
6541         {
6542             changePowerStateToPriv(ON_STATE);
6543             if (idleSeconds)
6544             {
6545                 startIdleSleepTimer( idleSeconds );
6546             }
6547         }
6548         else
6549         {
6550             // Start idle timer if prefs now allow system sleep
6551             // and user is already inactive. Disk spindown is
6552             // accelerated upon timer expiration.
6553 
6554             if (!userIsActive)
6555             {
6556                 startIdleSleepTimer(getTimeToIdleSleep());
6557             }
6558         }
6559     }
6560 
6561     if (flags.bit.idleSleepDisabled)
6562     {
6563         DLOG("idle sleep timer disabled\n");
6564         cancelIdleSleepTimer();
6565         restoreUserSpinDownTimeout();
6566         adjustPowerState();
6567     }
6568 
6569     if (flags.bit.adjustPowerState)
6570     {
6571         bool sleepASAP = false;
6572 
6573         if (!systemBooting && (preventIdleSleepList->getCount() == 0))
6574         {
6575             if (!wrangler)
6576             {
6577                 changePowerStateToPriv(ON_STATE);
6578                 if (idleSeconds)
6579                 {
6580                     // stay awake for at least idleSeconds
6581                     startIdleSleepTimer(idleSeconds);
6582                 }
6583             }
6584             else if (!extraSleepDelay && !idleSleepTimerPending && !systemDarkWake)
6585             {
6586                 sleepASAP = true;
6587             }
6588         }
6589 
6590         adjustPowerState(sleepASAP);
6591     }
6592 }
6593 
6594 //******************************************************************************
6595 // requestFullWake
6596 //
6597 // Request transition from dark wake to full wake
6598 //******************************************************************************
6599 
6600 void IOPMrootDomain::requestFullWake( FullWakeReason reason )
6601 {
6602     uint32_t        options = 0;
6603     IOService *     pciRoot = 0;
6604     bool            promotion = false;
6605 
6606     // System must be in dark wake and a valid reason for entering full wake
6607     if ((kFullWakeReasonNone == reason) ||
6608         (kFullWakeReasonNone != fullWakeReason) ||
6609         (CAP_CURRENT(kIOPMSystemCapabilityGraphics)))
6610     {
6611         return;
6612     }
6613 
6614     // Will clear reason upon exit from full wake
6615     fullWakeReason = reason;
6616 
6617     _desiredCapability |= (kIOPMSystemCapabilityGraphics |
6618                            kIOPMSystemCapabilityAudio);
6619 
6620     if ((kSystemTransitionWake == _systemTransitionType) &&
6621         !(_pendingCapability & kIOPMSystemCapabilityGraphics) &&
6622         !graphicsSuppressed)
6623     {
6624         // Promote to full wake while waking up to dark wake due to tickle.
6625         // PM will hold off notifying the graphics subsystem about system wake
6626         // as late as possible, so if a HID tickle does arrive, graphics can
6627         // power up on this same wake cycle. The latency to power up graphics
6628         // on the next cycle can be huge on some systems. However, once any
6629         // graphics suppression has taken effect, it is too late. All other
6630         // graphics devices must be similarly suppressed. But the delay till
6631         // the following cycle should be short.
6632 
6633         _pendingCapability |= (kIOPMSystemCapabilityGraphics |
6634                                kIOPMSystemCapabilityAudio);
6635 
6636         // Immediately bring up audio and graphics
6637         pciRoot = pciHostBridgeDriver;
6638         willEnterFullWake();
6639         promotion = true;
6640     }
6641 
6642     // Unsafe to cancel once graphics was powered.
6643     // If system woke from dark wake, the return to sleep can
6644     // be cancelled. "awake -> dark -> sleep" transition
6645     // can be canceled also, during the "dark --> sleep" phase
6646     // *prior* to driver power down.
6647     if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics) ||
6648         _pendingCapability == 0) {
6649         options |= kIOPMSyncCancelPowerDown;
6650     }
6651 
6652     synchronizePowerTree(options, pciRoot);
6653     if (kFullWakeReasonLocalUser == fullWakeReason)
6654     {
6655         // IOGraphics doesn't light the display even though graphics is
6656         // enabled in kIOMessageSystemCapabilityChange message(radar 9502104)
6657         // So, do an explicit activity tickle
6658         if (wrangler)
6659             wrangler->activityTickle(0,0);
6660     }
6661 
6662     // Log a timestamp for the initial full wake request.
6663     // System may not always honor this full wake request.
6664     if (!CAP_HIGHEST(kIOPMSystemCapabilityGraphics))
6665     {
6666         AbsoluteTime    now;
6667         uint64_t        nsec;
6668 
6669         clock_get_uptime(&now);
6670         SUB_ABSOLUTETIME(&now, &systemWakeTime);
6671         absolutetime_to_nanoseconds(now, &nsec);
6672         MSG("full wake %s (reason %u) %u ms\n",
6673             promotion ? "promotion" : "request",
6674             fullWakeReason, ((int)((nsec) / 1000000ULL)));
6675     }
6676 }
6677 
6678 //******************************************************************************
6679 // willEnterFullWake
6680 //
6681 // System will enter full wake from sleep, from dark wake, or from dark
6682 // wake promotion. This function aggregate things that are in common to
6683 // all three full wake transitions.
6684 //
6685 // Assumptions: fullWakeReason was updated
6686 //******************************************************************************
6687 
6688 void IOPMrootDomain::willEnterFullWake( void )
6689 {
6690     hibernateRetry = false;
6691     sleepToStandby = false;
6692     sleepTimerMaintenance = false;
6693 
6694     _systemMessageClientMask = kSystemMessageClientPowerd |
6695                                kSystemMessageClientLegacyApp;
6696 
6697     if ((_highestCapability & kIOPMSystemCapabilityGraphics) == 0)
6698     {
6699         // Initial graphics full power
6700         _systemMessageClientMask |= kSystemMessageClientKernel;
6701 
6702         // Set kIOPMUserTriggeredFullWakeKey before full wake for IOGraphics
6703         setProperty(gIOPMUserTriggeredFullWakeKey,
6704             (kFullWakeReasonLocalUser == fullWakeReason) ?
6705                 kOSBooleanTrue : kOSBooleanFalse);
6706     }
6707 #if HIBERNATION
6708     IOHibernateSetWakeCapabilities(_pendingCapability);
6709 #endif
6710 
6711     IOService::setAdvisoryTickleEnable( true );
6712     tellClients(kIOMessageSystemWillPowerOn);
6713     preventTransitionToUserActive(false);
6714 }
6715 
6716 //******************************************************************************
6717 // fullWakeDelayedWork
6718 //
6719 // System has already entered full wake. Invoked by a delayed thread call.
6720 //******************************************************************************
6721 
6722 void IOPMrootDomain::fullWakeDelayedWork( void )
6723 {
6724 #if DARK_TO_FULL_EVALUATE_CLAMSHELL
6725     // Not gated, don't modify state
6726     if ((kSystemTransitionNone == _systemTransitionType) &&
6727         CAP_CURRENT(kIOPMSystemCapabilityGraphics))
6728     {
6729         receivePowerNotification( kLocalEvalClamshellCommand );
6730     }
6731 #endif
6732 }
6733 
6734 //******************************************************************************
6735 // evaluateAssertions
6736 //
6737 //******************************************************************************
6738 void IOPMrootDomain::evaluateAssertions(IOPMDriverAssertionType newAssertions, IOPMDriverAssertionType oldAssertions)
6739 {
6740     IOPMDriverAssertionType changedBits = newAssertions ^ oldAssertions;
6741 
6742     messageClients(kIOPMMessageDriverAssertionsChanged);
6743 
6744     if (changedBits & kIOPMDriverAssertionPreventDisplaySleepBit) {
6745 
6746         if (wrangler) {
6747             bool value = (newAssertions & kIOPMDriverAssertionPreventDisplaySleepBit) ? true : false;
6748 
6749             DLOG("wrangler->setIgnoreIdleTimer\(%d)\n", value);
6750             wrangler->setIgnoreIdleTimer( value );
6751         }
6752     }
6753 
6754     if (changedBits & kIOPMDriverAssertionCPUBit)
6755         evaluatePolicy(kStimulusDarkWakeEvaluate);
6756 
6757     if (changedBits & kIOPMDriverAssertionReservedBit7) {
6758         bool value = (newAssertions & kIOPMDriverAssertionReservedBit7) ? true : false;
6759         if (value) {
6760             DLOG("Driver assertion ReservedBit7 raised. Legacy IO preventing sleep\n");
6761             updatePreventIdleSleepList(this, true);
6762         }
6763         else {
6764             DLOG("Driver assertion ReservedBit7 dropped\n");
6765             updatePreventIdleSleepList(this, false);
6766         }
6767     }
6768 }
6769 
6770 // MARK: -
6771 // MARK: Statistics
6772 
6773 //******************************************************************************
6774 // pmStats
6775 //
6776 //******************************************************************************
6777 
6778 void IOPMrootDomain::pmStatsRecordEvent(
6779     int                 eventIndex,
6780     AbsoluteTime        timestamp)
6781 {
6782     bool        starting = eventIndex & kIOPMStatsEventStartFlag ? true:false;
6783     bool        stopping = eventIndex & kIOPMStatsEventStopFlag ? true:false;
6784     uint64_t    delta;
6785     uint64_t    nsec;
6786     OSData *publishPMStats = NULL;
6787 
6788     eventIndex &= ~(kIOPMStatsEventStartFlag | kIOPMStatsEventStopFlag);
6789 
6790     absolutetime_to_nanoseconds(timestamp, &nsec);
6791 
6792     switch (eventIndex) {
6793         case kIOPMStatsHibernateImageWrite:
6794             if (starting)
6795                 gPMStats.hibWrite.start = nsec;
6796             else if (stopping)
6797                 gPMStats.hibWrite.stop = nsec;
6798 
6799             if (stopping) {
6800                 delta = gPMStats.hibWrite.stop - gPMStats.hibWrite.start;
6801                 IOLog("PMStats: Hibernate write took %qd ms\n", delta/1000000ULL);
6802             }
6803             break;
6804         case kIOPMStatsHibernateImageRead:
6805             if (starting)
6806                 gPMStats.hibRead.start = nsec;
6807             else if (stopping)
6808                 gPMStats.hibRead.stop = nsec;
6809 
6810             if (stopping) {
6811                 delta = gPMStats.hibRead.stop - gPMStats.hibRead.start;
6812                 IOLog("PMStats: Hibernate read took %qd ms\n", delta/1000000ULL);
6813 
6814                 publishPMStats = OSData::withBytes(&gPMStats, sizeof(gPMStats));
6815                 setProperty(kIOPMSleepStatisticsKey, publishPMStats);
6816                 publishPMStats->release();
6817                 bzero(&gPMStats, sizeof(gPMStats));
6818             }
6819             break;
6820     }
6821 }
6822 
6823 /*
6824  * Appends a record of the application response to
6825  * IOPMrootDomain::pmStatsAppResponses
6826  */
6827 void IOPMrootDomain::pmStatsRecordApplicationResponse(
6828     const OSSymbol      *response,
6829     const char          *name,
6830     int                 messageType,
6831     uint32_t            delay_ms,
6832     int                 app_pid,
6833     OSObject            *object,
6834     IOPMPowerStateIndex powerState)
6835 {
6836     OSDictionary    *responseDescription    = NULL;
6837     OSNumber        *delayNum               = NULL;
6838     OSNumber        *powerCaps              = NULL;
6839     OSNumber        *pidNum                 = NULL;
6840     OSNumber        *msgNum                 = NULL;
6841     const OSSymbol  *appname;
6842     const OSSymbol  *sleep = NULL, *wake = NULL;
6843     IOPMServiceInterestNotifier *notify = 0;
6844 
6845     if (object && (notify = OSDynamicCast(IOPMServiceInterestNotifier, object)))
6846     {
6847         if (response->isEqualTo(gIOPMStatsApplicationResponseTimedOut))
6848             notify->ackTimeoutCnt++;
6849         else
6850             notify->ackTimeoutCnt = 0;
6851 
6852     }
6853 
6854     if (response->isEqualTo(gIOPMStatsApplicationResponsePrompt) ||
6855          (_systemTransitionType == kSystemTransitionNone) || (_systemTransitionType == kSystemTransitionNewCapClient))
6856         return;
6857 
6858 
6859     responseDescription = OSDictionary::withCapacity(5);
6860     if (responseDescription)
6861     {
6862         if (response) {
6863             responseDescription->setObject(_statsResponseTypeKey, response);
6864         }
6865 
6866         msgNum = OSNumber::withNumber(messageType, 32);
6867         if (msgNum) {
6868             responseDescription->setObject(_statsMessageTypeKey, msgNum);
6869             msgNum->release();
6870         }
6871 
6872         if (name && (strlen(name) > 0))
6873         {
6874             appname = OSSymbol::withCString(name);
6875             if (appname) {
6876                 responseDescription->setObject(_statsNameKey, appname);
6877                 appname->release();
6878             }
6879         }
6880 
6881         if (app_pid != -1) {
6882             pidNum = OSNumber::withNumber(app_pid, 32);
6883             if (pidNum) {
6884                 responseDescription->setObject(_statsPIDKey, pidNum);
6885                 pidNum->release();
6886             }
6887         }
6888 
6889         delayNum = OSNumber::withNumber(delay_ms, 32);
6890         if (delayNum) {
6891             responseDescription->setObject(_statsTimeMSKey, delayNum);
6892             delayNum->release();
6893         }
6894 
6895         if (response->isEqualTo(gIOPMStatsDriverPSChangeSlow)) {
6896             powerCaps = OSNumber::withNumber(powerState, 32);
6897 
6898 #if !defined(__i386__) && !defined(__x86_64__)
6899             IOLog("%s::powerStateChange type(%d) to(%lu) async took %d ms\n",
6900                   name, messageType,
6901                   powerState, delay_ms);
6902 #endif
6903 
6904         }
6905         else {
6906             powerCaps = OSNumber::withNumber(_pendingCapability, 32);
6907         }
6908         if (powerCaps) {
6909             responseDescription->setObject(_statsPowerCapsKey, powerCaps);
6910             powerCaps->release();
6911         }
6912 
6913         sleep = OSSymbol::withCString("Sleep");
6914         wake = OSSymbol::withCString("Wake");
6915         if (_systemTransitionType == kSystemTransitionSleep)  {
6916             responseDescription->setObject(kIOPMStatsSystemTransitionKey, sleep);
6917         }
6918         else if (_systemTransitionType == kSystemTransitionWake) {
6919             responseDescription->setObject(kIOPMStatsSystemTransitionKey, wake);
6920         }
6921         else if (_systemTransitionType == kSystemTransitionCapability) {
6922             if (CAP_LOSS(kIOPMSystemCapabilityGraphics))
6923                 responseDescription->setObject(kIOPMStatsSystemTransitionKey, sleep);
6924             else if (CAP_GAIN(kIOPMSystemCapabilityGraphics))
6925                 responseDescription->setObject(kIOPMStatsSystemTransitionKey, wake);
6926         }
6927         if (sleep) sleep->release();
6928         if (wake) wake->release();
6929 
6930 
6931 
6932         IOLockLock(pmStatsLock);
6933         if (pmStatsAppResponses && pmStatsAppResponses->getCount() < 50) {
6934             pmStatsAppResponses->setObject(responseDescription);
6935         }
6936         IOLockUnlock(pmStatsLock);
6937 
6938         responseDescription->release();
6939     }
6940 
6941     return;
6942 }
6943 
6944 // MARK: -
6945 // MARK: PMTraceWorker
6946 
6947 //******************************************************************************
6948 // TracePoint support
6949 //
6950 //******************************************************************************
6951 
6952 #define kIOPMRegisterNVRAMTracePointHandlerKey  \
6953         "IOPMRegisterNVRAMTracePointHandler"
6954 
6955 IOReturn IOPMrootDomain::callPlatformFunction(
6956     const OSSymbol * functionName,
6957     bool waitForFunction,
6958     void * param1, void * param2,
6959     void * param3, void * param4 )
6960 {
6961     if (pmTracer && functionName &&
6962         functionName->isEqualTo(kIOPMRegisterNVRAMTracePointHandlerKey) &&
6963         !pmTracer->tracePointHandler && !pmTracer->tracePointTarget)
6964     {
6965         uint32_t    tracePointPhases, tracePointPCI;
6966         uint64_t    statusCode;
6967 
6968         pmTracer->tracePointHandler = (IOPMTracePointHandler) param1;
6969         pmTracer->tracePointTarget  = (void *) param2;
6970         tracePointPCI               = (uint32_t)(uintptr_t) param3;
6971         tracePointPhases            = (uint32_t)(uintptr_t) param4;
6972         statusCode = (((uint64_t)tracePointPCI) << 32) | tracePointPhases;
6973         if ((tracePointPhases >> 24) != kIOPMTracePointSystemUp)
6974         {
6975             MSG("Sleep failure code 0x%08x 0x%08x\n",
6976                 tracePointPCI, tracePointPhases);
6977         }
6978         setProperty(kIOPMSleepWakeFailureCodeKey, statusCode, 64);
6979         pmTracer->tracePointHandler( pmTracer->tracePointTarget, 0, 0 );
6980 
6981         return kIOReturnSuccess;
6982     }
6983 #if HIBERNATION
6984     else if (functionName &&
6985              functionName->isEqualTo(kIOPMInstallSystemSleepPolicyHandlerKey))
6986     {
6987         if (gSleepPolicyHandler)
6988             return kIOReturnExclusiveAccess;
6989         if (!param1)
6990             return kIOReturnBadArgument;
6991         gSleepPolicyHandler = (IOPMSystemSleepPolicyHandler) param1;
6992         gSleepPolicyTarget  = (void *) param2;
6993         setProperty("IOPMSystemSleepPolicyHandler", kOSBooleanTrue);
6994         return kIOReturnSuccess;
6995     }
6996 #endif
6997 
6998     return super::callPlatformFunction(
6999         functionName, waitForFunction, param1, param2, param3, param4);
7000 }
7001 
7002 void IOPMrootDomain::tracePoint( uint8_t point )
7003 {
7004     if (systemBooting) return;
7005 
7006     if (kIOPMTracePointWakeCapabilityClients == point)
7007         acceptSystemWakeEvents(false);
7008 
7009     PMDebug(kPMLogSleepWakeTracePoint, point, 0);
7010     pmTracer->tracePoint(point);
7011 }
7012 
7013 void IOPMrootDomain::tracePoint( uint8_t point, uint8_t data )
7014 {
7015     if (systemBooting) return;
7016 
7017     PMDebug(kPMLogSleepWakeTracePoint, point, data);
7018     pmTracer->tracePoint(point, data);
7019 }
7020 
7021 void IOPMrootDomain::traceDetail( uint32_t detail )
7022 {
7023     if (!systemBooting)
7024         pmTracer->traceDetail( detail );
7025 }
7026 
7027 
7028 IOReturn IOPMrootDomain::configureReport(IOReportChannelList    *channelList,
7029                                     IOReportConfigureAction action,
7030                                     void                   *result,
7031                                     void                   *destination)
7032 {
7033     unsigned cnt;
7034     if (action != kIOReportGetDimensions) goto exit;
7035 
7036     for (cnt = 0; cnt < channelList->nchannels; cnt++) {
7037         if ( (channelList->channels[cnt].channel_id == kSleepCntChID) ||
7038                (channelList->channels[cnt].channel_id == kDarkWkCntChID) ||
7039                (channelList->channels[cnt].channel_id == kUserWkCntChID) ) {
7040             SIMPLEREPORT_UPDATERES(kIOReportGetDimensions, result);
7041         }
7042     }
7043 
7044 exit:
7045     return super::configureReport(channelList, action, result, destination);
7046 }
7047 
7048 
7049 IOReturn IOPMrootDomain::updateReport(IOReportChannelList      *channelList,
7050                                  IOReportUpdateAction      action,
7051                                  void                     *result,
7052                                  void                     *destination)
7053 {
7054     uint32_t size2cpy;
7055     void *data2cpy;
7056     uint8_t buf[SIMPLEREPORT_BUFSIZE];
7057     IOBufferMemoryDescriptor *dest = OSDynamicCast(IOBufferMemoryDescriptor, (OSObject *)destination);
7058     unsigned cnt;
7059     uint64_t ch_id;
7060 
7061     if (action != kIOReportCopyChannelData) goto exit;
7062 
7063     for (cnt = 0; cnt < channelList->nchannels; cnt++) {
7064         ch_id = channelList->channels[cnt].channel_id ;
7065 
7066         if ((ch_id == kSleepCntChID) ||
7067                 (ch_id == kDarkWkCntChID) || (ch_id == kUserWkCntChID)) {
7068             SIMPLEREPORT_INIT(buf, sizeof(buf), getRegistryEntryID(), ch_id, kIOReportCategoryPower);
7069         }
7070         else continue;
7071 
7072         if (ch_id == kSleepCntChID)
7073             SIMPLEREPORT_SETVALUE(buf, sleepCnt);
7074         else if (ch_id == kDarkWkCntChID)
7075             SIMPLEREPORT_SETVALUE(buf, darkWakeCnt);
7076         else if (ch_id == kUserWkCntChID)
7077             SIMPLEREPORT_SETVALUE(buf, displayWakeCnt);
7078 
7079         SIMPLEREPORT_UPDATEPREP(buf, data2cpy, size2cpy);
7080         SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData, result);
7081         dest->appendBytes(data2cpy, size2cpy);
7082     }
7083 
7084 exit:
7085     return super::updateReport(channelList, action, result, destination);
7086 }
7087 
7088 
7089 //******************************************************************************
7090 // PMTraceWorker Class
7091 //
7092 //******************************************************************************
7093 
7094 #undef super
7095 #define super OSObject
7096 OSDefineMetaClassAndStructors(PMTraceWorker, OSObject)
7097 
7098 #define kPMBestGuessPCIDevicesCount     25
7099 #define kPMMaxRTCBitfieldSize           32
7100 
7101 PMTraceWorker *PMTraceWorker::tracer(IOPMrootDomain *owner)
7102 {
7103     PMTraceWorker           *me;
7104 
7105     me = OSTypeAlloc( PMTraceWorker );
7106     if (!me || !me->init())
7107     {
7108         return NULL;
7109     }
7110 
7111     DLOG("PMTraceWorker %p\n", OBFUSCATE(me));
7112 
7113     // Note that we cannot instantiate the PCI device -> bit mappings here, since
7114     // the IODeviceTree has not yet been created by IOPlatformExpert. We create
7115     // this dictionary lazily.
7116     me->owner = owner;
7117     me->pciDeviceBitMappings = NULL;
7118     me->pciMappingLock = IOLockAlloc();
7119     me->tracePhase = kIOPMTracePointSystemUp;
7120     me->loginWindowPhase = 0;
7121     me->traceData32 = 0;
7122     return me;
7123 }
7124 
7125 void PMTraceWorker::RTC_TRACE(void)
7126 {
7127     if (tracePointHandler && tracePointTarget)
7128     {
7129         uint32_t    wordA;
7130 
7131         wordA = (tracePhase << 24) | (loginWindowPhase << 16) |
7132                 (traceData8 << 8);
7133 
7134         tracePointHandler( tracePointTarget, traceData32, wordA );
7135         _LOG("RTC_TRACE wrote 0x%08x 0x%08x\n", traceData32, wordA);
7136     }
7137 }
7138 
7139 int PMTraceWorker::recordTopLevelPCIDevice(IOService * pciDevice)
7140 {
7141     const OSSymbol *    deviceName;
7142     int                 index = -1;
7143 
7144     IOLockLock(pciMappingLock);
7145 
7146     if (!pciDeviceBitMappings)
7147     {
7148         pciDeviceBitMappings = OSArray::withCapacity(kPMBestGuessPCIDevicesCount);
7149         if (!pciDeviceBitMappings)
7150             goto exit;
7151     }
7152 
7153     // Check for bitmask overflow.
7154     if (pciDeviceBitMappings->getCount() >= kPMMaxRTCBitfieldSize)
7155         goto exit;
7156 
7157     if ((deviceName = pciDevice->copyName()) &&
7158         (pciDeviceBitMappings->getNextIndexOfObject(deviceName, 0) == (unsigned int)-1) &&
7159         pciDeviceBitMappings->setObject(deviceName))
7160     {
7161         index = pciDeviceBitMappings->getCount() - 1;
7162         _LOG("PMTrace PCI array: set object %s => %d\n",
7163             deviceName->getCStringNoCopy(), index);
7164     }
7165     if (deviceName)
7166         deviceName->release();
7167     if (!addedToRegistry && (index >= 0))
7168         addedToRegistry = owner->setProperty("PCITopLevel", this);
7169 
7170 exit:
7171     IOLockUnlock(pciMappingLock);
7172     return index;
7173 }
7174 
7175 bool PMTraceWorker::serialize(OSSerialize *s) const
7176 {
7177     bool ok = false;
7178     if (pciDeviceBitMappings)
7179     {
7180         IOLockLock(pciMappingLock);
7181         ok = pciDeviceBitMappings->serialize(s);
7182         IOLockUnlock(pciMappingLock);
7183     }
7184     return ok;
7185 }
7186 
7187 void PMTraceWorker::tracePoint(uint8_t phase)
7188 {
7189     // clear trace detail when phase begins
7190     if (tracePhase != phase)
7191         traceData32 = 0;
7192 
7193     tracePhase = phase;
7194 
7195     DLOG("trace point 0x%02x\n", tracePhase);
7196     RTC_TRACE();
7197 }
7198 
7199 void PMTraceWorker::tracePoint(uint8_t phase, uint8_t data8)
7200 {
7201     // clear trace detail when phase begins
7202     if (tracePhase != phase)
7203         traceData32 = 0;
7204 
7205     tracePhase = phase;
7206     traceData8 = data8;
7207 
7208     DLOG("trace point 0x%02x 0x%02x\n", tracePhase, traceData8);
7209     RTC_TRACE();
7210 }
7211 
7212 void PMTraceWorker::traceDetail(uint32_t detail)
7213 {
7214     if (kIOPMTracePointSleepPriorityClients != tracePhase)
7215         return;
7216 
7217     traceData32 = detail;
7218     DLOG("trace point 0x%02x detail 0x%08x\n", tracePhase, traceData32);
7219 
7220     RTC_TRACE();
7221 }
7222 
7223 void PMTraceWorker::traceLoginWindowPhase(uint8_t phase)
7224 {
7225     loginWindowPhase = phase;
7226 
7227     DLOG("loginwindow tracepoint 0x%02x\n", loginWindowPhase);
7228     RTC_TRACE();
7229 }
7230 
7231 void PMTraceWorker::tracePCIPowerChange(
7232     change_t type, IOService *service, uint32_t changeFlags, uint32_t bitNum)
7233 {
7234     uint32_t    bitMask;
7235     uint32_t    expectedFlag;
7236 
7237     // Ignore PCI changes outside of system sleep/wake.
7238     if ((kIOPMTracePointSleepPowerPlaneDrivers != tracePhase) &&
7239         (kIOPMTracePointWakePowerPlaneDrivers  != tracePhase))
7240         return;
7241 
7242     // Only record the WillChange transition when going to sleep,
7243     // and the DidChange on the way up.
7244     changeFlags &= (kIOPMDomainWillChange | kIOPMDomainDidChange);
7245     expectedFlag = (kIOPMTracePointSleepPowerPlaneDrivers == tracePhase) ?
7246                     kIOPMDomainWillChange : kIOPMDomainDidChange;
7247     if (changeFlags != expectedFlag)
7248         return;
7249 
7250     // Mark this device off in our bitfield
7251     if (bitNum < kPMMaxRTCBitfieldSize)
7252     {
7253         bitMask = (1 << bitNum);
7254 
7255         if (kPowerChangeStart == type)
7256         {
7257             traceData32 |= bitMask;
7258             _LOG("PMTrace: Device %s started  - bit %2d mask 0x%08x => 0x%08x\n",
7259                 service->getName(), bitNum, bitMask, traceData32);
7260         }
7261         else
7262         {
7263             traceData32 &= ~bitMask;
7264             _LOG("PMTrace: Device %s finished - bit %2d mask 0x%08x => 0x%08x\n",
7265                 service->getName(), bitNum, bitMask, traceData32);
7266         }
7267 
7268         DLOG("trace point 0x%02x detail 0x%08x\n", tracePhase, traceData32);
7269         RTC_TRACE();
7270     }
7271 }
7272 
7273 uint64_t  PMTraceWorker::getPMStatusCode( )
7274 {
7275     return (((uint64_t)traceData32 << 32) | (tracePhase << 24) |
7276             (loginWindowPhase << 16) | (traceData8 << 8));
7277 
7278 }
7279 
7280 // MARK: -
7281 // MARK: PMHaltWorker
7282 
7283 //******************************************************************************
7284 // PMHaltWorker Class
7285 //
7286 //******************************************************************************
7287 
7288 static unsigned int     gPMHaltBusyCount;
7289 static unsigned int     gPMHaltIdleCount;
7290 static int              gPMHaltDepth;
7291 static unsigned long    gPMHaltEvent;
7292 static IOLock *         gPMHaltLock  = 0;
7293 static OSArray *        gPMHaltArray = 0;
7294 static const OSSymbol * gPMHaltClientAcknowledgeKey = 0;
7295 
7296 PMHaltWorker * PMHaltWorker::worker( void )
7297 {
7298     PMHaltWorker *  me;
7299     IOThread        thread;
7300 
7301     do {
7302         me = OSTypeAlloc( PMHaltWorker );
7303         if (!me || !me->init())
7304             break;
7305 
7306         me->lock = IOLockAlloc();
7307         if (!me->lock)
7308             break;
7309 
7310         DLOG("PMHaltWorker %p\n", OBFUSCATE(me));
7311         me->retain();   // thread holds extra retain
7312         if (KERN_SUCCESS != kernel_thread_start(&PMHaltWorker::main, (void *) me, &thread))
7313         {
7314             me->release();
7315             break;
7316         }
7317         thread_deallocate(thread);
7318         return me;
7319 
7320     } while (false);
7321 
7322     if (me) me->release();
7323     return 0;
7324 }
7325 
7326 void PMHaltWorker::free( void )
7327 {
7328     DLOG("PMHaltWorker free %p\n", OBFUSCATE(this));
7329     if (lock)
7330     {
7331         IOLockFree(lock);
7332         lock = 0;
7333     }
7334     return OSObject::free();
7335 }
7336 
7337 void PMHaltWorker::main( void * arg, wait_result_t waitResult )
7338 {
7339     PMHaltWorker * me = (PMHaltWorker *) arg;
7340 
7341     IOLockLock( gPMHaltLock );
7342     gPMHaltBusyCount++;
7343     me->depth = gPMHaltDepth;
7344     IOLockUnlock( gPMHaltLock );
7345 
7346     while (me->depth >= 0)
7347     {
7348         PMHaltWorker::work( me );
7349 
7350         IOLockLock( gPMHaltLock );
7351         if (++gPMHaltIdleCount >= gPMHaltBusyCount)
7352         {
7353             // This is the last thread to finish work on this level,
7354             // inform everyone to start working on next lower level.
7355             gPMHaltDepth--;
7356             me->depth = gPMHaltDepth;
7357             gPMHaltIdleCount = 0;
7358             thread_wakeup((event_t) &gPMHaltIdleCount);
7359         }
7360         else
7361         {
7362             // One or more threads are still working on this level,
7363             // this thread must wait.
7364             me->depth = gPMHaltDepth - 1;
7365             do {
7366                 IOLockSleep(gPMHaltLock, &gPMHaltIdleCount, THREAD_UNINT);
7367             } while (me->depth != gPMHaltDepth);
7368         }
7369         IOLockUnlock( gPMHaltLock );
7370     }
7371 
7372     // No more work to do, terminate thread
7373     DLOG("All done for worker: %p (visits = %u)\n", OBFUSCATE(me), me->visits);
7374     thread_wakeup( &gPMHaltDepth );
7375     me->release();
7376 }
7377 
7378 void PMHaltWorker::work( PMHaltWorker * me )
7379 {
7380     IOService *     service;
7381     OSSet *         inner;
7382     AbsoluteTime    startTime;
7383     UInt32          deltaTime;
7384     bool            timeout;
7385 
7386     while (true)
7387     {
7388         service = 0;
7389         timeout = false;
7390 
7391         // Claim an unit of work from the shared pool
7392         IOLockLock( gPMHaltLock );
7393         inner = (OSSet *)gPMHaltArray->getObject(me->depth);
7394         if (inner)
7395         {
7396             service = (IOService *)inner->getAnyObject();
7397             if (service)
7398             {
7399                 service->retain();
7400                 inner->removeObject(service);
7401             }
7402         }
7403         IOLockUnlock( gPMHaltLock );
7404         if (!service)
7405             break;  // no more work at this depth
7406 
7407         clock_get_uptime(&startTime);
7408 
7409         if (!service->isInactive() &&
7410             service->setProperty(gPMHaltClientAcknowledgeKey, me))
7411         {
7412             IOLockLock(me->lock);
7413             me->startTime = startTime;
7414             me->service   = service;
7415             me->timeout   = false;
7416             IOLockUnlock(me->lock);
7417 
7418             service->systemWillShutdown( gPMHaltEvent );
7419 
7420             // Wait for driver acknowledgement
7421             IOLockLock(me->lock);
7422             while (service->getProperty(gPMHaltClientAcknowledgeKey))
7423             {
7424                 IOLockSleep(me->lock, me, THREAD_UNINT);
7425             }
7426             me->service = 0;
7427             timeout = me->timeout;
7428             IOLockUnlock(me->lock);
7429         }
7430 
7431         deltaTime = computeDeltaTimeMS(&startTime);
7432         if ((deltaTime > kPMHaltTimeoutMS) || timeout ||
7433             (gIOKitDebug & kIOLogPMRootDomain))
7434         {
7435             LOG("%s driver %s (%p) took %u ms\n",
7436                 (gPMHaltEvent == kIOMessageSystemWillPowerOff) ?
7437                     "PowerOff" : "Restart",
7438                 service->getName(), OBFUSCATE(service),
7439                 (uint32_t) deltaTime );
7440         }
7441 
7442         service->release();
7443         me->visits++;
7444     }
7445 }
7446 
7447 void PMHaltWorker::checkTimeout( PMHaltWorker * me, AbsoluteTime * now )
7448 {
7449     UInt64          nano;
7450     AbsoluteTime    startTime;
7451     AbsoluteTime    endTime;
7452 
7453     endTime = *now;
7454 
7455     IOLockLock(me->lock);
7456     if (me->service && !me->timeout)
7457     {
7458         startTime = me->startTime;
7459         nano = 0;
7460         if (CMP_ABSOLUTETIME(&endTime, &startTime) > 0)
7461         {
7462             SUB_ABSOLUTETIME(&endTime, &startTime);
7463             absolutetime_to_nanoseconds(endTime, &nano);
7464         }
7465         if (nano > 3000000000ULL)
7466         {
7467             me->timeout = true;
7468             MSG("%s still waiting on %s\n",
7469                 (gPMHaltEvent == kIOMessageSystemWillPowerOff) ?
7470                     "PowerOff" : "Restart",
7471                 me->service->getName());
7472         }
7473     }
7474     IOLockUnlock(me->lock);
7475 }
7476 
7477 
7478 //******************************************************************************
7479 // acknowledgeSystemWillShutdown
7480 //
7481 // Acknowledgement from drivers that they have prepared for shutdown/restart.
7482 //******************************************************************************
7483 
7484 void IOPMrootDomain::acknowledgeSystemWillShutdown( IOService * from )
7485 {
7486     PMHaltWorker *  worker;
7487     OSObject *      prop;
7488 
7489     if (!from)
7490         return;
7491 
7492     //DLOG("%s acknowledged\n", from->getName());
7493     prop = from->copyProperty( gPMHaltClientAcknowledgeKey );
7494     if (prop)
7495     {
7496         worker = (PMHaltWorker *) prop;
7497         IOLockLock(worker->lock);
7498         from->removeProperty( gPMHaltClientAcknowledgeKey );
7499         thread_wakeup((event_t) worker);
7500         IOLockUnlock(worker->lock);
7501         worker->release();
7502     }
7503     else
7504     {
7505         DLOG("%s acknowledged without worker property\n",
7506             from->getName());
7507     }
7508 }
7509 
7510 
7511 //******************************************************************************
7512 // notifySystemShutdown
7513 //
7514 // Notify all objects in PM tree that system will shutdown or restart
7515 //******************************************************************************
7516 
7517 static void
7518 notifySystemShutdown( IOService * root, unsigned long event )
7519 {
7520 #define PLACEHOLDER ((OSSet *)gPMHaltArray)
7521     IORegistryIterator *    iter;
7522     IORegistryEntry *       entry;
7523     IOService *             node;
7524     OSSet *                 inner;
7525     PMHaltWorker *          workers[kPMHaltMaxWorkers];
7526     AbsoluteTime            deadline;
7527     unsigned int            totalNodes = 0;
7528     unsigned int            depth;
7529     unsigned int            rootDepth;
7530     unsigned int            numWorkers;
7531     unsigned int            count;
7532     int                     waitResult;
7533     void *                  baseFunc;
7534     bool                    ok;
7535 
7536     DLOG("%s event = %lx\n", __FUNCTION__, event);
7537 
7538     baseFunc = OSMemberFunctionCast(void *, root, &IOService::systemWillShutdown);
7539 
7540     // Iterate the entire PM tree starting from root
7541 
7542     rootDepth = root->getDepth( gIOPowerPlane );
7543     if (!rootDepth) goto done;
7544 
7545     // debug - for repeated test runs
7546     while (PMHaltWorker::metaClass->getInstanceCount())
7547         IOSleep(1);
7548 
7549     if (!gPMHaltArray)
7550     {
7551         gPMHaltArray = OSArray::withCapacity(40);
7552         if (!gPMHaltArray) goto done;
7553     }
7554     else // debug
7555         gPMHaltArray->flushCollection();
7556 
7557     if (!gPMHaltLock)
7558     {
7559         gPMHaltLock = IOLockAlloc();
7560         if (!gPMHaltLock) goto done;
7561     }
7562 
7563     if (!gPMHaltClientAcknowledgeKey)
7564     {
7565         gPMHaltClientAcknowledgeKey =
7566             OSSymbol::withCStringNoCopy("PMShutdown");
7567         if (!gPMHaltClientAcknowledgeKey) goto done;
7568     }
7569 
7570     gPMHaltEvent = event;
7571 
7572     // Depth-first walk of PM plane
7573 
7574     iter = IORegistryIterator::iterateOver(
7575         root, gIOPowerPlane, kIORegistryIterateRecursively);
7576 
7577     if (iter)
7578     {
7579         while ((entry = iter->getNextObject()))
7580         {
7581             node = OSDynamicCast(IOService, entry);
7582             if (!node)
7583                 continue;
7584 
7585             if (baseFunc ==
7586                 OSMemberFunctionCast(void *, node, &IOService::systemWillShutdown))
7587                 continue;
7588 
7589             depth = node->getDepth( gIOPowerPlane );
7590             if (depth <= rootDepth)
7591                 continue;
7592 
7593             ok = false;
7594 
7595             // adjust to zero based depth
7596             depth -= (rootDepth + 1);
7597 
7598             // gPMHaltArray is an array of containers, each container
7599             // refers to nodes with the same depth.
7600 
7601             count = gPMHaltArray->getCount();
7602             while (depth >= count)
7603             {
7604                 // expand array and insert placeholders
7605                 gPMHaltArray->setObject(PLACEHOLDER);
7606                 count++;
7607             }
7608             count = gPMHaltArray->getCount();
7609             if (depth < count)
7610             {
7611                 inner = (OSSet *)gPMHaltArray->getObject(depth);
7612                 if (inner == PLACEHOLDER)
7613                 {
7614                     inner = OSSet::withCapacity(40);
7615                     if (inner)
7616                     {
7617                         gPMHaltArray->replaceObject(depth, inner);
7618                         inner->release();
7619                     }
7620                 }
7621 
7622                 // PM nodes that appear more than once in the tree will have
7623                 // the same depth, OSSet will refuse to add the node twice.
7624                 if (inner)
7625                     ok = inner->setObject(node);
7626             }
7627             if (!ok)
7628                 DLOG("Skipped PM node %s\n", node->getName());
7629         }
7630         iter->release();
7631     }
7632 
7633     // debug only
7634     for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i)); i++)
7635     {
7636         count = 0;
7637         if (inner != PLACEHOLDER)
7638             count = inner->getCount();
7639         DLOG("Nodes at depth %u = %u\n", i, count);
7640     }
7641 
7642     // strip placeholders (not all depths are populated)
7643     numWorkers = 0;
7644     for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i)); )
7645     {
7646         if (inner == PLACEHOLDER)
7647         {
7648             gPMHaltArray->removeObject(i);
7649             continue;
7650         }
7651         count = inner->getCount();
7652         if (count > numWorkers)
7653             numWorkers = count;
7654         totalNodes += count;
7655         i++;
7656     }
7657 
7658     if (gPMHaltArray->getCount() == 0 || !numWorkers)
7659         goto done;
7660 
7661     gPMHaltBusyCount = 0;
7662     gPMHaltIdleCount = 0;
7663     gPMHaltDepth = gPMHaltArray->getCount() - 1;
7664 
7665     // Create multiple workers (and threads)
7666 
7667     if (numWorkers > kPMHaltMaxWorkers)
7668         numWorkers = kPMHaltMaxWorkers;
7669 
7670     DLOG("PM nodes %u, maxDepth %u, workers %u\n",
7671         totalNodes, gPMHaltArray->getCount(), numWorkers);
7672 
7673     for (unsigned int i = 0; i < numWorkers; i++)
7674         workers[i] = PMHaltWorker::worker();
7675 
7676     // Wait for workers to exhaust all available work
7677 
7678     IOLockLock(gPMHaltLock);
7679     while (gPMHaltDepth >= 0)
7680     {
7681         clock_interval_to_deadline(1000, kMillisecondScale, &deadline);
7682 
7683         waitResult = IOLockSleepDeadline(
7684             gPMHaltLock, &gPMHaltDepth, deadline, THREAD_UNINT);
7685         if (THREAD_TIMED_OUT == waitResult)
7686         {
7687             AbsoluteTime now;
7688             clock_get_uptime(&now);
7689 
7690             IOLockUnlock(gPMHaltLock);
7691             for (unsigned int i = 0 ; i < numWorkers; i++)
7692             {
7693                 if (workers[i])
7694                     PMHaltWorker::checkTimeout(workers[i], &now);
7695             }
7696             IOLockLock(gPMHaltLock);
7697         }
7698     }
7699     IOLockUnlock(gPMHaltLock);
7700 
7701     // Release all workers
7702 
7703     for (unsigned int i = 0; i < numWorkers; i++)
7704     {
7705         if (workers[i])
7706             workers[i]->release();
7707         // worker also retained by it's own thread
7708     }
7709 
7710 done:
7711     DLOG("%s done\n", __FUNCTION__);
7712     return;
7713 }
7714 
7715 // MARK: -
7716 // MARK: Kernel Assertion
7717 
7718 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
7719 
7720 IOPMDriverAssertionID IOPMrootDomain::createPMAssertion(
7721     IOPMDriverAssertionType whichAssertionBits,
7722     IOPMDriverAssertionLevel assertionLevel,
7723     IOService *ownerService,
7724     const char *ownerDescription)
7725 {
7726     IOReturn            ret;
7727     IOPMDriverAssertionID     newAssertion;
7728 
7729     if (!pmAssertions)
7730         return 0;
7731 
7732     ret = pmAssertions->createAssertion(whichAssertionBits, assertionLevel, ownerService, ownerDescription, &newAssertion);
7733 
7734     if (kIOReturnSuccess == ret)
7735         return newAssertion;
7736     else
7737         return 0;
7738 }
7739 
7740 IOReturn IOPMrootDomain::releasePMAssertion(IOPMDriverAssertionID releaseAssertion)
7741 {
7742     if (!pmAssertions)
7743         return kIOReturnInternalError;
7744 
7745     return pmAssertions->releaseAssertion(releaseAssertion);
7746 }
7747 
7748 
7749 IOReturn IOPMrootDomain::setPMAssertionLevel(
7750     IOPMDriverAssertionID assertionID,
7751     IOPMDriverAssertionLevel assertionLevel)
7752 {
7753     return pmAssertions->setAssertionLevel(assertionID, assertionLevel);
7754 }
7755 
7756 IOPMDriverAssertionLevel IOPMrootDomain::getPMAssertionLevel(IOPMDriverAssertionType whichAssertion)
7757 {
7758     IOPMDriverAssertionType       sysLevels;
7759 
7760     if (!pmAssertions || whichAssertion == 0)
7761         return kIOPMDriverAssertionLevelOff;
7762 
7763     sysLevels = pmAssertions->getActivatedAssertions();
7764 
7765     // Check that every bit set in argument 'whichAssertion' is asserted
7766     // in the aggregate bits.
7767     if ((sysLevels & whichAssertion) == whichAssertion)
7768         return kIOPMDriverAssertionLevelOn;
7769     else
7770         return kIOPMDriverAssertionLevelOff;
7771 }
7772 
7773 IOReturn IOPMrootDomain::setPMAssertionUserLevels(IOPMDriverAssertionType inLevels)
7774 {
7775     if (!pmAssertions)
7776         return kIOReturnNotFound;
7777 
7778     return pmAssertions->setUserAssertionLevels(inLevels);
7779 }
7780 
7781 bool IOPMrootDomain::serializeProperties( OSSerialize * s ) const
7782 {
7783     if (pmAssertions)
7784     {
7785         pmAssertions->publishProperties();
7786     }
7787     return( IOService::serializeProperties(s) );
7788 }
7789 
7790 OSObject * IOPMrootDomain::copyProperty( const char * aKey) const
7791 {
7792     OSObject *obj = NULL;
7793     obj = IOService::copyProperty(aKey);
7794 
7795     if (obj)  return obj;
7796 
7797     if (!strncmp(aKey, kIOPMSleepWakeWdogRebootKey,
7798                         sizeof(kIOPMSleepWakeWdogRebootKey))) {
7799         if (swd_flags & SWD_BOOT_BY_SW_WDOG)
7800             return OSBoolean::withBoolean(true);
7801         else
7802             return OSBoolean::withBoolean(false);
7803 
7804     }
7805 
7806     if (!strncmp(aKey, kIOPMSleepWakeWdogLogsValidKey,
7807                         sizeof(kIOPMSleepWakeWdogLogsValidKey))) {
7808         if (swd_flags & SWD_VALID_LOGS)
7809             return OSBoolean::withBoolean(true);
7810         else
7811             return OSBoolean::withBoolean(false);
7812 
7813     }
7814 
7815     /*
7816      * XXX: We should get rid of "DesktopMode" property  when 'kAppleClamshellCausesSleepKey'
7817      * is set properly in darwake from sleep. For that, kIOPMEnableClamshell msg has to be
7818      * issued by DisplayWrangler on darkwake.
7819      */
7820     if (!strcmp(aKey, "DesktopMode")) {
7821         if (desktopMode)
7822             return OSBoolean::withBoolean(true);
7823         else
7824             return OSBoolean::withBoolean(false);
7825     }
7826     if (!strcmp(aKey, "DisplayIdleForDemandSleep")) {
7827         if (displayIdleForDemandSleep) {
7828             return OSBoolean::withBoolean(true);
7829         }
7830         else  {
7831             return OSBoolean::withBoolean(false);
7832         }
7833     }
7834 
7835     if (!strcmp(aKey, kIOPMDriverWakeEventsKey))
7836     {
7837         OSArray * array = 0;
7838         WAKEEVENT_LOCK();
7839         if (_systemWakeEventsArray && _systemWakeEventsArray->getCount())
7840             array = OSArray::withArray(_systemWakeEventsArray);
7841         WAKEEVENT_UNLOCK();
7842         return array;
7843     }
7844 
7845     if (!strcmp(aKey, kIOPMSleepStatisticsAppsKey))
7846     {
7847         OSArray * array = 0;
7848         IOLockLock(pmStatsLock);
7849         if (pmStatsAppResponses && pmStatsAppResponses->getCount()) {
7850             array = OSArray::withArray(pmStatsAppResponses);
7851             pmStatsAppResponses->flushCollection();
7852         }
7853         IOLockUnlock(pmStatsLock);
7854         return array;
7855     }
7856 
7857     return NULL;
7858 }
7859 
7860 // MARK: -
7861 // MARK: Wake Event Reporting
7862 
7863 void IOPMrootDomain::copyWakeReasonString( char * outBuf, size_t bufSize )
7864 {
7865     WAKEEVENT_LOCK();
7866     strlcpy(outBuf, gWakeReasonString, bufSize);
7867     WAKEEVENT_UNLOCK();
7868 }
7869 
7870 //******************************************************************************
7871 // acceptSystemWakeEvents
7872 //
7873 // Private control for the acceptance of driver wake event claims.
7874 //******************************************************************************
7875 
7876 void IOPMrootDomain::acceptSystemWakeEvents( bool accept )
7877 {
7878     bool logWakeReason = false;
7879 
7880     WAKEEVENT_LOCK();
7881     if (accept)
7882     {
7883         gWakeReasonString[0] = '\0';
7884         if (!_systemWakeEventsArray)
7885             _systemWakeEventsArray = OSArray::withCapacity(4);
7886         if ((_acceptSystemWakeEvents = (_systemWakeEventsArray != 0)))
7887             _systemWakeEventsArray->flushCollection();
7888     }
7889     else
7890     {
7891         _acceptSystemWakeEvents = false;
7892     }
7893     WAKEEVENT_UNLOCK();
7894 
7895     if (logWakeReason)
7896         MSG("system wake events:%s\n", gWakeReasonString);
7897 }
7898 
7899 //******************************************************************************
7900 // claimSystemWakeEvent
7901 //
7902 // For a driver to claim a device is the source/conduit of a system wake event.
7903 //******************************************************************************
7904 
7905 void IOPMrootDomain::claimSystemWakeEvent(
7906     IOService *     device,
7907     IOOptionBits    flags,
7908     const char *    reason,
7909     OSObject *      details )
7910 {
7911     const OSSymbol *    deviceName   = 0;
7912     OSNumber *          deviceRegId  = 0;
7913     OSNumber *          claimTime    = 0;
7914     OSData *            flagsData    = 0;
7915     OSString *          reasonString = 0;
7916     OSDictionary *      d = 0;
7917     uint64_t            timestamp;
7918     bool                ok = false;
7919 
7920     pmEventTimeStamp(&timestamp);
7921 
7922     if (!device || !reason) return;
7923 
7924     deviceName   = device->copyName(gIOServicePlane);
7925     deviceRegId  = OSNumber::withNumber(device->getRegistryEntryID(), 64);
7926     claimTime    = OSNumber::withNumber(timestamp, 64);
7927     flagsData    = OSData::withBytes(&flags, sizeof(flags));
7928     reasonString = OSString::withCString(reason);
7929     d = OSDictionary::withCapacity(5 + (details ? 1 : 0));
7930     if (!deviceName || !deviceRegId || !claimTime || !flagsData || !reasonString)
7931         goto done;
7932 
7933     d->setObject(gIONameKey, deviceName);
7934     d->setObject(gIORegistryEntryIDKey, deviceRegId);
7935     d->setObject(kIOPMWakeEventTimeKey, claimTime);
7936     d->setObject(kIOPMWakeEventFlagsKey, flagsData);
7937     d->setObject(kIOPMWakeEventReasonKey, reasonString);
7938     if (details)
7939         d->setObject(kIOPMWakeEventDetailsKey, details);
7940 
7941     WAKEEVENT_LOCK();
7942     if (!gWakeReasonSysctlRegistered)
7943     {
7944         // Lazy registration until the platform driver stops registering
7945         // the same name.
7946         gWakeReasonSysctlRegistered = true;
7947     }
7948     if (_acceptSystemWakeEvents)
7949     {
7950         ok = _systemWakeEventsArray->setObject(d);
7951         if (gWakeReasonString[0] != '\0')
7952             strlcat(gWakeReasonString, " ", sizeof(gWakeReasonString));
7953         strlcat(gWakeReasonString, reason, sizeof(gWakeReasonString));
7954     }
7955     WAKEEVENT_UNLOCK();
7956 
7957 done:
7958     if (deviceName)   deviceName->release();
7959     if (deviceRegId)  deviceRegId->release();
7960     if (claimTime)    claimTime->release();
7961     if (flagsData)    flagsData->release();
7962     if (reasonString) reasonString->release();
7963     if (d) d->release();
7964 }
7965 
7966 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
7967 
7968 // MARK: -
7969 // MARK: PMSettingHandle
7970 
7971 OSDefineMetaClassAndStructors( PMSettingHandle, OSObject )
7972 
7973 void PMSettingHandle::free( void )
7974 {
7975     if (pmso)
7976     {
7977         pmso->clientHandleFreed();
7978         pmso->release();
7979         pmso = 0;
7980     }
7981 
7982     OSObject::free();
7983 }
7984 
7985 // MARK: -
7986 // MARK: PMSettingObject
7987 
7988 #undef super
7989 #define super OSObject
7990 OSDefineMetaClassAndFinalStructors( PMSettingObject, OSObject )
7991 
7992 /*
7993  * Static constructor/initializer for PMSettingObject
7994  */
7995 PMSettingObject *PMSettingObject::pmSettingObject(
7996     IOPMrootDomain                      *parent_arg,
7997     IOPMSettingControllerCallback       handler_arg,
7998     OSObject                            *target_arg,
7999     uintptr_t                           refcon_arg,
8000     uint32_t                            supportedPowerSources,
8001     const OSSymbol *                    settings[],
8002     OSObject                            **handle_obj)
8003 {
8004     uint32_t                            settingCount = 0;
8005     PMSettingObject                     *pmso = 0;
8006     PMSettingHandle                     *pmsh = 0;
8007 
8008     if ( !parent_arg || !handler_arg || !settings || !handle_obj )
8009         return NULL;
8010 
8011     // count OSSymbol entries in NULL terminated settings array
8012     while (settings[settingCount]) {
8013         settingCount++;
8014     }
8015     if (0 == settingCount)
8016         return NULL;
8017 
8018     pmso = new PMSettingObject;
8019     if (!pmso || !pmso->init())
8020         goto fail;
8021 
8022     pmsh = new PMSettingHandle;
8023     if (!pmsh || !pmsh->init())
8024         goto fail;
8025 
8026     queue_init(&pmso->calloutQueue);
8027     pmso->parent       = parent_arg;
8028     pmso->func         = handler_arg;
8029     pmso->target       = target_arg;
8030     pmso->refcon       = refcon_arg;
8031     pmso->settingCount = settingCount;
8032 
8033     pmso->retain();     // handle holds a retain on pmso
8034     pmsh->pmso = pmso;
8035     pmso->pmsh = pmsh;
8036 
8037     pmso->publishedFeatureID = (uint32_t *)IOMalloc(sizeof(uint32_t)*settingCount);
8038     if (pmso->publishedFeatureID) {
8039         for (unsigned int i=0; i<settingCount; i++) {
8040             // Since there is now at least one listener to this setting, publish
8041             // PM root domain support for it.
8042             parent_arg->publishPMSetting( settings[i],
8043                     supportedPowerSources, &pmso->publishedFeatureID[i] );
8044         }
8045     }
8046 
8047     *handle_obj = pmsh;
8048     return pmso;
8049 
8050 fail:
8051     if (pmso) pmso->release();
8052     if (pmsh) pmsh->release();
8053     return NULL;
8054 }
8055 
8056 void PMSettingObject::free( void )
8057 {
8058     if (publishedFeatureID) {
8059         for (uint32_t i=0; i<settingCount; i++) {
8060             if (publishedFeatureID[i]) {
8061                 parent->removePublishedFeature( publishedFeatureID[i] );
8062             }
8063         }
8064 
8065         IOFree(publishedFeatureID, sizeof(uint32_t) * settingCount);
8066     }
8067 
8068     super::free();
8069 }
8070 
8071 void PMSettingObject::dispatchPMSetting( const OSSymbol * type, OSObject * object )
8072 {
8073     (*func)(target, type, object, refcon);
8074 }
8075 
8076 void PMSettingObject::clientHandleFreed( void )
8077 {
8078     parent->deregisterPMSettingObject(this);
8079 }
8080 
8081 // MARK: -
8082 // MARK: PMAssertionsTracker
8083 
8084 //*********************************************************************************
8085 //*********************************************************************************
8086 //*********************************************************************************
8087 // class PMAssertionsTracker Implementation
8088 
8089 #define kAssertUniqueIDStart    500
8090 
8091 PMAssertionsTracker *PMAssertionsTracker::pmAssertionsTracker( IOPMrootDomain *rootDomain )
8092 {
8093     PMAssertionsTracker    *myself;
8094 
8095     myself = new PMAssertionsTracker;
8096 
8097     if (myself) {
8098         myself->init();
8099         myself->owner = rootDomain;
8100         myself->issuingUniqueID = kAssertUniqueIDStart;
8101         myself->assertionsArray = OSArray::withCapacity(5);
8102         myself->assertionsKernel = 0;
8103         myself->assertionsUser = 0;
8104         myself->assertionsCombined = 0;
8105         myself->assertionsArrayLock = IOLockAlloc();
8106         myself->tabulateProducerCount = myself->tabulateConsumerCount = 0;
8107 
8108         if (!myself->assertionsArray || !myself->assertionsArrayLock)
8109             myself = NULL;
8110     }
8111 
8112     return myself;
8113 }
8114 
8115 /* tabulate
8116  * - Update assertionsKernel to reflect the state of all
8117  * assertions in the kernel.
8118  * - Update assertionsCombined to reflect both kernel & user space.
8119  */
8120 void PMAssertionsTracker::tabulate(void)
8121 {
8122     int i;
8123     int count;
8124     PMAssertStruct      *_a = NULL;
8125     OSData              *_d = NULL;
8126 
8127     IOPMDriverAssertionType oldKernel = assertionsKernel;
8128     IOPMDriverAssertionType oldCombined = assertionsCombined;
8129 
8130     ASSERT_GATED();
8131 
8132     assertionsKernel = 0;
8133     assertionsCombined = 0;
8134 
8135     if (!assertionsArray)
8136         return;
8137 
8138     if ((count = assertionsArray->getCount()))
8139     {
8140         for (i=0; i<count; i++)
8141         {
8142             _d = OSDynamicCast(OSData, assertionsArray->getObject(i));
8143             if (_d)
8144             {
8145                 _a = (PMAssertStruct *)_d->getBytesNoCopy();
8146                 if (_a && (kIOPMDriverAssertionLevelOn == _a->level))
8147                     assertionsKernel |= _a->assertionBits;
8148             }
8149         }
8150     }
8151 
8152     tabulateProducerCount++;
8153     assertionsCombined = assertionsKernel | assertionsUser;
8154 
8155     if ((assertionsKernel != oldKernel) ||
8156         (assertionsCombined != oldCombined))
8157     {
8158         owner->evaluateAssertions(assertionsCombined, oldCombined);
8159     }
8160 }
8161 
8162 void PMAssertionsTracker::publishProperties( void )
8163 {
8164     OSArray             *assertionsSummary = NULL;
8165 
8166     if (tabulateConsumerCount != tabulateProducerCount)
8167     {
8168         IOLockLock(assertionsArrayLock);
8169 
8170         tabulateConsumerCount = tabulateProducerCount;
8171 
8172         /* Publish the IOPMrootDomain property "DriverPMAssertionsDetailed"
8173          */
8174         assertionsSummary = copyAssertionsArray();
8175         if (assertionsSummary)
8176         {
8177             owner->setProperty(kIOPMAssertionsDriverDetailedKey, assertionsSummary);
8178             assertionsSummary->release();
8179         }
8180         else
8181         {
8182             owner->removeProperty(kIOPMAssertionsDriverDetailedKey);
8183         }
8184 
8185         /* Publish the IOPMrootDomain property "DriverPMAssertions"
8186          */
8187         owner->setProperty(kIOPMAssertionsDriverKey, assertionsKernel, 64);
8188 
8189         IOLockUnlock(assertionsArrayLock);
8190     }
8191 }
8192 
8193 PMAssertionsTracker::PMAssertStruct *PMAssertionsTracker::detailsForID(IOPMDriverAssertionID _id, int *index)
8194 {
8195     PMAssertStruct      *_a = NULL;
8196     OSData              *_d = NULL;
8197     int                 found = -1;
8198     int                 count = 0;
8199     int                 i = 0;
8200 
8201     if (assertionsArray
8202         && (count = assertionsArray->getCount()))
8203     {
8204         for (i=0; i<count; i++)
8205         {
8206             _d = OSDynamicCast(OSData, assertionsArray->getObject(i));
8207             if (_d)
8208             {
8209                 _a = (PMAssertStruct *)_d->getBytesNoCopy();
8210                 if (_a && (_id == _a->id)) {
8211                     found = i;
8212                     break;
8213                 }
8214             }
8215         }
8216     }
8217 
8218     if (-1 == found) {
8219         return NULL;
8220     } else {
8221         if (index)
8222             *index = found;
8223         return _a;
8224     }
8225 }
8226 
8227 /* PMAssertionsTracker::handleCreateAssertion
8228  * Perform assertion work on the PM workloop. Do not call directly.
8229  */
8230 IOReturn PMAssertionsTracker::handleCreateAssertion(OSData *newAssertion)
8231 {
8232     ASSERT_GATED();
8233 
8234     if (newAssertion)
8235     {
8236         IOLockLock(assertionsArrayLock);
8237         assertionsArray->setObject(newAssertion);
8238         IOLockUnlock(assertionsArrayLock);
8239         newAssertion->release();
8240 
8241         tabulate();
8242     }
8243     return kIOReturnSuccess;
8244 }
8245 
8246 /* PMAssertionsTracker::createAssertion
8247  * createAssertion allocates memory for a new PM assertion, and affects system behavior, if
8248  * appropiate.
8249  */
8250 IOReturn PMAssertionsTracker::createAssertion(
8251     IOPMDriverAssertionType which,
8252     IOPMDriverAssertionLevel level,
8253     IOService *serviceID,
8254     const char *whoItIs,
8255     IOPMDriverAssertionID *outID)
8256 {
8257     OSData          *dataStore = NULL;
8258     PMAssertStruct  track;
8259 
8260     // Warning: trillions and trillions of created assertions may overflow the unique ID.
8261     track.id = OSIncrementAtomic64((SInt64*) &issuingUniqueID);
8262     track.level = level;
8263     track.assertionBits = which;
8264     track.ownerString = whoItIs ? OSSymbol::withCString(whoItIs):0;
8265     track.ownerService = serviceID;
8266     track.registryEntryID = serviceID ? serviceID->getRegistryEntryID():0;
8267     track.modifiedTime = 0;
8268     pmEventTimeStamp(&track.createdTime);
8269 
8270     dataStore = OSData::withBytes(&track, sizeof(PMAssertStruct));
8271     if (!dataStore)
8272     {
8273         if (track.ownerString)
8274             track.ownerString->release();
8275         return kIOReturnNoMemory;
8276     }
8277 
8278     *outID = track.id;
8279 
8280     if (owner && owner->pmPowerStateQueue) {
8281         owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionCreate, (void *)dataStore);
8282     }
8283 
8284     return kIOReturnSuccess;
8285 }
8286 
8287 /* PMAssertionsTracker::handleReleaseAssertion
8288  * Runs in PM workloop. Do not call directly.
8289  */
8290 IOReturn PMAssertionsTracker::handleReleaseAssertion(
8291     IOPMDriverAssertionID _id)
8292 {
8293     ASSERT_GATED();
8294 
8295     int             index;
8296     PMAssertStruct  *assertStruct = detailsForID(_id, &index);
8297 
8298     if (!assertStruct)
8299         return kIOReturnNotFound;
8300 
8301     IOLockLock(assertionsArrayLock);
8302     if (assertStruct->ownerString)
8303         assertStruct->ownerString->release();
8304 
8305     assertionsArray->removeObject(index);
8306     IOLockUnlock(assertionsArrayLock);
8307 
8308     tabulate();
8309     return kIOReturnSuccess;
8310 }
8311 
8312 /* PMAssertionsTracker::releaseAssertion
8313  * Releases an assertion and affects system behavior if appropiate.
8314  * Actual work happens on PM workloop.
8315  */
8316 IOReturn PMAssertionsTracker::releaseAssertion(
8317     IOPMDriverAssertionID _id)
8318 {
8319     if (owner && owner->pmPowerStateQueue) {
8320         owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionRelease, 0, _id);
8321     }
8322     return kIOReturnSuccess;
8323 }
8324 
8325 /* PMAssertionsTracker::handleSetAssertionLevel
8326  * Runs in PM workloop. Do not call directly.
8327  */
8328 IOReturn PMAssertionsTracker::handleSetAssertionLevel(
8329     IOPMDriverAssertionID    _id,
8330     IOPMDriverAssertionLevel _level)
8331 {
8332     PMAssertStruct      *assertStruct = detailsForID(_id, NULL);
8333 
8334     ASSERT_GATED();
8335 
8336     if (!assertStruct) {
8337         return kIOReturnNotFound;
8338     }
8339 
8340     IOLockLock(assertionsArrayLock);
8341     pmEventTimeStamp(&assertStruct->modifiedTime);
8342     assertStruct->level = _level;
8343     IOLockUnlock(assertionsArrayLock);
8344 
8345     tabulate();
8346     return kIOReturnSuccess;
8347 }
8348 
8349 /* PMAssertionsTracker::setAssertionLevel
8350  */
8351 IOReturn PMAssertionsTracker::setAssertionLevel(
8352     IOPMDriverAssertionID    _id,
8353     IOPMDriverAssertionLevel _level)
8354 {
8355     if (owner && owner->pmPowerStateQueue) {
8356         owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionSetLevel,
8357                 (void *)(uintptr_t)_level, _id);
8358     }
8359 
8360     return kIOReturnSuccess;
8361 }
8362 
8363 IOReturn PMAssertionsTracker::handleSetUserAssertionLevels(void * arg0)
8364 {
8365     IOPMDriverAssertionType new_user_levels = *(IOPMDriverAssertionType *) arg0;
8366 
8367     ASSERT_GATED();
8368 
8369     if (new_user_levels != assertionsUser)
8370     {
8371         assertionsUser = new_user_levels;
8372         DLOG("assertionsUser 0x%llx\n", assertionsUser);
8373     }
8374 
8375     tabulate();
8376     return kIOReturnSuccess;
8377 }
8378 
8379 IOReturn PMAssertionsTracker::setUserAssertionLevels(
8380     IOPMDriverAssertionType new_user_levels)
8381 {
8382     if (gIOPMWorkLoop) {
8383         gIOPMWorkLoop->runAction(
8384             OSMemberFunctionCast(
8385                 IOWorkLoop::Action,
8386                 this,
8387                 &PMAssertionsTracker::handleSetUserAssertionLevels),
8388             this,
8389             (void *) &new_user_levels, 0, 0, 0);
8390     }
8391 
8392     return kIOReturnSuccess;
8393 }
8394 
8395 
8396 OSArray *PMAssertionsTracker::copyAssertionsArray(void)
8397 {
8398     int count;
8399     int i;
8400     OSArray     *outArray = NULL;
8401 
8402     if (!assertionsArray ||
8403         (0 == (count = assertionsArray->getCount())) ||
8404         (NULL == (outArray = OSArray::withCapacity(count))))
8405     {
8406         goto exit;
8407     }
8408 
8409     for (i=0; i<count; i++)
8410     {
8411         PMAssertStruct  *_a = NULL;
8412         OSData          *_d = NULL;
8413         OSDictionary    *details = NULL;
8414 
8415         _d = OSDynamicCast(OSData, assertionsArray->getObject(i));
8416         if (_d && (_a = (PMAssertStruct *)_d->getBytesNoCopy()))
8417         {
8418             OSNumber        *_n = NULL;
8419 
8420             details = OSDictionary::withCapacity(7);
8421             if (!details)
8422                 continue;
8423 
8424             outArray->setObject(details);
8425             details->release();
8426 
8427             _n = OSNumber::withNumber(_a->id, 64);
8428             if (_n) {
8429                 details->setObject(kIOPMDriverAssertionIDKey, _n);
8430                 _n->release();
8431             }
8432             _n = OSNumber::withNumber(_a->createdTime, 64);
8433             if (_n) {
8434                 details->setObject(kIOPMDriverAssertionCreatedTimeKey, _n);
8435                 _n->release();
8436             }
8437             _n = OSNumber::withNumber(_a->modifiedTime, 64);
8438             if (_n) {
8439                 details->setObject(kIOPMDriverAssertionModifiedTimeKey, _n);
8440                 _n->release();
8441             }
8442             _n = OSNumber::withNumber((uintptr_t)_a->registryEntryID, 64);
8443             if (_n) {
8444                 details->setObject(kIOPMDriverAssertionRegistryEntryIDKey, _n);
8445                 _n->release();
8446             }
8447             _n = OSNumber::withNumber(_a->level, 64);
8448             if (_n) {
8449                 details->setObject(kIOPMDriverAssertionLevelKey, _n);
8450                 _n->release();
8451             }
8452             _n = OSNumber::withNumber(_a->assertionBits, 64);
8453             if (_n) {
8454                 details->setObject(kIOPMDriverAssertionAssertedKey, _n);
8455                 _n->release();
8456             }
8457 
8458             if (_a->ownerString) {
8459                 details->setObject(kIOPMDriverAssertionOwnerStringKey, _a->ownerString);
8460             }
8461         }
8462     }
8463 
8464 exit:
8465     return outArray;
8466 }
8467 
8468 IOPMDriverAssertionType PMAssertionsTracker::getActivatedAssertions(void)
8469 {
8470     return assertionsCombined;
8471 }
8472 
8473 IOPMDriverAssertionLevel PMAssertionsTracker::getAssertionLevel(
8474     IOPMDriverAssertionType type)
8475 {
8476     if (type && ((type & assertionsKernel) == assertionsKernel))
8477     {
8478         return kIOPMDriverAssertionLevelOn;
8479     } else {
8480         return kIOPMDriverAssertionLevelOff;
8481     }
8482 }
8483 
8484 //*********************************************************************************
8485 //*********************************************************************************
8486 //*********************************************************************************
8487 
8488 
8489 static void pmEventTimeStamp(uint64_t *recordTS)
8490 {
8491     clock_sec_t     tsec;
8492     clock_usec_t    tusec;
8493 
8494     if (!recordTS)
8495         return;
8496 
8497     // We assume tsec fits into 32 bits; 32 bits holds enough
8498     // seconds for 136 years since the epoch in 1970.
8499     clock_get_calendar_microtime(&tsec, &tusec);
8500 
8501 
8502     // Pack the sec & microsec calendar time into a uint64_t, for fun.
8503     *recordTS = 0;
8504     *recordTS |= (uint32_t)tusec;
8505     *recordTS |= ((uint64_t)tsec << 32);
8506 
8507     return;
8508 }
8509 
8510 // MARK: -
8511 // MARK: IORootParent
8512 
8513 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
8514 
8515 OSDefineMetaClassAndFinalStructors(IORootParent, IOService)
8516 
8517 // The reason that root domain needs a root parent is to facilitate demand
8518 // sleep, since a power change from the root parent cannot be vetoed.
8519 //
8520 // The above statement is no longer true since root domain now performs
8521 // demand sleep using overrides. But root parent remains to avoid changing
8522 // the power tree stacking. Root parent is parked at the max power state.
8523 
8524 
8525 static IOPMPowerState patriarchPowerStates[2] =
8526 {
8527     {1,0,ON_POWER,0,0,0,0,0,0,0,0,0},
8528     {1,0,ON_POWER,0,0,0,0,0,0,0,0,0},
8529 };
8530 
8531 void IORootParent::initialize( void )
8532 {
8533 }
8534 
8535 bool IORootParent::start( IOService * nub )
8536 {
8537     IOService::start(nub);
8538     attachToParent( getRegistryRoot(), gIOPowerPlane );
8539     PMinit();
8540     registerPowerDriver(this, patriarchPowerStates, 2);
8541     makeUsable();
8542     return true;
8543 }
8544 
8545 void IORootParent::shutDownSystem( void )
8546 {
8547 }
8548 
8549 void IORootParent::restartSystem( void )
8550 {
8551 }
8552 
8553 void IORootParent::sleepSystem( void )
8554 {
8555 }
8556 
8557 void IORootParent::dozeSystem( void )
8558 {
8559 }
8560 
8561 void IORootParent::sleepToDoze( void )
8562 {
8563 }
8564 
8565 void IORootParent::wakeSystem( void )
8566 {
8567 }
8568 
8569 OSObject * IORootParent::copyProperty( const char * aKey) const
8570 {
8571     return (IOService::copyProperty(aKey));
8572 }
8573 
8574 
8575 #if defined(__i386__) || defined(__x86_64__)
8576 IOReturn IOPMrootDomain::restartWithStackshot()
8577 {
8578     if ((swd_flags & SWD_WDOG_ENABLED) == 0)
8579         return kIOReturnError;
8580 
8581     takeStackshot(true, true);
8582 
8583     return kIOReturnSuccess;
8584 }
8585 
8586 void IOPMrootDomain::sleepWakeDebugTrig(bool wdogTrigger)
8587 {
8588     takeStackshot(wdogTrigger, false);
8589 }
8590 
8591 void IOPMrootDomain::takeStackshot(bool wdogTrigger, bool isOSXWatchdog)
8592 {
8593    swd_hdr *         hdr = NULL;
8594    addr64_t          data[3];
8595    uint32_t          wdog_panic = 0;
8596    int               cnt = 0;
8597    pid_t             pid = 0;
8598    uint32_t          flags;
8599 
8600    char *            dstAddr;
8601    uint32_t          size;
8602    uint32_t          bytesRemaining;
8603    unsigned int      len;
8604    OSString *        UUIDstring = NULL;
8605    uint64_t          code;
8606    IOMemoryMap *     logBufMap = NULL;
8607 
8608    swd_stackshot_hdr *stackshotHdr = NULL;
8609    if ( kIOSleepWakeWdogOff & gIOKitDebug )
8610       return;
8611 
8612    if (wdogTrigger) {
8613        if (PE_parse_boot_argn("swd_panic", &wdog_panic, sizeof(wdog_panic)) &&
8614                   (wdog_panic == 1)) {
8615            // If boot-arg is set to panic on sleep/wake hang, call panic
8616            panic("Sleep/Wake hang detected\n");
8617            return;
8618        }
8619        else if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
8620            // If current boot is due to this watch dog trigger restart in previous boot,
8621            // then don't trigger again until at least 1 successful sleep & wake.
8622            sleepCnt = displayWakeCnt = 1;
8623            if (!(sleepCnt && displayWakeCnt)) {
8624                IOLog("Shutting down due to repeated Sleep/Wake failures\n");
8625                PEHaltRestart(kPEHaltCPU);
8626                return;
8627            }
8628        }
8629 
8630    }
8631 
8632    if (sleepWakeDebugIsWdogEnabled() == false)
8633        return;
8634 
8635    if (swd_buffer == NULL) {
8636       sleepWakeDebugMemAlloc();
8637       if (swd_buffer == NULL) return;
8638    }
8639 
8640    if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock))
8641        return;
8642 
8643 
8644    hdr = (swd_hdr *)swd_buffer;
8645    memset(hdr->UUID, 0x20, sizeof(hdr->UUID));
8646    if ((UUIDstring = OSDynamicCast(OSString, getProperty(kIOPMSleepWakeUUIDKey))) != NULL ) {
8647 
8648       if (wdogTrigger || (!UUIDstring->isEqualTo(hdr->UUID))) {
8649          const char *str = UUIDstring->getCStringNoCopy();
8650          snprintf(hdr->UUID, sizeof(hdr->UUID), "UUID: %s", str);
8651       }
8652       else {
8653          DLOG("Data for current UUID already exists\n");
8654          goto exit;
8655       }
8656    }
8657 
8658    dstAddr = (char*)hdr + hdr->spindump_offset;
8659    bytesRemaining = SWD_BUF_SIZE - hdr->spindump_offset;
8660 
8661    /* if AppleOSXWatchdog triggered the stackshot, set the flag in the heaer */
8662    hdr->is_osx_watchdog = isOSXWatchdog;
8663 
8664    DLOG("Taking snapshot. bytesRemaining: %d\n", bytesRemaining);
8665 
8666    while (bytesRemaining > sizeof(swd_stackshot_hdr)) {
8667 
8668        stackshotHdr = (swd_stackshot_hdr *)dstAddr;
8669        stackshotHdr->magic = SWD_STACKSHOTHDR_MAGIC;
8670        stackshotHdr->size = 0;
8671        bytesRemaining -= sizeof(swd_stackshot_hdr);
8672        dstAddr += sizeof(swd_stackshot_hdr);
8673 
8674        if (isOSXWatchdog) {
8675            pid = -1;
8676            size = bytesRemaining;
8677            flags = STACKSHOT_SAVE_LOADINFO | STACKSHOT_SAVE_KEXT_LOADINFO;
8678        }
8679        else if (cnt == 0) {
8680            /*
8681             * Take stackshot of all process on first sample. Size is restricted
8682             * to SWD_INITIAL_STACK_SIZE
8683             */
8684            pid = -1;
8685            size = (bytesRemaining > SWD_INITIAL_STACK_SIZE) ? SWD_INITIAL_STACK_SIZE : bytesRemaining;
8686            flags = STACKSHOT_SAVE_LOADINFO | STACKSHOT_SAVE_KEXT_LOADINFO|STACKSHOT_SAVE_KERNEL_FRAMES_ONLY;
8687        }
8688        else {
8689            /* Take sample of kernel threads only */
8690            pid = 0;
8691            size = bytesRemaining;
8692            flags = 0;
8693        }
8694 
8695        stack_snapshot_from_kernel(pid, dstAddr, size, flags, &stackshotHdr->size);
8696 
8697        dstAddr += stackshotHdr->size;
8698        bytesRemaining -= stackshotHdr->size;
8699 
8700        DLOG("Sample: %d size: %d bytesRemaining: %d\n", cnt, stackshotHdr->size, bytesRemaining);
8701        if ((stackshotHdr->size == 0) || (++cnt == 10))
8702            break;
8703        IOSleep(10); // 10 ms
8704    }
8705 
8706    hdr->spindump_size = (SWD_BUF_SIZE - bytesRemaining - hdr->spindump_offset);
8707 
8708 
8709    memset(hdr->cps, 0x20, sizeof(hdr->cps));
8710    snprintf(hdr->cps, sizeof(hdr->cps), "\ncps: %d", ((IOService*)this)->getPowerState());
8711    code = pmTracer->getPMStatusCode();
8712    memset(hdr->PMStatusCode, 0x20, sizeof(hdr->PMStatusCode));
8713    snprintf(hdr->PMStatusCode, sizeof(hdr->PMStatusCode), "\nCode: %08x %08x",
8714            (uint32_t)((code >> 32) & 0xffffffff), (uint32_t)(code & 0xffffffff));
8715    memset(hdr->reason, 0x20, sizeof(hdr->reason));
8716    snprintf(hdr->reason, sizeof(hdr->reason), "\nStackshot reason: Watchdog\n\n");
8717 
8718 
8719    data[0] = round_page(sizeof(swd_hdr) + hdr->spindump_size);
8720    /* Header & rootdomain log is constantly changing and  is not covered by CRC */
8721    data[1] = hdr->crc = crc32(0, ((char*)swd_buffer+hdr->spindump_offset), hdr->spindump_size);
8722    data[2] = kvtophys((vm_offset_t)swd_buffer);
8723    len = sizeof(addr64_t)*3;
8724    DLOG("bytes: 0x%llx crc:0x%llx paddr:0x%llx\n",
8725          data[0], data[1], data[2]);
8726 
8727    if (PEWriteNVRAMProperty(kIOSleepWakeDebugKey, data, len) == false)
8728    {
8729       DLOG("Failed to update nvram boot-args\n");
8730       goto exit;
8731    }
8732 
8733 exit:
8734 
8735    gRootDomain->swd_lock = 0;
8736 
8737    if (wdogTrigger) {
8738       IOLog("Restarting to collect Sleep wake debug logs\n");
8739       PEHaltRestart(kPERestartCPU);
8740    }
8741    else {
8742      logBufMap = sleepWakeDebugRetrieve();
8743       if (logBufMap) {
8744           sleepWakeDebugDumpFromMem(logBufMap);
8745           logBufMap->release();
8746           logBufMap = 0;
8747       }
8748    }
8749 }
8750 
8751 void IOPMrootDomain::sleepWakeDebugMemAlloc( )
8752 {
8753     vm_size_t    size = SWD_BUF_SIZE;
8754 
8755     swd_hdr      *hdr = NULL;
8756 
8757     IOBufferMemoryDescriptor  *memDesc = NULL;
8758 
8759 
8760     if ( kIOSleepWakeWdogOff & gIOKitDebug )
8761       return;
8762 
8763     if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock))
8764        return;
8765 
8766     // Try allocating above 4GB. If that fails, try at 2GB
8767     memDesc = IOBufferMemoryDescriptor::inTaskWithPhysicalMask(
8768                             kernel_task, kIOMemoryPhysicallyContiguous|kIOMemoryMapperNone,
8769                             size, 0xFFFFFFFF00000000ULL);
8770     if (!memDesc) {
8771        memDesc = IOBufferMemoryDescriptor::inTaskWithPhysicalMask(
8772                             kernel_task, kIOMemoryPhysicallyContiguous|kIOMemoryMapperNone,
8773                             size, 0xFFFFFFFF10000000ULL);
8774     }
8775 
8776     if (memDesc == NULL)
8777     {
8778       DLOG("Failed to allocate Memory descriptor for sleepWake debug\n");
8779       goto exit;
8780     }
8781 
8782 
8783     hdr = (swd_hdr *)memDesc->getBytesNoCopy();
8784     memset(hdr, 0, sizeof(swd_hdr));
8785 
8786     hdr->signature = SWD_HDR_SIGNATURE;
8787     hdr->alloc_size = size;
8788 
8789     hdr->spindump_offset = sizeof(swd_hdr);
8790     swd_buffer = (void *)hdr;
8791     DLOG("SleepWake debug buffer size:0x%x spindump offset:0x%x\n", hdr->alloc_size, hdr->spindump_offset);
8792 
8793 exit:
8794     gRootDomain->swd_lock = 0;
8795 }
8796 
8797 void IOPMrootDomain::sleepWakeDebugEnableWdog()
8798 {
8799     swd_flags |= SWD_WDOG_ENABLED;
8800     if (!swd_buffer)
8801         sleepWakeDebugMemAlloc();
8802 }
8803 
8804 bool IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
8805 {
8806     return ((swd_flags & SWD_WDOG_ENABLED) &&
8807             !systemBooting && !systemShutdown);
8808 }
8809 
8810 errno_t IOPMrootDomain::sleepWakeDebugSaveFile(const char *name, char *buf, int len)
8811 {
8812    struct vnode         *vp = NULL;
8813    vfs_context_t        ctx = vfs_context_create(vfs_context_current());
8814    kauth_cred_t         cred = vfs_context_ucred(ctx);
8815    struct vnode_attr    va;
8816    errno_t      error = EIO;
8817 
8818    if (vnode_open(name, (O_CREAT | FWRITE | O_NOFOLLOW),
8819                         S_IRUSR|S_IRGRP|S_IROTH, VNODE_LOOKUP_NOFOLLOW, &vp, ctx) != 0)
8820    {
8821       IOLog("Failed to open the file %s\n", name);
8822       goto exit;
8823    }
8824    VATTR_INIT(&va);
8825    VATTR_WANTED(&va, va_nlink);
8826    /* Don't dump to non-regular files or files with links. */
8827    if (vp->v_type != VREG ||
8828         vnode_getattr(vp, &va, ctx) || va.va_nlink != 1) {
8829         IOLog("Bailing as this is not a regular file\n");
8830         goto exit;
8831     }
8832     VATTR_INIT(&va);
8833     VATTR_SET(&va, va_data_size, 0);
8834     vnode_setattr(vp, &va, ctx);
8835 
8836 
8837     error = vn_rdwr(UIO_WRITE, vp, buf, len, 0,
8838         UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) 0,  vfs_context_proc(ctx));
8839     if (error != 0)
8840        IOLog("Failed to save sleep wake log. err 0x%x\n", error);
8841     else
8842        DLOG("Saved %d bytes to file %s\n",len, name);
8843 
8844 exit:
8845     if (vp) vnode_close(vp, FWRITE, ctx);
8846     if (ctx) vfs_context_rele(ctx);
8847 
8848     return error;
8849 
8850 }
8851 
8852 errno_t IOPMrootDomain::sleepWakeDebugCopyFile(
8853                                struct vnode *srcVp,
8854                                vfs_context_t srcCtx,
8855                                char *tmpBuf, uint64_t tmpBufSize,
8856                                uint64_t srcOffset,
8857                                const char *dstFname,
8858                                uint64_t numBytes,
8859                                uint32_t crc)
8860 {
8861    struct vnode         *vp = NULL;
8862    vfs_context_t        ctx = vfs_context_create(vfs_context_current());
8863    struct vnode_attr    va;
8864    errno_t      error = EIO;
8865    uint64_t bytesToRead, bytesToWrite;
8866    uint64_t readFileOffset, writeFileOffset, srcDataOffset;
8867    uint32_t newcrc = 0;
8868 
8869    if (vnode_open(dstFname, (O_CREAT | FWRITE | O_NOFOLLOW),
8870                         S_IRUSR|S_IRGRP|S_IROTH, VNODE_LOOKUP_NOFOLLOW, &vp, ctx) != 0)
8871    {
8872       DLOG("Failed to open the file %s\n", dstFname);
8873       goto exit;
8874    }
8875    VATTR_INIT(&va);
8876    VATTR_WANTED(&va, va_nlink);
8877    /* Don't dump to non-regular files or files with links. */
8878    if (vp->v_type != VREG ||
8879         vnode_getattr(vp, &va, ctx) || va.va_nlink != 1) {
8880         DLOG("Bailing as this is not a regular file\n");
8881         goto exit;
8882 	}
8883     VATTR_INIT(&va);
8884     VATTR_SET(&va, va_data_size, 0);
8885     vnode_setattr(vp, &va, ctx);
8886 
8887     writeFileOffset = 0;
8888     while(numBytes) {
8889         bytesToRead = (round_page(numBytes) > tmpBufSize) ? tmpBufSize : round_page(numBytes);
8890         readFileOffset = trunc_page(srcOffset);
8891 
8892        DLOG("Read file (numBytes:0x%llx)\n", bytesToRead);
8893        error = vn_rdwr(UIO_READ, srcVp, tmpBuf, bytesToRead, readFileOffset,
8894                UIO_SYSSPACE, IO_SKIP_ENCRYPTION|IO_SYNC|IO_NODELOCKED|IO_UNIT|IO_NOCACHE,
8895                vfs_context_ucred(srcCtx), (int *) 0,
8896                vfs_context_proc(srcCtx));
8897        if (error) {
8898            DLOG("Failed to read file(numBytes:0x%llx)\n", bytesToRead);
8899            break;
8900        }
8901 
8902        srcDataOffset = (uint64_t)tmpBuf + (srcOffset - readFileOffset);
8903        bytesToWrite = bytesToRead - (srcOffset - readFileOffset);
8904        if (bytesToWrite > numBytes) bytesToWrite = numBytes;
8905 
8906        if (crc) {
8907            newcrc = crc32(newcrc, (void *)srcDataOffset, bytesToWrite);
8908        }
8909        error = vn_rdwr(UIO_WRITE, vp, (char *)srcDataOffset, bytesToWrite, writeFileOffset,
8910                UIO_SYSSPACE, IO_SYNC|IO_NODELOCKED|IO_UNIT,
8911                vfs_context_ucred(ctx), (int *) 0,
8912                vfs_context_proc(ctx));
8913        if (error) {
8914            DLOG("Failed to write file(numBytes:0x%llx)\n", bytesToWrite);
8915            break;
8916        }
8917 
8918        writeFileOffset += bytesToWrite;
8919        numBytes -= bytesToWrite;
8920        srcOffset += bytesToWrite;
8921 
8922     }
8923     if (crc != newcrc) {
8924         swd_stackshot_hdr *shdr = (swd_stackshot_hdr *)tmpBuf;;
8925 
8926         /* Set statckshot size to 0 if crc doesn't match */
8927         shdr->magic = SWD_STACKSHOTHDR_MAGIC;
8928         shdr->size = 0;
8929 
8930         assert(tmpBufSize > sizeof(swd_stackshot_hdr));
8931         bytesToWrite = round_page(sizeof(swd_stackshot_hdr));
8932         vn_rdwr(UIO_WRITE, vp, (char *)tmpBuf, bytesToWrite, 0,
8933                UIO_SYSSPACE, IO_SYNC|IO_NODELOCKED|IO_UNIT,
8934                vfs_context_ucred(ctx), (int *) 0,
8935                vfs_context_proc(ctx));
8936 
8937         DLOG("CRC check failed. expected:0x%x actual:0x%x\n", crc, newcrc);
8938         error = EFAULT;
8939     }
8940 exit:
8941     if (vp) {
8942         error = vnode_close(vp, FWRITE, ctx);
8943         DLOG("vnode_close returned 0x%x\n", error);
8944     }
8945     if (ctx) vfs_context_rele(ctx);
8946 
8947     return error;
8948 
8949 
8950 
8951 }
8952 
8953 void IOPMrootDomain::sleepWakeDebugDumpFromFile( )
8954 {
8955 
8956     int             rc;
8957     char			hibernateFilename[MAXPATHLEN+1];
8958     char            PMStatusCode[100];
8959     void            *tmpBuf;
8960     swd_hdr         *hdr = NULL;
8961     uint32_t        stacksSize, logSize;
8962     uint64_t        tmpBufSize;
8963     uint64_t        hdrOffset, stacksOffset, logOffset;
8964     errno_t         error = EIO;
8965     OSObject        *obj = NULL;
8966     OSString        *str = NULL;
8967     OSNumber        *failStat = NULL;
8968     struct vnode    *vp = NULL;
8969     vfs_context_t   ctx = NULL;
8970 
8971     struct vnode_attr           va;
8972     IOBufferMemoryDescriptor    *tmpBufDesc = NULL;
8973     IOHibernateImageHeader      *imageHdr;
8974 
8975     DLOG("sleepWakeDebugDumpFromFile\n");
8976     if ((swd_flags & SWD_LOGS_IN_FILE) == 0)
8977         return;
8978 
8979    if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock))
8980        return;
8981 
8982 
8983     hibernateFilename[0] = 0;
8984     if ((obj = copyProperty(kIOHibernateFileKey)))
8985     {
8986         if ((str = OSDynamicCast(OSString, obj)))
8987             strlcpy(hibernateFilename, str->getCStringNoCopy(),
8988                     sizeof(hibernateFilename));
8989         obj->release();
8990     }
8991     if (!hibernateFilename[0]) {
8992         DMSG("sleepWakeDebugDumpFromFile: Failed to hib file name\n");
8993         goto exit;
8994     }
8995     DLOG("sleepWakeDebugDumpFromFile: Hib file name %s\n", hibernateFilename);
8996 
8997     /* Allocate a temp buffer to copy data between files */
8998     tmpBufSize = 2*4096;
8999     tmpBufDesc = IOBufferMemoryDescriptor::
9000         inTaskWithOptions(kernel_task, kIODirectionOutIn | kIOMemoryMapperNone,
9001                           tmpBufSize, PAGE_SIZE);
9002 
9003     if (!tmpBufDesc) {
9004         DMSG("sleepWakeDebugDumpFromFile: Fail to allocate temp buf\n");
9005         goto exit;
9006     }
9007 
9008     tmpBuf = tmpBufDesc->getBytesNoCopy();
9009 
9010    ctx = vfs_context_create(vfs_context_current());
9011     if (vnode_open(hibernateFilename, (FREAD | O_NOFOLLOW), 0,
9012                    VNODE_LOOKUP_NOFOLLOW, &vp, ctx) != 0)
9013     {
9014         DMSG("sleepWakeDebugDumpFromFile: Failed to open the hibernate file %s\n", hibernateFilename);
9015         goto exit;
9016     }
9017     VATTR_INIT(&va);
9018     VATTR_WANTED(&va, va_nlink);
9019     VATTR_WANTED(&va, va_data_alloc);
9020     if (vp->v_type != VREG ||
9021         vnode_getattr(vp, &va, ctx) || va.va_nlink != 1) {
9022         DMSG("sleepWakeDebugDumpFromFile: Bailing as this is not a regular file\n");
9023         goto exit;
9024     }
9025 
9026     /* Read the sleepimage file header */
9027     rc = vn_rdwr(UIO_READ, vp, (char *)tmpBuf, round_page(sizeof(IOHibernateImageHeader)), 0,
9028                 UIO_SYSSPACE, IO_SKIP_ENCRYPTION|IO_SYNC|IO_NODELOCKED|IO_UNIT|IO_NOCACHE,
9029                 vfs_context_ucred(ctx), (int *) 0,
9030                 vfs_context_proc(ctx));
9031     if (rc != 0) {
9032         DMSG("sleepWakeDebugDumpFromFile: Failed to read header size %lu(rc=%d)\n", round_page(sizeof(IOHibernateImageHeader)), rc);
9033         goto exit;
9034     }
9035 
9036     imageHdr = ((IOHibernateImageHeader *)tmpBuf);
9037     if (imageHdr->signature != kIOHibernateHeaderDebugDataSignature) {
9038         DMSG("sleepWakeDebugDumpFromFile: File header has unexpected value 0x%x\n", imageHdr->signature);
9039         goto exit;
9040     }
9041 
9042     /* Sleep/Wake debug header(swd_hdr) is at the beggining of the second block */
9043     hdrOffset = imageHdr->deviceBlockSize;
9044     if (hdrOffset + sizeof(swd_hdr) >= va.va_data_alloc) {
9045         DMSG("sleepWakeDebugDumpFromFile: header is crossing file size(0x%llx)\n",  va.va_data_alloc);
9046         goto exit;
9047     }
9048 
9049     DLOG("Reading swd_hdr len 0x%lx offset 0x%lx\n", round_page(sizeof(swd_hdr)), trunc_page(hdrOffset));
9050     /* Read the sleep/wake debug header(swd_hdr) */
9051     rc = vn_rdwr(UIO_READ, vp, (char *)tmpBuf, round_page(sizeof(swd_hdr)), trunc_page(hdrOffset),
9052                 UIO_SYSSPACE, IO_SKIP_ENCRYPTION|IO_SYNC|IO_NODELOCKED|IO_UNIT|IO_NOCACHE,
9053                 vfs_context_ucred(ctx), (int *) 0,
9054                 vfs_context_proc(ctx));
9055     if (rc != 0) {
9056         DMSG("sleepWakeDebugDumpFromFile: Failed to debug read header size %lu. rc=%d\n",
9057              round_page(sizeof(swd_hdr)), rc);
9058         goto exit;
9059     }
9060 
9061     hdr = (swd_hdr *)((char *)tmpBuf + (hdrOffset - trunc_page(hdrOffset)));
9062     if ((hdr->signature != SWD_HDR_SIGNATURE) || (hdr->alloc_size > SWD_BUF_SIZE) ||
9063         (hdr->spindump_offset > SWD_BUF_SIZE) || (hdr->spindump_size > SWD_BUF_SIZE)) {
9064         DMSG("sleepWakeDebugDumpFromFile: Invalid data in debug header. sign:0x%x size:0x%x spindump_offset:0x%x spindump_size:0x%x\n",
9065              hdr->signature, hdr->alloc_size, hdr->spindump_offset, hdr->spindump_size);
9066         goto exit;
9067     }
9068     stacksSize = hdr->spindump_size;
9069 
9070     /* Get stacks & log offsets in the image file */
9071     stacksOffset = hdrOffset + hdr->spindump_offset;
9072     logOffset = hdrOffset + offsetof(swd_hdr, UUID);
9073     logSize = sizeof(swd_hdr)-offsetof(swd_hdr, UUID);
9074 
9075     error = sleepWakeDebugCopyFile(vp, ctx, (char *)tmpBuf, tmpBufSize, stacksOffset,
9076                                    getDumpStackFilename(hdr), stacksSize, hdr->crc);
9077     if (error == EFAULT) {
9078         DMSG("sleepWakeDebugDumpFromFile: Stackshot CRC doesn't match\n");
9079         goto exit;
9080     }
9081     error = sleepWakeDebugCopyFile(vp, ctx, (char *)tmpBuf, tmpBufSize, logOffset,
9082                                    getDumpLogFilename(hdr), logSize, 0);
9083     if (error) {
9084         DMSG("sleepWakeDebugDumpFromFile: Failed to write the log file(0x%x)\n", error);
9085         goto exit;
9086     }
9087 exit:
9088     if (error) {
9089       // Write just the SleepWakeLog.dump with failure code
9090       uint64_t fcode = 0;
9091       const char *fname;
9092       if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
9093           failStat = OSDynamicCast(OSNumber, getProperty(kIOPMSleepWakeFailureCodeKey));
9094           fcode = failStat->unsigned64BitValue();
9095           fname = kSleepWakeLogFilename;
9096       }
9097       else {
9098           fname = kAppleOSXWatchdogLogFilename;
9099       }
9100       memset(PMStatusCode, 0x20, sizeof(PMStatusCode)); // Fill with spaces
9101       PMStatusCode[sizeof(PMStatusCode)-1] = 0xa; // And an end-of-line at the end
9102       snprintf(PMStatusCode, sizeof(PMStatusCode)-1, "Code: 0x%llx", fcode);
9103       sleepWakeDebugSaveFile(fname, PMStatusCode, sizeof(PMStatusCode));
9104     }
9105     gRootDomain->swd_lock = 0;
9106 
9107     if (vp) vnode_close(vp, FREAD, ctx);
9108     if (ctx) vfs_context_rele(ctx);
9109     if (tmpBufDesc) tmpBufDesc->release();
9110 
9111 }
9112 
9113 void IOPMrootDomain::sleepWakeDebugDumpFromMem(IOMemoryMap *logBufMap)
9114 {
9115    IOVirtualAddress     srcBuf = NULL;
9116    char                 *stackBuf = NULL, *logOffset = NULL;
9117    int                  logSize = 0;
9118 
9119    errno_t      error = EIO;
9120    uint64_t     bufSize = 0;
9121    swd_hdr      *hdr = NULL;
9122    char PMStatusCode[100];
9123    OSNumber  *failStat = NULL;
9124 
9125    if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock))
9126        return;
9127 
9128    if ((logBufMap == 0) || ( (srcBuf = logBufMap->getVirtualAddress()) == 0) )
9129    {
9130       DLOG("Nothing saved to dump to file\n");
9131       goto exit;
9132    }
9133 
9134    hdr = (swd_hdr *)srcBuf;
9135    bufSize = logBufMap->getLength();
9136    if (bufSize <= sizeof(swd_hdr))
9137    {
9138       IOLog("SleepWake log buffer contents are invalid\n");
9139       goto exit;
9140    }
9141 
9142    stackBuf = (char*)hdr+hdr->spindump_offset;
9143 
9144    error = sleepWakeDebugSaveFile(getDumpStackFilename(hdr), stackBuf, hdr->spindump_size);
9145    if (error) goto exit;
9146 
9147    logOffset = (char*)hdr+offsetof(swd_hdr, UUID);
9148    logSize = sizeof(swd_hdr)-offsetof(swd_hdr, UUID);
9149 
9150    error = sleepWakeDebugSaveFile(getDumpLogFilename(hdr), logOffset, logSize);
9151    if (error) goto exit;
9152 
9153     hdr->spindump_size = 0;
9154     error = 0;
9155 
9156 exit:
9157     if (error) {
9158       // Write just the SleepWakeLog.dump with failure code
9159       uint64_t fcode = 0;
9160       const char *sname, *lname;
9161       swd_stackshot_hdr shdr;
9162 
9163         /* Try writing an empty stacks file */
9164         shdr.magic = SWD_STACKSHOTHDR_MAGIC;
9165         shdr.size = 0;
9166 
9167 
9168       if (swd_flags & SWD_BOOT_BY_SW_WDOG) {
9169           failStat = OSDynamicCast(OSNumber, getProperty(kIOPMSleepWakeFailureCodeKey));
9170           fcode = failStat->unsigned64BitValue();
9171           lname = kSleepWakeLogFilename;
9172           sname = kSleepWakeStackFilename;
9173       }
9174       else {
9175           lname = kAppleOSXWatchdogLogFilename;
9176           sname= kAppleOSXWatchdogStackFilename;
9177       }
9178 
9179       sleepWakeDebugSaveFile(sname, (char*)(&shdr), sizeof(shdr));
9180       memset(PMStatusCode, 0x20, sizeof(PMStatusCode)); // Fill with spaces
9181       PMStatusCode[sizeof(PMStatusCode)-1] = 0xa; // And an end-of-line at the end
9182       snprintf(PMStatusCode, sizeof(PMStatusCode)-1, "Code: 0x%llx", fcode);
9183       sleepWakeDebugSaveFile(lname, PMStatusCode, sizeof(PMStatusCode));
9184     }
9185     gRootDomain->swd_lock = 0;
9186 }
9187 
9188 IOMemoryMap *IOPMrootDomain::sleepWakeDebugRetrieve( )
9189 {
9190    IOVirtualAddress     vaddr = NULL;
9191    IOMemoryDescriptor * desc = NULL;
9192    IOMemoryMap *        logBufMap = NULL;
9193 
9194    uint32_t          len;
9195    addr64_t          data[3];
9196    uint64_t          bufSize = 0;
9197    uint64_t          crc = 0;
9198    uint64_t          newcrc = 0;
9199    uint64_t          paddr = 0;
9200    swd_hdr           *hdr = NULL;
9201    bool              ret = false;
9202    char              str[20];
9203 
9204 
9205    if (!OSCompareAndSwap(0, 1, &gRootDomain->swd_lock))
9206        return NULL;
9207 
9208    if (!PEReadNVRAMProperty(kIOSleepWakeDebugKey, 0, &len)) {
9209       DLOG("No sleepWakeDebug note to read\n");
9210       goto exit;
9211    }
9212 
9213    if (len == strlen("sleepimage")) {
9214        str[0] = 0;
9215        PEReadNVRAMProperty(kIOSleepWakeDebugKey, str, &len);
9216 
9217        if (!strncmp((char*)str, "sleepimage", strlen("sleepimage"))) {
9218            DLOG("sleepWakeDebugRetrieve: in file logs\n");
9219            swd_flags |= SWD_LOGS_IN_FILE|SWD_VALID_LOGS;
9220            goto exit;
9221        }
9222    }
9223    else if (len == sizeof(addr64_t)*3)
9224        PEReadNVRAMProperty(kIOSleepWakeDebugKey, data, &len);
9225    else {
9226       DLOG("Invalid sleepWakeDebug note length(%d)\n", len);
9227       goto exit;
9228    }
9229 
9230 
9231 
9232    DLOG("sleepWakeDebugRetrieve: data[0]:0x%llx data[1]:0x%llx data[2]:0x%llx\n",
9233         data[0], data[1], data[2]);
9234    DLOG("sleepWakeDebugRetrieve: in mem logs\n");
9235    bufSize = data[0];
9236    crc = data[1];
9237    paddr = data[2];
9238    if ( (bufSize <= sizeof(swd_hdr)) ||(bufSize > SWD_BUF_SIZE) || (crc == 0) )
9239    {
9240       IOLog("SleepWake log buffer contents are invalid\n");
9241       return NULL;
9242    }
9243 
9244    DLOG("size:0x%llx crc:0x%llx paddr:0x%llx\n",
9245          bufSize, crc, paddr);
9246 
9247 
9248    desc = IOMemoryDescriptor::withAddressRange( paddr, bufSize,
9249                           kIODirectionOutIn | kIOMemoryMapperNone, NULL);
9250    if (desc == NULL)
9251    {
9252       IOLog("Fail to map SleepWake log buffer\n");
9253       goto exit;
9254    }
9255 
9256    logBufMap = desc->map();
9257 
9258    vaddr = logBufMap->getVirtualAddress();
9259 
9260 
9261    if ( (logBufMap->getLength() <= sizeof(swd_hdr)) || (vaddr == NULL) ) {
9262       IOLog("Fail to map SleepWake log buffer\n");
9263       goto exit;
9264    }
9265 
9266    hdr = (swd_hdr *)vaddr;
9267    if (hdr->spindump_offset+hdr->spindump_size > bufSize)
9268    {
9269       IOLog("SleepWake log buffer contents are invalid\n");
9270       goto exit;
9271    }
9272 
9273    hdr->crc = crc;
9274    newcrc = crc32(0, (void *)((char*)vaddr+hdr->spindump_offset),
9275             hdr->spindump_size);
9276    if (newcrc != crc) {
9277       IOLog("SleepWake log buffer contents are invalid\n");
9278       goto exit;
9279    }
9280 
9281    ret = true;
9282    swd_flags |= SWD_LOGS_IN_MEM | SWD_VALID_LOGS;
9283 
9284 
9285 exit:
9286    PERemoveNVRAMProperty(kIOSleepWakeDebugKey);
9287    if (!ret) {
9288       if (logBufMap) logBufMap->release();
9289       logBufMap = 0;
9290    }
9291    if (desc) desc->release();
9292     gRootDomain->swd_lock = 0;
9293 
9294    return logBufMap;
9295 }
9296 
9297 #else
9298 
9299 void IOPMrootDomain::sleepWakeDebugTrig(bool restart)
9300 {
9301 }
9302 
9303 void IOPMrootDomain::takeStackshot(bool restart, bool isOSXWatchdog)
9304 {
9305 #pragma unused(restart)
9306 #pragma unused(isOSXWatchdog)
9307 }
9308 
9309 void IOPMrootDomain::sleepWakeDebugMemAlloc( )
9310 {
9311 }
9312 void IOPMrootDomain::sleepWakeDebugDumpFromMem(IOMemoryMap *map)
9313 {
9314 }
9315 errno_t IOPMrootDomain::sleepWakeDebugCopyFile(
9316                                struct vnode *srcVp,
9317                                vfs_context_t srcCtx,
9318                                char *tmpBuf, uint64_t tmpBufSize,
9319                                uint64_t srcOffset,
9320                                const char *dstFname,
9321                                uint64_t numBytes,
9322                                uint32_t crc)
9323 {
9324     return EIO;
9325 }
9326 
9327 void IOPMrootDomain::sleepWakeDebugDumpFromFile()
9328 {
9329 }
9330 
9331 IOMemoryMap *IOPMrootDomain::sleepWakeDebugRetrieve( )
9332 {
9333    return NULL;
9334 }
9335 
9336 void IOPMrootDomain::sleepWakeDebugEnableWdog()
9337 {
9338 }
9339 
9340 bool IOPMrootDomain::sleepWakeDebugIsWdogEnabled()
9341 {
9342     return false;
9343 }
9344 
9345 errno_t IOPMrootDomain::sleepWakeDebugSaveFile(const char *name, char *buf, int len)
9346 {
9347     return 0;
9348 }
9349 
9350 #endif
9351 
9352