]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOPMrootDomain.cpp
2144447aed054d6cab564a3019dda20450e59fa6
[apple/xnu.git] / iokit / Kernel / IOPMrootDomain.cpp
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/OSDebug.h>
31 #include <IOKit/IOWorkLoop.h>
32 #include <IOKit/IOCommandGate.h>
33 #include <IOKit/IOPlatformExpert.h>
34 #include <IOKit/IOKitDebug.h>
35 #include <IOKit/IOTimeStamp.h>
36 #include <IOKit/pwr_mgt/IOPMlog.h>
37 #include <IOKit/pwr_mgt/RootDomain.h>
38 #include <IOKit/pwr_mgt/IOPMPrivate.h>
39 #include <IOKit/IODeviceTreeSupport.h>
40 #include <IOKit/IOMessage.h>
41 #include <IOKit/IOReturn.h>
42 #include "RootDomainUserClient.h"
43 #include "IOKit/pwr_mgt/IOPowerConnection.h"
44 #include "IOPMPowerStateQueue.h"
45 #include <IOKit/IOCatalogue.h>
46 #include <IOKit/IOCommand.h> // IOServicePMPrivate
47 #if HIBERNATION
48 #include <IOKit/IOHibernatePrivate.h>
49 #endif
50 #include <sys/syslog.h>
51 #include <sys/sysctl.h>
52 #include <sys/time.h>
53 #include "IOServicePrivate.h" // _IOServiceInterestNotifier
54 #include "IOServicePMPrivate.h"
55
56 __BEGIN_DECLS
57 #include <mach/shared_region.h>
58 __END_DECLS
59
60 #if defined(__i386__) || defined(__x86_64__)
61 __BEGIN_DECLS
62 #include "IOPMrootDomainInternal.h"
63 __END_DECLS
64 #endif
65
66 #define kIOPMrootDomainClass "IOPMrootDomain"
67
68 #define LOG_PREFIX "PMRD: "
69
70 #define LOG(x...) do { \
71 kprintf(LOG_PREFIX x); IOLog(x); } while (false)
72
73 #define KLOG(x...) do { \
74 kprintf(LOG_PREFIX x); } while (false)
75
76 #define DLOG(x...) do { \
77 if (kIOLogPMRootDomain & gIOKitDebug) \
78 kprintf(LOG_PREFIX x); } while (false)
79
80 #define CHECK_THREAD_CONTEXT
81 #ifdef CHECK_THREAD_CONTEXT
82 static IOWorkLoop * gIOPMWorkLoop = 0;
83 #define ASSERT_GATED(x) \
84 do { \
85 if (gIOPMWorkLoop && gIOPMWorkLoop->inGate() != true) { \
86 panic("RootDomain: not inside PM gate"); \
87 } \
88 } while(false)
89 #else
90 #define ASSERT_GATED(x)
91 #endif /* CHECK_THREAD_CONTEXT */
92
93 // Event types for IOPMPowerStateQueue::submitPowerEvent()
94 enum {
95 kPowerEventFeatureChanged = 1,
96 kPowerEventReceivedPowerNotification,
97 kPowerEventSystemBootCompleted,
98 kPowerEventSystemShutdown,
99 kPowerEventUserDisabledSleep,
100 kPowerEventConfigdRegisteredInterest,
101 kPowerEventAggressivenessChanged,
102 kPowerEventAssertionCreate, // 8
103 kPowerEventAssertionRelease, // 9
104 kPowerEventAssertionSetLevel // 10
105 };
106
107 extern "C" {
108 IOReturn OSKextSystemSleepOrWake( UInt32 );
109 }
110
111 extern const IORegistryPlane * gIOPowerPlane;
112
113 static void idleSleepTimerExpired( thread_call_param_t, thread_call_param_t );
114 static void wakeupClamshellTimerExpired( thread_call_param_t us, thread_call_param_t );
115 static void notifySystemShutdown( IOService * root, unsigned long event );
116 static bool clientMessageFilter( OSObject * object, void * context );
117 static void handleAggressivesFunction( thread_call_param_t param1, thread_call_param_t param2 );
118 static void pmEventTimeStamp(uint64_t *recordTS);
119
120 // "IOPMSetSleepSupported" callPlatformFunction name
121 static const OSSymbol *sleepSupportedPEFunction = NULL;
122 static const OSSymbol *sleepMessagePEFunction = NULL;
123
124 #define kIOSleepSupportedKey "IOSleepSupported"
125
126 #define kRD_AllPowerSources (kIOPMSupportedOnAC \
127 | kIOPMSupportedOnBatt \
128 | kIOPMSupportedOnUPS)
129
130 enum
131 {
132 // not idle around autowake time, secs
133 kAutoWakePreWindow = 45,
134 kAutoWakePostWindow = 15
135 };
136
137 #define kLocalEvalClamshellCommand (1 << 15)
138
139 enum {
140 OFF_STATE = 0,
141 RESTART_STATE = 1,
142 SLEEP_STATE = 2,
143 DOZE_STATE = 3,
144 ON_STATE = 4,
145 NUM_POWER_STATES
146 };
147
148 #define ON_POWER kIOPMPowerOn
149 #define RESTART_POWER kIOPMRestart
150 #define SLEEP_POWER kIOPMAuxPowerOn
151 #define DOZE_POWER kIOPMDoze
152
153 static IOPMPowerState ourPowerStates[NUM_POWER_STATES] =
154 {
155 {1, 0, 0, 0, 0,0,0,0,0,0,0,0},
156 {1, kIOPMRestartCapability, kIOPMRestart, RESTART_POWER, 0,0,0,0,0,0,0,0},
157 {1, kIOPMSleepCapability, kIOPMSleep, SLEEP_POWER, 0,0,0,0,0,0,0,0},
158 {1, kIOPMDoze, kIOPMDoze, DOZE_POWER, 0,0,0,0,0,0,0,0},
159 {1, kIOPMPowerOn, kIOPMPowerOn, ON_POWER, 0,0,0,0,0,0,0,0}
160 };
161
162 // Clients eligible to receive system power messages.
163 enum {
164 kMessageClientNone = 0,
165 kMessageClientAll,
166 kMessageClientConfigd
167 };
168
169 // Run states (R-state) defined within the ON power state.
170 enum {
171 kRStateNormal = 0,
172 kRStateDark,
173 kRStateMaintenance,
174 kRStateCount
175 };
176
177 // IOService in power plane can be tagged with following flags.
178 enum {
179 kServiceFlagGraphics = 0x01,
180 kServiceFlagNoPowerUp = 0x02,
181 kServiceFlagTopLevelPCI = 0x04
182 };
183
184 // Flags describing R-state features and capabilities.
185 enum {
186 kRStateFlagNone = 0x00000000,
187 kRStateFlagSuppressGraphics = 0x00000001,
188 kRStateFlagSuppressMessages = 0x00000002,
189 kRStateFlagSuppressPCICheck = 0x00000004,
190 kRStateFlagDisableIdleSleep = 0x00000008
191 };
192
193 #if ROOT_DOMAIN_RUN_STATES
194
195 // Table of flags for each R-state.
196 static uint32_t gRStateFlags[ kRStateCount ] =
197 {
198 kRStateFlagNone,
199
200 /* Dark wake */
201 kRStateFlagSuppressGraphics,
202
203 /* Maintenance wake */
204 kRStateFlagSuppressGraphics |
205 kRStateFlagSuppressMessages |
206 kRStateFlagSuppressPCICheck |
207 kRStateFlagDisableIdleSleep
208 };
209
210 static IONotifier * gConfigdNotifier = 0;
211
212 #define kIOPMRootDomainRunStateKey "Run State"
213 #define kIOPMRootDomainWakeTypeMaintenance "Maintenance"
214 #define kIOPMRootDomainWakeTypeSleepTimer "SleepTimer"
215 #define kIOPMrootDomainWakeTypeLowBattery "LowBattery"
216
217 #endif /* ROOT_DOMAIN_RUN_STATES */
218
219 // Special interest that entitles the interested client from receiving
220 // all system messages. Used by pmconfigd to support maintenance wake.
221 //
222 #define kIOPMPrivilegedPowerInterest "IOPMPrivilegedPowerInterest"
223
224 static IONotifier * gSysPowerDownNotifier = 0;
225
226 /*
227 * Aggressiveness
228 */
229 #define AGGRESSIVES_LOCK() IOLockLock(featuresDictLock)
230 #define AGGRESSIVES_UNLOCK() IOLockUnlock(featuresDictLock)
231
232 #define kAggressivesMinValue 1
233
234 static uint32_t gAggressivesState = 0;
235
236 enum {
237 kAggressivesStateBusy = 0x01,
238 kAggressivesStateQuickSpindown = 0x02
239 };
240
241 struct AggressivesRecord {
242 uint32_t flags;
243 uint32_t type;
244 uint32_t value;
245 };
246
247 struct AggressivesRequest {
248 queue_chain_t chain;
249 uint32_t options;
250 uint32_t dataType;
251 union {
252 IOService * service;
253 AggressivesRecord record;
254 } data;
255 };
256
257 enum {
258 kAggressivesRequestTypeService = 1,
259 kAggressivesRequestTypeRecord
260 };
261
262 enum {
263 kAggressivesOptionSynchronous = 0x00000001,
264 kAggressivesOptionQuickSpindownEnable = 0x00000100,
265 kAggressivesOptionQuickSpindownDisable = 0x00000200,
266 kAggressivesOptionQuickSpindownMask = 0x00000300
267 };
268
269 enum {
270 kAggressivesRecordFlagModified = 0x00000001,
271 kAggressivesRecordFlagMinValue = 0x00000002
272
273 };
274
275 static IOPMrootDomain * gRootDomain;
276 static UInt32 gSleepOrShutdownPending = 0;
277 static UInt32 gWillShutdown = 0;
278 static uint32_t gMessageClientType = kMessageClientNone;
279 static UInt32 gSleepWakeUUIDIsSet = false;
280
281 struct timeval gIOLastSleepTime;
282 struct timeval gIOLastWakeTime;
283
284 // Constants used as arguments to IOPMrootDomain::informCPUStateChange
285 #define kCPUUnknownIndex 9999999
286 enum {
287 kInformAC = 0,
288 kInformLid = 1,
289 kInformableCount = 2
290 };
291
292 const OSSymbol *gIOPMStatsApplicationResponseTimedOut;
293 const OSSymbol *gIOPMStatsApplicationResponseCancel;
294 const OSSymbol *gIOPMStatsApplicationResponseSlow;
295
296 class PMSettingObject : public OSObject
297 {
298 OSDeclareFinalStructors(PMSettingObject)
299 private:
300 IOPMrootDomain *parent;
301 IOPMSettingControllerCallback func;
302 OSObject *target;
303 uintptr_t refcon;
304 uint32_t *publishedFeatureID;
305 int releaseAtCount;
306 public:
307 static PMSettingObject *pmSettingObject(
308 IOPMrootDomain *parent_arg,
309 IOPMSettingControllerCallback handler_arg,
310 OSObject *target_arg,
311 uintptr_t refcon_arg,
312 uint32_t supportedPowerSources,
313 const OSSymbol *settings[]);
314
315 void setPMSetting(const OSSymbol *type, OSObject *obj);
316
317 void taggedRelease(const void *tag, const int when) const;
318 void free(void);
319 };
320
321 /*
322 * PMAssertionsTracker
323 * Tracks kernel and user space PM assertions
324 */
325 class PMAssertionsTracker : public OSObject
326 {
327 OSDeclareFinalStructors(PMAssertionsTracker)
328 public:
329 static PMAssertionsTracker *pmAssertionsTracker( IOPMrootDomain * );
330
331 IOReturn createAssertion(IOPMDriverAssertionType, IOPMDriverAssertionLevel, IOService *, const char *, IOPMDriverAssertionID *);
332 IOReturn releaseAssertion(IOPMDriverAssertionID);
333 IOReturn setAssertionLevel(IOPMDriverAssertionID, IOPMDriverAssertionLevel);
334 IOReturn setUserAssertionLevels(IOPMDriverAssertionType);
335
336 OSArray *copyAssertionsArray(void);
337 IOPMDriverAssertionType getActivatedAssertions(void);
338 IOPMDriverAssertionLevel getAssertionLevel(IOPMDriverAssertionType);
339
340 IOReturn handleCreateAssertion(OSData *);
341 IOReturn handleReleaseAssertion(IOPMDriverAssertionID);
342 IOReturn handleSetAssertionLevel(IOPMDriverAssertionID, IOPMDriverAssertionLevel);
343 IOReturn handleSetUserAssertionLevels(void * arg0);
344 void publishProperties(void);
345
346 private:
347 typedef struct {
348 IOPMDriverAssertionID id;
349 IOPMDriverAssertionType assertionBits;
350 uint64_t createdTime;
351 uint64_t modifiedTime;
352 const OSSymbol *ownerString;
353 IOService *ownerService;
354 IOPMDriverAssertionLevel level;
355 } PMAssertStruct;
356
357 uint32_t tabulateProducerCount;
358 uint32_t tabulateConsumerCount;
359
360 PMAssertStruct *detailsForID(IOPMDriverAssertionID, int *);
361 void tabulate(void);
362
363 IOPMrootDomain *owner;
364 OSArray *assertionsArray;
365 IOLock *assertionsArrayLock;
366 IOPMDriverAssertionID issuingUniqueID;
367 IOPMDriverAssertionType assertionsKernel;
368 IOPMDriverAssertionType assertionsUser;
369 IOPMDriverAssertionType assertionsCombined;
370 };
371
372 OSDefineMetaClassAndFinalStructors(PMAssertionsTracker, OSObject);
373
374 /*
375 * PMTraceWorker
376 * Internal helper object for logging trace points to RTC
377 * IOPMrootDomain and only IOPMrootDomain should instantiate
378 * exactly one of these.
379 */
380
381 typedef void (*IOPMTracePointHandler)(
382 void * target, uint32_t code, uint32_t data );
383
384 class PMTraceWorker : public OSObject
385 {
386 OSDeclareDefaultStructors(PMTraceWorker)
387 public:
388 typedef enum { kPowerChangeStart, kPowerChangeCompleted } change_t;
389
390 static PMTraceWorker *tracer( IOPMrootDomain * );
391 void tracePCIPowerChange(change_t, IOService *, uint32_t, uint32_t);
392 void tracePoint(uint8_t phase);
393 void traceLoginWindowPhase(uint8_t phase);
394 int recordTopLevelPCIDevice(IOService *);
395 void RTC_TRACE(void);
396 virtual bool serialize(OSSerialize *s) const;
397
398 IOPMTracePointHandler tracePointHandler;
399 void * tracePointTarget;
400 private:
401 IOPMrootDomain *owner;
402 IOLock *pciMappingLock;
403 OSArray *pciDeviceBitMappings;
404
405 uint8_t tracePhase;
406 uint8_t loginWindowPhase;
407 uint8_t addedToRegistry;
408 uint8_t unused0;
409 uint32_t pciBusyBitMask;
410 };
411
412 /*
413 * PMHaltWorker
414 * Internal helper object for Shutdown/Restart notifications.
415 */
416 #define kPMHaltMaxWorkers 8
417 #define kPMHaltTimeoutMS 100
418
419 class PMHaltWorker : public OSObject
420 {
421 OSDeclareFinalStructors( PMHaltWorker )
422
423 public:
424 IOService * service; // service being worked on
425 AbsoluteTime startTime; // time when work started
426 int depth; // work on nubs at this PM-tree depth
427 int visits; // number of nodes visited (debug)
428 IOLock * lock;
429 bool timeout; // service took too long
430
431 static PMHaltWorker * worker( void );
432 static void main( void * arg, wait_result_t waitResult );
433 static void work( PMHaltWorker * me );
434 static void checkTimeout( PMHaltWorker * me, AbsoluteTime * now );
435 virtual void free( void );
436 };
437
438 OSDefineMetaClassAndFinalStructors( PMHaltWorker, OSObject )
439
440
441 #define super IOService
442 OSDefineMetaClassAndFinalStructors(IOPMrootDomain, IOService)
443
444 extern "C"
445 {
446 IONotifier * registerSleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref)
447 {
448 return gRootDomain->registerInterest( gIOGeneralInterest, handler, self, ref );
449 }
450
451 IONotifier * registerPrioritySleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref)
452 {
453 return gRootDomain->registerInterest( gIOPriorityPowerStateInterest, handler, self, ref );
454 }
455
456 IOReturn acknowledgeSleepWakeNotification(void * PMrefcon)
457 {
458 return gRootDomain->allowPowerChange ( (unsigned long)PMrefcon );
459 }
460
461 IOReturn vetoSleepWakeNotification(void * PMrefcon)
462 {
463 return gRootDomain->cancelPowerChange ( (unsigned long)PMrefcon );
464 }
465
466 IOReturn rootDomainRestart ( void )
467 {
468 return gRootDomain->restartSystem();
469 }
470
471 IOReturn rootDomainShutdown ( void )
472 {
473 return gRootDomain->shutdownSystem();
474 }
475
476 void IOSystemShutdownNotification ( void )
477 {
478 if (OSCompareAndSwap(0, 1, &gWillShutdown))
479 {
480 OSKext::willShutdown();
481 for (int i = 0; i < 100; i++)
482 {
483 if (OSCompareAndSwap(0, 1, &gSleepOrShutdownPending)) break;
484 IOSleep( 100 );
485 }
486 }
487 }
488
489 int sync_internal(void);
490 }
491
492 /*
493 A device is always in the highest power state which satisfies its driver, its policy-maker, and any power domain
494 children it has, but within the constraint of the power state provided by its parent. The driver expresses its desire by
495 calling changePowerStateTo(), the policy-maker expresses its desire by calling changePowerStateToPriv(), and the children
496 express their desires by calling requestPowerDomainState().
497
498 The Root Power Domain owns the policy for idle and demand sleep and doze for the system. It is a power-managed IOService just
499 like the others in the system. It implements several power states which correspond to what we see as Sleep, Doze, etc.
500
501 The sleep/doze policy is as follows:
502 Sleep and Doze are prevented if the case is open so that nobody will think the machine is off and plug/unplug cards.
503 Sleep and Doze are prevented if the sleep timeout slider in the preferences panel is at zero.
504 The system cannot Sleep, but can Doze if some object in the tree is in a power state marked kIOPMPreventSystemSleep.
505
506 These three conditions are enforced using the "driver clamp" by calling changePowerStateTo(). For example, if the case is
507 opened, changePowerStateTo(ON_STATE) is called to hold the system on regardless of the desires of the children of the root or
508 the state of the other clamp.
509
510 Demand Sleep/Doze is initiated by pressing the front panel power button, closing the clamshell, or selecting the menu item.
511 In this case the root's parent actually initiates the power state change so that the root has no choice and does not give
512 applications the opportunity to veto the change.
513
514 Idle Sleep/Doze occurs if no objects in the tree are in a state marked kIOPMPreventIdleSleep. When this is true, the root's
515 children are not holding the root on, so it sets the "policy-maker clamp" by calling changePowerStateToPriv(ON_STATE)
516 to hold itself on until the sleep timer expires. This timer is set for the difference between the sleep timeout slider and
517 the larger of the display dim timeout slider and the disk spindown timeout slider in the Preferences panel. For example, if
518 the system is set to sleep after thirty idle minutes, and the display and disk are set to sleep after five idle minutes,
519 when there is no longer an object in the tree holding the system out of Idle Sleep (via kIOPMPreventIdleSleep), the root
520 sets its timer for 25 minutes (30 - 5). When the timer expires, it releases its clamp and now nothing is holding it awake,
521 so it falls asleep.
522
523 Demand sleep is prevented when the system is booting. When preferences are transmitted by the loginwindow at the end of
524 boot, a flag is cleared, and this allows subsequent Demand Sleep.
525
526 The system will not Sleep, but will Doze if some object calls setSleepSupported(kPCICantSleep) during a power change to the sleep state (this can be done by the PCI Aux Power Supply drivers, Slots99, MacRISC299, etc.). This is not enforced with
527 a clamp, but sets a flag which is noticed before actually sleeping the kernel. If the flag is set, the root steps up
528 one power state from Sleep to Doze, and any objects in the tree for which this is relevent will act appropriately (USB and
529 ADB will turn on again so that they can wake the system out of Doze (keyboard/mouse activity will cause the Display Wrangler
530 to be tickled)).
531 */
532
533 //******************************************************************************
534
535 IOPMrootDomain * IOPMrootDomain::construct( void )
536 {
537 IOPMrootDomain *root;
538
539 root = new IOPMrootDomain;
540 if( root)
541 root->init();
542
543 return( root );
544 }
545
546 //******************************************************************************
547
548 static void disk_sync_callout( thread_call_param_t p0, thread_call_param_t p1 )
549 {
550 IOService *rootDomain = (IOService *) p0;
551 unsigned long pmRef = (unsigned long) p1;
552
553 DLOG("disk_sync_callout start\n");
554
555 #if HIBERNATION
556 IOHibernateSystemSleep();
557 #endif
558 sync_internal();
559 rootDomain->allowPowerChange(pmRef);
560 DLOG("disk_sync_callout finish\n");
561 }
562
563 //******************************************************************************
564
565 static UInt32 computeDeltaTimeMS( const AbsoluteTime * startTime )
566 {
567 AbsoluteTime endTime;
568 UInt64 nano = 0;
569
570 clock_get_uptime(&endTime);
571 if (CMP_ABSOLUTETIME(&endTime, startTime) > 0)
572 {
573 SUB_ABSOLUTETIME(&endTime, startTime);
574 absolutetime_to_nanoseconds(endTime, &nano);
575 }
576
577 return (UInt32)(nano / 1000000ULL);
578 }
579
580 //******************************************************************************
581
582 static int
583 sysctl_sleepwaketime SYSCTL_HANDLER_ARGS
584 {
585 struct timeval *swt = (struct timeval *)arg1;
586 struct proc *p = req->p;
587
588 if (p == kernproc) {
589 return sysctl_io_opaque(req, swt, sizeof(*swt), NULL);
590 } else if(proc_is64bit(p)) {
591 struct user64_timeval t;
592 t.tv_sec = swt->tv_sec;
593 t.tv_usec = swt->tv_usec;
594 return sysctl_io_opaque(req, &t, sizeof(t), NULL);
595 } else {
596 struct user32_timeval t;
597 t.tv_sec = swt->tv_sec;
598 t.tv_usec = swt->tv_usec;
599 return sysctl_io_opaque(req, &t, sizeof(t), NULL);
600 }
601 }
602
603 static SYSCTL_PROC(_kern, OID_AUTO, sleeptime,
604 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN,
605 &gIOLastSleepTime, 0, sysctl_sleepwaketime, "S,timeval", "");
606
607 static SYSCTL_PROC(_kern, OID_AUTO, waketime,
608 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN,
609 &gIOLastWakeTime, 0, sysctl_sleepwaketime, "S,timeval", "");
610
611
612 static int
613 sysctl_willshutdown
614 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
615 {
616 int new_value, changed;
617 int error = sysctl_io_number(req, gWillShutdown, sizeof(int), &new_value, &changed);
618 if (changed) {
619 if (!gWillShutdown && (new_value == 1)) {
620 IOSystemShutdownNotification();
621 } else
622 error = EINVAL;
623 }
624 return(error);
625 }
626
627 static SYSCTL_PROC(_kern, OID_AUTO, willshutdown,
628 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN,
629 0, 0, sysctl_willshutdown, "I", "");
630
631 #if !CONFIG_EMBEDDED
632
633 static int
634 sysctl_progressmeterenable
635 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
636 {
637 int error;
638 int new_value, changed;
639
640 error = sysctl_io_number(req, vc_progress_meter_enable, sizeof(int), &new_value, &changed);
641
642 if (changed)
643 vc_enable_progressmeter(new_value);
644
645 return (error);
646 }
647
648 static int
649 sysctl_progressmeter
650 (__unused struct sysctl_oid *oidp, __unused void *arg1, __unused int arg2, struct sysctl_req *req)
651 {
652 int error;
653 int new_value, changed;
654
655 error = sysctl_io_number(req, vc_progress_meter_value, sizeof(int), &new_value, &changed);
656
657 if (changed)
658 vc_set_progressmeter(new_value);
659
660 return (error);
661 }
662
663 static SYSCTL_PROC(_kern, OID_AUTO, progressmeterenable,
664 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN,
665 0, 0, sysctl_progressmeterenable, "I", "");
666
667 static SYSCTL_PROC(_kern, OID_AUTO, progressmeter,
668 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN,
669 0, 0, sysctl_progressmeter, "I", "");
670
671 #endif
672
673 static const OSSymbol * gIOPMSettingAutoWakeSecondsKey;
674 static const OSSymbol * gIOPMSettingMaintenanceWakeCalendarKey;
675
676 //******************************************************************************
677 // start
678 //
679 //******************************************************************************
680
681 #define kRootDomainSettingsCount 16
682
683 bool IOPMrootDomain::start( IOService * nub )
684 {
685 OSIterator *psIterator;
686 OSDictionary *tmpDict;
687
688 super::start(nub);
689
690 gRootDomain = this;
691 gIOPMSettingAutoWakeSecondsKey = OSSymbol::withCString(kIOPMSettingAutoWakeSecondsKey);
692 gIOPMSettingMaintenanceWakeCalendarKey =
693 OSSymbol::withCString(kIOPMSettingMaintenanceWakeCalendarKey);
694
695 gIOPMStatsApplicationResponseTimedOut = OSSymbol::withCString(kIOPMStatsResponseTimedOut);
696 gIOPMStatsApplicationResponseCancel = OSSymbol::withCString(kIOPMStatsResponseCancel);
697 gIOPMStatsApplicationResponseSlow = OSSymbol::withCString(kIOPMStatsResponseSlow);
698
699 sleepSupportedPEFunction = OSSymbol::withCString("IOPMSetSleepSupported");
700 sleepMessagePEFunction = OSSymbol::withCString("IOPMSystemSleepMessage");
701
702 const OSSymbol *settingsArr[kRootDomainSettingsCount] =
703 {
704 OSSymbol::withCString(kIOPMSettingSleepOnPowerButtonKey),
705 gIOPMSettingAutoWakeSecondsKey,
706 OSSymbol::withCString(kIOPMSettingAutoPowerSecondsKey),
707 OSSymbol::withCString(kIOPMSettingAutoWakeCalendarKey),
708 OSSymbol::withCString(kIOPMSettingAutoPowerCalendarKey),
709 OSSymbol::withCString(kIOPMSettingDebugWakeRelativeKey),
710 OSSymbol::withCString(kIOPMSettingDebugPowerRelativeKey),
711 OSSymbol::withCString(kIOPMSettingWakeOnRingKey),
712 OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey),
713 OSSymbol::withCString(kIOPMSettingWakeOnClamshellKey),
714 OSSymbol::withCString(kIOPMSettingWakeOnACChangeKey),
715 OSSymbol::withCString(kIOPMSettingTimeZoneOffsetKey),
716 OSSymbol::withCString(kIOPMSettingDisplaySleepUsesDimKey),
717 OSSymbol::withCString(kIOPMSettingMobileMotionModuleKey),
718 OSSymbol::withCString(kIOPMSettingGraphicsSwitchKey),
719 OSSymbol::withCString(kIOPMStateConsoleShutdown)
720 };
721
722 queue_init(&aggressivesQueue);
723 aggressivesThreadCall = thread_call_allocate(handleAggressivesFunction, this);
724 aggressivesData = OSData::withCapacity(
725 sizeof(AggressivesRecord) * (kPMLastAggressivenessType + 4));
726
727 featuresDictLock = IOLockAlloc();
728 settingsCtrlLock = IORecursiveLockAlloc();
729 setPMRootDomain(this);
730
731 extraSleepTimer = thread_call_allocate(
732 idleSleepTimerExpired,
733 (thread_call_param_t) this);
734
735 clamshellWakeupIgnore = thread_call_allocate(
736 wakeupClamshellTimerExpired,
737 (thread_call_param_t) this);
738
739 diskSyncCalloutEntry = thread_call_allocate(
740 &disk_sync_callout,
741 (thread_call_param_t) this);
742
743 canSleep = true;
744 setProperty(kIOSleepSupportedKey, true);
745
746 bzero(&pmStats, sizeof(pmStats));
747
748 pmTracer = PMTraceWorker::tracer(this);
749
750 pmAssertions = PMAssertionsTracker::pmAssertionsTracker(this);
751
752 updateRunState(kRStateNormal);
753 userDisabledAllSleep = false;
754 allowSleep = true;
755 sleepIsSupported = true;
756 systemBooting = true;
757 sleepSlider = 0;
758 idleSleepTimerPending = false;
759 wrangler = NULL;
760 sleepASAP = false;
761 clamshellIsClosed = false;
762 clamshellExists = false;
763 ignoringClamshell = true;
764 ignoringClamshellOnWake = false;
765 acAdaptorConnected = true;
766
767 queuedSleepWakeUUIDString = NULL;
768 pmStatsAppResponses = OSArray::withCapacity(5);
769 _statsNameKey = OSSymbol::withCString(kIOPMStatsNameKey);
770 _statsPIDKey = OSSymbol::withCString(kIOPMStatsPIDKey);
771 _statsTimeMSKey = OSSymbol::withCString(kIOPMStatsTimeMSKey);
772 _statsResponseTypeKey = OSSymbol::withCString(kIOPMStatsApplicationResponseTypeKey);
773 _statsMessageTypeKey = OSSymbol::withCString(kIOPMStatsMessageTypeKey);
774
775 idxPMCPUClamshell = kCPUUnknownIndex;
776 idxPMCPULimitedPower = kCPUUnknownIndex;
777
778 tmpDict = OSDictionary::withCapacity(1);
779 setProperty(kRootDomainSupportedFeatures, tmpDict);
780 tmpDict->release();
781
782 settingsCallbacks = OSDictionary::withCapacity(1);
783
784 // Create a list of the valid PM settings that we'll relay to
785 // interested clients in setProperties() => setPMSetting()
786 allowedPMSettings = OSArray::withObjects(
787 (const OSObject **)settingsArr,
788 kRootDomainSettingsCount,
789 0);
790
791 fPMSettingsDict = OSDictionary::withCapacity(5);
792
793 PMinit(); // creates gIOPMWorkLoop
794
795 // Create IOPMPowerStateQueue used to queue external power
796 // events, and to handle those events on the PM work loop.
797 pmPowerStateQueue = IOPMPowerStateQueue::PMPowerStateQueue(
798 this, OSMemberFunctionCast(IOEventSource::Action, this,
799 &IOPMrootDomain::dispatchPowerEvent));
800 getPMworkloop()->addEventSource(pmPowerStateQueue);
801 #ifdef CHECK_THREAD_CONTEXT
802 gIOPMWorkLoop = getPMworkloop();
803 #endif
804
805 // create our power parent
806 patriarch = new IORootParent;
807 patriarch->init();
808 patriarch->attach(this);
809 patriarch->start(this);
810 patriarch->addPowerChild(this);
811
812 registerPowerDriver(this, ourPowerStates, NUM_POWER_STATES);
813
814 // set a clamp until we sleep
815 changePowerStateToPriv(ON_STATE);
816
817 // install power change handler
818 gSysPowerDownNotifier = registerPrioritySleepWakeInterest( &sysPowerDownHandler, this, 0);
819
820 #if !NO_KERNEL_HID
821 // Register for a notification when IODisplayWrangler is published
822 if ((tmpDict = serviceMatching("IODisplayWrangler")))
823 {
824 _displayWranglerNotifier = addMatchingNotification(
825 gIOPublishNotification, tmpDict,
826 (IOServiceMatchingNotificationHandler) &displayWranglerPublished,
827 this, 0);
828 tmpDict->release();
829 }
830 #endif
831
832 // Battery location published - ApplePMU support only
833 if ((tmpDict = serviceMatching("IOPMPowerSource")))
834 {
835 _batteryPublishNotifier = addMatchingNotification(
836 gIOPublishNotification, tmpDict,
837 (IOServiceMatchingNotificationHandler) &batteryPublished,
838 this, this);
839 tmpDict->release();
840 }
841
842 const OSSymbol *ucClassName = OSSymbol::withCStringNoCopy("RootDomainUserClient");
843 setProperty(gIOUserClientClassKey, (OSObject *) ucClassName);
844 ucClassName->release();
845
846 // IOBacklightDisplay can take a long time to load at boot, or it may
847 // not load at all if you're booting with clamshell closed. We publish
848 // 'DisplayDims' here redundantly to get it published early and at all.
849 psIterator = getMatchingServices( serviceMatching("IOPMPowerSource") );
850 if( psIterator && psIterator->getNextObject() )
851 {
852 // There's at least one battery on the system, so we publish
853 // 'DisplayDims' support for the LCD.
854 publishFeature("DisplayDims");
855 }
856 if(psIterator) {
857 psIterator->release();
858 }
859
860 sysctl_register_oid(&sysctl__kern_sleeptime);
861 sysctl_register_oid(&sysctl__kern_waketime);
862 sysctl_register_oid(&sysctl__kern_willshutdown);
863 #if !CONFIG_EMBEDDED
864 sysctl_register_oid(&sysctl__kern_progressmeterenable);
865 sysctl_register_oid(&sysctl__kern_progressmeter);
866 #endif /* !CONFIG_EMBEDDED */
867
868 #if HIBERNATION
869 IOHibernateSystemInit(this);
870 #endif
871
872 registerService(); // let clients find us
873
874 return true;
875 }
876
877
878 //******************************************************************************
879 // setProperties
880 //
881 // Receive a setProperty call
882 // The "System Boot" property means the system is completely booted.
883 //******************************************************************************
884
885 IOReturn IOPMrootDomain::setProperties( OSObject * props_obj )
886 {
887 IOReturn return_value = kIOReturnSuccess;
888 OSDictionary *dict = OSDynamicCast(OSDictionary, props_obj);
889 OSBoolean *b;
890 OSNumber *n;
891 OSString *str;
892 OSSymbol *type;
893 OSObject *obj;
894 unsigned int i;
895
896 const OSSymbol *boot_complete_string =
897 OSSymbol::withCString("System Boot Complete");
898 const OSSymbol *sys_shutdown_string =
899 OSSymbol::withCString("System Shutdown");
900 const OSSymbol *stall_halt_string =
901 OSSymbol::withCString("StallSystemAtHalt");
902 const OSSymbol *battery_warning_disabled_string =
903 OSSymbol::withCString("BatteryWarningsDisabled");
904 const OSSymbol *idle_seconds_string =
905 OSSymbol::withCString("System Idle Seconds");
906 #if HIBERNATION
907 const OSSymbol *hibernatemode_string =
908 OSSymbol::withCString(kIOHibernateModeKey);
909 const OSSymbol *hibernatefile_string =
910 OSSymbol::withCString(kIOHibernateFileKey);
911 const OSSymbol *hibernatefreeratio_string =
912 OSSymbol::withCString(kIOHibernateFreeRatioKey);
913 const OSSymbol *hibernatefreetime_string =
914 OSSymbol::withCString(kIOHibernateFreeTimeKey);
915 #endif
916 const OSSymbol *sleepdisabled_string =
917 OSSymbol::withCString("SleepDisabled");
918 const OSSymbol *ondeck_sleepwake_uuid_string =
919 OSSymbol::withCString(kIOPMSleepWakeUUIDKey);
920 const OSSymbol *loginwindow_tracepoint_string =
921 OSSymbol::withCString(kIOPMLoginWindowSecurityDebugKey);
922
923 if(!dict)
924 {
925 return_value = kIOReturnBadArgument;
926 goto exit;
927 }
928
929 if ((n = OSDynamicCast(OSNumber, dict->getObject(idle_seconds_string))))
930 {
931 setProperty(idle_seconds_string, n);
932 idleSeconds = n->unsigned32BitValue();
933 }
934
935 if (boot_complete_string && dict->getObject(boot_complete_string))
936 {
937 pmPowerStateQueue->submitPowerEvent( kPowerEventSystemBootCompleted );
938 }
939
940 if( battery_warning_disabled_string
941 && dict->getObject(battery_warning_disabled_string))
942 {
943 setProperty( battery_warning_disabled_string,
944 dict->getObject(battery_warning_disabled_string));
945 }
946
947 if( sys_shutdown_string
948 && (b = OSDynamicCast(OSBoolean, dict->getObject(sys_shutdown_string))))
949 {
950 pmPowerStateQueue->submitPowerEvent(kPowerEventSystemShutdown, (void *) b);
951 }
952
953 if( stall_halt_string
954 && (b = OSDynamicCast(OSBoolean, dict->getObject(stall_halt_string))) )
955 {
956 setProperty(stall_halt_string, b);
957 }
958
959 #if HIBERNATION
960 if ( hibernatemode_string
961 && (n = OSDynamicCast(OSNumber, dict->getObject(hibernatemode_string))))
962 {
963 setProperty(hibernatemode_string, n);
964 }
965 if ( hibernatefreeratio_string
966 && (n = OSDynamicCast(OSNumber, dict->getObject(hibernatefreeratio_string))))
967 {
968 setProperty(hibernatefreeratio_string, n);
969 }
970 if ( hibernatefreetime_string
971 && (n = OSDynamicCast(OSNumber, dict->getObject(hibernatefreetime_string))))
972 {
973 setProperty(hibernatefreetime_string, n);
974 }
975 if ( hibernatefile_string
976 && (str = OSDynamicCast(OSString, dict->getObject(hibernatefile_string))))
977 {
978 setProperty(hibernatefile_string, str);
979 }
980 #endif
981
982 if( sleepdisabled_string
983 && (b = OSDynamicCast(OSBoolean, dict->getObject(sleepdisabled_string))) )
984 {
985 setProperty(sleepdisabled_string, b);
986 pmPowerStateQueue->submitPowerEvent(kPowerEventUserDisabledSleep, (void *) b);
987 }
988
989 if (ondeck_sleepwake_uuid_string
990 && (obj = dict->getObject(ondeck_sleepwake_uuid_string)))
991 {
992 // Clear the currently published UUID
993 if (kOSBooleanFalse == obj)
994 {
995 publishSleepWakeUUID(NULL);
996 }
997
998 // Cache UUID for an upcoming sleep/wake
999 if ((str = OSDynamicCast(OSString, obj)))
1000 {
1001 if (queuedSleepWakeUUIDString) {
1002 queuedSleepWakeUUIDString->release();
1003 queuedSleepWakeUUIDString = NULL;
1004 }
1005 queuedSleepWakeUUIDString = str;
1006 queuedSleepWakeUUIDString->retain();
1007 DLOG("SleepWake UUID queued: %s\n",
1008 queuedSleepWakeUUIDString->getCStringNoCopy());
1009 }
1010 }
1011
1012 if (loginwindow_tracepoint_string
1013 && (n = OSDynamicCast(OSNumber, dict->getObject(loginwindow_tracepoint_string)))
1014 && pmTracer)
1015 {
1016 pmTracer->traceLoginWindowPhase( n->unsigned8BitValue() );
1017 }
1018
1019 if ((b = OSDynamicCast(OSBoolean, dict->getObject(kIOPMDeepSleepEnabledKey))))
1020 {
1021 setProperty(kIOPMDeepSleepEnabledKey, b);
1022 }
1023 if ((n = OSDynamicCast(OSNumber, dict->getObject(kIOPMDeepSleepDelayKey))))
1024 {
1025 setProperty(kIOPMDeepSleepDelayKey, n);
1026 }
1027
1028 // Relay our allowed PM settings onto our registered PM clients
1029 for(i = 0; i < allowedPMSettings->getCount(); i++) {
1030
1031 type = (OSSymbol *)allowedPMSettings->getObject(i);
1032 if(!type) continue;
1033
1034 obj = dict->getObject(type);
1035 if(!obj) continue;
1036
1037 if ((gIOPMSettingAutoWakeSecondsKey == type) && ((n = OSDynamicCast(OSNumber, obj))))
1038 {
1039 UInt32 rsecs = n->unsigned32BitValue();
1040 if (!rsecs)
1041 autoWakeStart = autoWakeEnd = 0;
1042 else
1043 {
1044 AbsoluteTime deadline;
1045 clock_interval_to_deadline(rsecs + kAutoWakePostWindow, kSecondScale, &deadline);
1046 autoWakeEnd = AbsoluteTime_to_scalar(&deadline);
1047 if (rsecs > kAutoWakePreWindow)
1048 rsecs -= kAutoWakePreWindow;
1049 else
1050 rsecs = 0;
1051 clock_interval_to_deadline(rsecs, kSecondScale, &deadline);
1052 autoWakeStart = AbsoluteTime_to_scalar(&deadline);
1053 }
1054 }
1055
1056 return_value = setPMSetting(type, obj);
1057
1058 if(kIOReturnSuccess != return_value) goto exit;
1059 }
1060
1061 exit:
1062 if(boot_complete_string) boot_complete_string->release();
1063 if(sys_shutdown_string) sys_shutdown_string->release();
1064 if(stall_halt_string) stall_halt_string->release();
1065 if (battery_warning_disabled_string) battery_warning_disabled_string->release();
1066 if(idle_seconds_string) idle_seconds_string->release();
1067 if(sleepdisabled_string) sleepdisabled_string->release();
1068 if(ondeck_sleepwake_uuid_string) ondeck_sleepwake_uuid_string->release();
1069 if(loginwindow_tracepoint_string) loginwindow_tracepoint_string->release();
1070 #if HIBERNATION
1071 if(hibernatemode_string) hibernatemode_string->release();
1072 if(hibernatefile_string) hibernatefile_string->release();
1073 if(hibernatefreeratio_string) hibernatefreeratio_string->release();
1074 if(hibernatefreetime_string) hibernatefreetime_string->release();
1075 #endif
1076 return return_value;
1077 }
1078
1079
1080 //******************************************************************************
1081 // aggressivenessChanged
1082 //
1083 // We are behind the command gate to examine changes to aggressives.
1084 //******************************************************************************
1085
1086 void IOPMrootDomain::aggressivenessChanged( void )
1087 {
1088 unsigned long minutesToSleep = 0;
1089 unsigned long minutesToDisplayDim = 0;
1090
1091 ASSERT_GATED();
1092
1093 // Fetch latest display and system sleep slider values.
1094 getAggressiveness(kPMMinutesToSleep, &minutesToSleep);
1095 getAggressiveness(kPMMinutesToDim, &minutesToDisplayDim);
1096 DLOG("aggressiveness changed system %u, display %u\n",
1097 (uint32_t) minutesToSleep, (uint32_t) minutesToDisplayDim);
1098
1099 DLOG("idle time -> %ld secs (ena %d)\n",
1100 idleSeconds, (minutesToSleep != 0));
1101
1102 if (0x7fffffff == minutesToSleep)
1103 minutesToSleep = idleSeconds;
1104
1105 // How long to wait before sleeping the system once the displays turns
1106 // off is indicated by 'extraSleepDelay'.
1107
1108 if ( minutesToSleep > minutesToDisplayDim ) {
1109 extraSleepDelay = minutesToSleep - minutesToDisplayDim;
1110 }
1111 else {
1112 extraSleepDelay = 0;
1113 }
1114
1115 // system sleep timer was disabled, but not anymore.
1116 if ( (sleepSlider == 0) && (minutesToSleep != 0) ) {
1117 if (!wrangler)
1118 {
1119 sleepASAP = false;
1120 changePowerStateToPriv(ON_STATE);
1121 if (idleSeconds)
1122 {
1123 startIdleSleepTimer( idleSeconds );
1124 }
1125 }
1126 else
1127 {
1128 // Start idle sleep timer if wrangler went to sleep
1129 // while system sleep was disabled.
1130
1131 sleepASAP = false;
1132 if (wranglerAsleep)
1133 {
1134 AbsoluteTime now;
1135 uint64_t nanos;
1136 uint32_t minutesSinceDisplaySleep = 0;
1137 uint32_t sleepDelay;
1138
1139 clock_get_uptime(&now);
1140 if (CMP_ABSOLUTETIME(&now, &wranglerSleepTime) > 0)
1141 {
1142 SUB_ABSOLUTETIME(&now, &wranglerSleepTime);
1143 absolutetime_to_nanoseconds(now, &nanos);
1144 minutesSinceDisplaySleep = nanos / (60000000000ULL);
1145 }
1146
1147 if (extraSleepDelay > minutesSinceDisplaySleep)
1148 {
1149 sleepDelay = extraSleepDelay - minutesSinceDisplaySleep;
1150 }
1151 else
1152 {
1153 // 1 min idle sleep.
1154 sleepDelay = 1;
1155 }
1156
1157 startIdleSleepTimer(sleepDelay * 60);
1158 DLOG("display slept %u min, set idle timer to %u min\n",
1159 minutesSinceDisplaySleep, sleepDelay);
1160 }
1161 }
1162 }
1163
1164 sleepSlider = minutesToSleep;
1165 if ( sleepSlider == 0 ) {
1166 cancelIdleSleepTimer();
1167 // idle sleep is now disabled
1168 adjustPowerState();
1169 // make sure we're powered
1170 patriarch->wakeSystem();
1171 }
1172 }
1173
1174
1175 //******************************************************************************
1176 // setAggressiveness
1177 //
1178 // Override IOService::setAggressiveness()
1179 //******************************************************************************
1180
1181 IOReturn IOPMrootDomain::setAggressiveness(
1182 unsigned long type,
1183 unsigned long value )
1184 {
1185 return setAggressiveness( type, value, 0 );
1186 }
1187
1188 /*
1189 * Private setAggressiveness() with an internal options argument.
1190 */
1191 IOReturn IOPMrootDomain::setAggressiveness(
1192 unsigned long type,
1193 unsigned long value,
1194 IOOptionBits options )
1195 {
1196 AggressivesRequest * entry;
1197 AggressivesRequest * request;
1198 bool found = false;
1199
1200 DLOG("setAggressiveness 0x%x = %u, options 0x%x\n",
1201 (uint32_t) type, (uint32_t) value, (uint32_t) options);
1202
1203 request = IONew(AggressivesRequest, 1);
1204 if (!request)
1205 return kIOReturnNoMemory;
1206
1207 memset(request, 0, sizeof(*request));
1208 request->options = options;
1209 request->dataType = kAggressivesRequestTypeRecord;
1210 request->data.record.type = (uint32_t) type;
1211 request->data.record.value = (uint32_t) value;
1212
1213 AGGRESSIVES_LOCK();
1214
1215 // Update disk quick spindown flag used by getAggressiveness().
1216 // Never merge requests with quick spindown flags set.
1217
1218 if (options & kAggressivesOptionQuickSpindownEnable)
1219 gAggressivesState |= kAggressivesStateQuickSpindown;
1220 else if (options & kAggressivesOptionQuickSpindownDisable)
1221 gAggressivesState &= ~kAggressivesStateQuickSpindown;
1222 else
1223 {
1224 // Coalesce requests with identical aggressives types.
1225 // Deal with callers that calls us too "aggressively".
1226
1227 queue_iterate(&aggressivesQueue, entry, AggressivesRequest *, chain)
1228 {
1229 if ((entry->dataType == kAggressivesRequestTypeRecord) &&
1230 (entry->data.record.type == type) &&
1231 ((entry->options & kAggressivesOptionQuickSpindownMask) == 0))
1232 {
1233 entry->data.record.value = value;
1234 found = true;
1235 break;
1236 }
1237 }
1238 }
1239
1240 if (!found)
1241 {
1242 queue_enter(&aggressivesQueue, request, AggressivesRequest *, chain);
1243 }
1244
1245 AGGRESSIVES_UNLOCK();
1246
1247 if (found)
1248 IODelete(request, AggressivesRequest, 1);
1249
1250 if (options & kAggressivesOptionSynchronous)
1251 handleAggressivesRequests(); // not truly synchronous
1252 else
1253 thread_call_enter(aggressivesThreadCall);
1254
1255 return kIOReturnSuccess;
1256 }
1257
1258
1259 //******************************************************************************
1260 // getAggressiveness
1261 //
1262 // Override IOService::setAggressiveness()
1263 // Fetch the aggressiveness factor with the given type.
1264 //******************************************************************************
1265
1266 IOReturn IOPMrootDomain::getAggressiveness (
1267 unsigned long type,
1268 unsigned long * outLevel )
1269 {
1270 uint32_t value = 0;
1271 int source = 0;
1272
1273 if (!outLevel)
1274 return kIOReturnBadArgument;
1275
1276 AGGRESSIVES_LOCK();
1277
1278 // Disk quick spindown in effect, report value = 1
1279
1280 if ((gAggressivesState & kAggressivesStateQuickSpindown) &&
1281 (type == kPMMinutesToSpinDown))
1282 {
1283 value = kAggressivesMinValue;
1284 source = 1;
1285 }
1286
1287 // Consult the pending request queue.
1288
1289 if (!source)
1290 {
1291 AggressivesRequest * entry;
1292
1293 queue_iterate(&aggressivesQueue, entry, AggressivesRequest *, chain)
1294 {
1295 if ((entry->dataType == kAggressivesRequestTypeRecord) &&
1296 (entry->data.record.type == type) &&
1297 ((entry->options & kAggressivesOptionQuickSpindownMask) == 0))
1298 {
1299 value = entry->data.record.value;
1300 source = 2;
1301 break;
1302 }
1303 }
1304 }
1305
1306 // Consult the backend records.
1307
1308 if (!source && aggressivesData)
1309 {
1310 AggressivesRecord * record;
1311 int i, count;
1312
1313 count = aggressivesData->getLength() / sizeof(AggressivesRecord);
1314 record = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
1315
1316 for (i = 0; i < count; i++, record++)
1317 {
1318 if (record->type == type)
1319 {
1320 value = record->value;
1321 source = 3;
1322 break;
1323 }
1324 }
1325 }
1326
1327 AGGRESSIVES_UNLOCK();
1328
1329 if (source)
1330 {
1331 DLOG("getAggressiveness 0x%x = %u, source %d\n",
1332 (uint32_t) type, value, source);
1333 *outLevel = (unsigned long) value;
1334 return kIOReturnSuccess;
1335 }
1336 else
1337 {
1338 DLOG("getAggressiveness type 0x%x not found\n", (uint32_t) type);
1339 *outLevel = 0; // default return = 0, driver may not check for error
1340 return kIOReturnInvalid;
1341 }
1342 }
1343
1344
1345 //******************************************************************************
1346 // joinAggressiveness
1347 //
1348 // Request from IOService to join future aggressiveness broadcasts.
1349 //******************************************************************************
1350
1351 IOReturn IOPMrootDomain::joinAggressiveness(
1352 IOService * service )
1353 {
1354 AggressivesRequest * request;
1355
1356 if (!service || (service == this))
1357 return kIOReturnBadArgument;
1358
1359 DLOG("joinAggressiveness %s (%p)\n", service->getName(), service);
1360
1361 request = IONew(AggressivesRequest, 1);
1362 if (!request)
1363 return kIOReturnNoMemory;
1364
1365 service->retain(); // released by synchronizeAggressives()
1366
1367 memset(request, 0, sizeof(*request));
1368 request->dataType = kAggressivesRequestTypeService;
1369 request->data.service = service;
1370
1371 AGGRESSIVES_LOCK();
1372 queue_enter(&aggressivesQueue, request, AggressivesRequest *, chain);
1373 AGGRESSIVES_UNLOCK();
1374
1375 thread_call_enter(aggressivesThreadCall);
1376
1377 return kIOReturnSuccess;
1378 }
1379
1380
1381 //******************************************************************************
1382 // handleAggressivesRequests
1383 //
1384 // Backend thread processes all incoming aggressiveness requests in the queue.
1385 //******************************************************************************
1386
1387 static void
1388 handleAggressivesFunction(
1389 thread_call_param_t param1,
1390 thread_call_param_t param2 )
1391 {
1392 if (param1)
1393 {
1394 ((IOPMrootDomain *) param1)->handleAggressivesRequests();
1395 }
1396 }
1397
1398 void IOPMrootDomain::handleAggressivesRequests( void )
1399 {
1400 AggressivesRecord * start;
1401 AggressivesRecord * record;
1402 AggressivesRequest * request;
1403 queue_head_t joinedQueue;
1404 int i, count;
1405 bool broadcast;
1406 bool found;
1407 bool pingSelf = false;
1408
1409 AGGRESSIVES_LOCK();
1410
1411 if ((gAggressivesState & kAggressivesStateBusy) || !aggressivesData ||
1412 queue_empty(&aggressivesQueue))
1413 goto unlock_done;
1414
1415 gAggressivesState |= kAggressivesStateBusy;
1416 count = aggressivesData->getLength() / sizeof(AggressivesRecord);
1417 start = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
1418
1419 do
1420 {
1421 broadcast = false;
1422 queue_init(&joinedQueue);
1423
1424 do
1425 {
1426 // Remove request from the incoming queue in FIFO order.
1427 queue_remove_first(&aggressivesQueue, request, AggressivesRequest *, chain);
1428 switch (request->dataType)
1429 {
1430 case kAggressivesRequestTypeRecord:
1431 // Update existing record if found.
1432 found = false;
1433 for (i = 0, record = start; i < count; i++, record++)
1434 {
1435 if (record->type == request->data.record.type)
1436 {
1437 found = true;
1438
1439 if (request->options & kAggressivesOptionQuickSpindownEnable)
1440 {
1441 if ((record->flags & kAggressivesRecordFlagMinValue) == 0)
1442 {
1443 broadcast = true;
1444 record->flags |= (kAggressivesRecordFlagMinValue |
1445 kAggressivesRecordFlagModified);
1446 DLOG("quick spindown accelerated, was %u min\n",
1447 record->value);
1448 }
1449 }
1450 else if (request->options & kAggressivesOptionQuickSpindownDisable)
1451 {
1452 if (record->flags & kAggressivesRecordFlagMinValue)
1453 {
1454 broadcast = true;
1455 record->flags |= kAggressivesRecordFlagModified;
1456 record->flags &= ~kAggressivesRecordFlagMinValue;
1457 DLOG("disk spindown restored to %u min\n",
1458 record->value);
1459 }
1460 }
1461 else if (record->value != request->data.record.value)
1462 {
1463 record->value = request->data.record.value;
1464 if ((record->flags & kAggressivesRecordFlagMinValue) == 0)
1465 {
1466 broadcast = true;
1467 record->flags |= kAggressivesRecordFlagModified;
1468 }
1469 }
1470 break;
1471 }
1472 }
1473
1474 // No matching record, append a new record.
1475 if (!found &&
1476 ((request->options & kAggressivesOptionQuickSpindownDisable) == 0))
1477 {
1478 AggressivesRecord newRecord;
1479
1480 newRecord.flags = kAggressivesRecordFlagModified;
1481 newRecord.type = request->data.record.type;
1482 newRecord.value = request->data.record.value;
1483 if (request->options & kAggressivesOptionQuickSpindownEnable)
1484 {
1485 newRecord.flags |= kAggressivesRecordFlagMinValue;
1486 DLOG("disk spindown accelerated\n");
1487 }
1488
1489 aggressivesData->appendBytes(&newRecord, sizeof(newRecord));
1490
1491 // OSData may have switched to another (larger) buffer.
1492 count = aggressivesData->getLength() / sizeof(AggressivesRecord);
1493 start = (AggressivesRecord *) aggressivesData->getBytesNoCopy();
1494 broadcast = true;
1495 }
1496
1497 // Finished processing the request, release it.
1498 IODelete(request, AggressivesRequest, 1);
1499 break;
1500
1501 case kAggressivesRequestTypeService:
1502 // synchronizeAggressives() will free request.
1503 queue_enter(&joinedQueue, request, AggressivesRequest *, chain);
1504 break;
1505
1506 default:
1507 panic("bad aggressives request type %x\n", request->dataType);
1508 break;
1509 }
1510 } while (!queue_empty(&aggressivesQueue));
1511
1512 // Release the lock to perform work, with busy flag set.
1513 if (!queue_empty(&joinedQueue) || broadcast)
1514 {
1515 AGGRESSIVES_UNLOCK();
1516 if (!queue_empty(&joinedQueue))
1517 synchronizeAggressives(&joinedQueue, start, count);
1518 if (broadcast)
1519 broadcastAggressives(start, count);
1520 AGGRESSIVES_LOCK();
1521 }
1522
1523 // Remove the modified flag from all records.
1524 for (i = 0, record = start; i < count; i++, record++)
1525 {
1526 if ((record->flags & kAggressivesRecordFlagModified) &&
1527 ((record->type == kPMMinutesToDim) ||
1528 (record->type == kPMMinutesToSleep)))
1529 pingSelf = true;
1530
1531 record->flags &= ~kAggressivesRecordFlagModified;
1532 }
1533
1534 // Check the incoming queue again since new entries may have been
1535 // added while lock was released above.
1536
1537 } while (!queue_empty(&aggressivesQueue));
1538
1539 gAggressivesState &= ~kAggressivesStateBusy;
1540
1541 unlock_done:
1542 AGGRESSIVES_UNLOCK();
1543
1544 // Root domain is interested in system and display sleep slider changes.
1545 // Submit a power event to handle those changes on the PM work loop.
1546
1547 if (pingSelf && pmPowerStateQueue) {
1548 pmPowerStateQueue->submitPowerEvent( kPowerEventAggressivenessChanged );
1549 }
1550 }
1551
1552
1553 //******************************************************************************
1554 // synchronizeAggressives
1555 //
1556 // Push all known aggressiveness records to one or more IOService.
1557 //******************************************************************************
1558
1559 void IOPMrootDomain::synchronizeAggressives(
1560 queue_head_t * joinedQueue,
1561 const AggressivesRecord * array,
1562 int count )
1563 {
1564 IOService * service;
1565 AggressivesRequest * request;
1566 const AggressivesRecord * record;
1567 uint32_t value;
1568 int i;
1569
1570 while (!queue_empty(joinedQueue))
1571 {
1572 queue_remove_first(joinedQueue, request, AggressivesRequest *, chain);
1573 if (request->dataType == kAggressivesRequestTypeService)
1574 service = request->data.service;
1575 else
1576 service = 0;
1577
1578 IODelete(request, AggressivesRequest, 1);
1579 request = 0;
1580
1581 if (service)
1582 {
1583 if (service->assertPMThreadCall())
1584 {
1585 for (i = 0, record = array; i < count; i++, record++)
1586 {
1587 value = record->value;
1588 if (record->flags & kAggressivesRecordFlagMinValue)
1589 value = kAggressivesMinValue;
1590
1591 DLOG("synchronizeAggressives 0x%x = %u to %s\n",
1592 record->type, value, service->getName());
1593 service->setAggressiveness(record->type, value);
1594 }
1595 service->deassertPMThreadCall();
1596 }
1597 service->release(); // retained by joinAggressiveness()
1598 }
1599 }
1600 }
1601
1602
1603 //******************************************************************************
1604 // broadcastAggressives
1605 //
1606 // Traverse PM tree and call setAggressiveness() for records that have changed.
1607 //******************************************************************************
1608
1609 void IOPMrootDomain::broadcastAggressives(
1610 const AggressivesRecord * array,
1611 int count )
1612 {
1613 IORegistryIterator * iter;
1614 IORegistryEntry * entry;
1615 IOPowerConnection * connect;
1616 IOService * service;
1617 const AggressivesRecord * record;
1618 uint32_t value;
1619 int i;
1620
1621 iter = IORegistryIterator::iterateOver(
1622 this, gIOPowerPlane, kIORegistryIterateRecursively);
1623 if (iter)
1624 {
1625 do
1626 {
1627 iter->reset();
1628 while ((entry = iter->getNextObject()))
1629 {
1630 connect = OSDynamicCast(IOPowerConnection, entry);
1631 if (!connect || !connect->getReadyFlag())
1632 continue;
1633
1634 if ((service = (IOService *) connect->copyChildEntry(gIOPowerPlane)))
1635 {
1636 if (service->assertPMThreadCall())
1637 {
1638 for (i = 0, record = array; i < count; i++, record++)
1639 {
1640 if (record->flags & kAggressivesRecordFlagModified)
1641 {
1642 value = record->value;
1643 if (record->flags & kAggressivesRecordFlagMinValue)
1644 value = kAggressivesMinValue;
1645 DLOG("broadcastAggressives %x = %u to %s\n",
1646 record->type, value, service->getName());
1647 service->setAggressiveness(record->type, value);
1648 }
1649 }
1650 service->deassertPMThreadCall();
1651 }
1652 service->release();
1653 }
1654 }
1655 }
1656 while (!entry && !iter->isValid());
1657 iter->release();
1658 }
1659 }
1660
1661
1662 //******************************************************************************
1663 // startIdleSleepTimer
1664 //
1665 //******************************************************************************
1666
1667 void IOPMrootDomain::startIdleSleepTimer( uint32_t inSeconds )
1668 {
1669 AbsoluteTime deadline;
1670
1671 ASSERT_GATED();
1672 if (inSeconds)
1673 {
1674 clock_interval_to_deadline(inSeconds, kSecondScale, &deadline);
1675 thread_call_enter_delayed(extraSleepTimer, deadline);
1676 idleSleepTimerPending = true;
1677 DLOG("idle timer set for %u seconds\n", inSeconds);
1678 }
1679 }
1680
1681
1682 //******************************************************************************
1683 // cancelIdleSleepTimer
1684 //
1685 //******************************************************************************
1686
1687 void IOPMrootDomain::cancelIdleSleepTimer( void )
1688 {
1689 ASSERT_GATED();
1690 if (idleSleepTimerPending)
1691 {
1692 DLOG("idle timer cancelled\n");
1693 thread_call_cancel(extraSleepTimer);
1694 idleSleepTimerPending = false;
1695 }
1696 }
1697
1698
1699 //******************************************************************************
1700 // idleSleepTimerExpired
1701 //
1702 //******************************************************************************
1703
1704 static void idleSleepTimerExpired(
1705 thread_call_param_t us, thread_call_param_t )
1706 {
1707 ((IOPMrootDomain *)us)->handleSleepTimerExpiration();
1708 }
1709
1710 static void wakeupClamshellTimerExpired(
1711 thread_call_param_t us, thread_call_param_t )
1712 {
1713 ((IOPMrootDomain *)us)->stopIgnoringClamshellEventsDuringWakeup();
1714 }
1715
1716
1717 //******************************************************************************
1718 // handleSleepTimerExpiration
1719 //
1720 // The time between the sleep idle timeout and the next longest one has elapsed.
1721 // It's time to sleep. Start that by removing the clamp that's holding us awake.
1722 //******************************************************************************
1723
1724 void IOPMrootDomain::handleSleepTimerExpiration( void )
1725 {
1726 if (!getPMworkloop()->inGate())
1727 {
1728 getPMworkloop()->runAction(
1729 OSMemberFunctionCast(IOWorkLoop::Action, this,
1730 &IOPMrootDomain::handleSleepTimerExpiration),
1731 this);
1732 return;
1733 }
1734
1735 AbsoluteTime time;
1736
1737 DLOG("sleep timer expired\n");
1738 ASSERT_GATED();
1739
1740 idleSleepTimerPending = false;
1741
1742 clock_get_uptime(&time);
1743 if ((AbsoluteTime_to_scalar(&time) > autoWakeStart) &&
1744 (AbsoluteTime_to_scalar(&time) < autoWakeEnd))
1745 {
1746 thread_call_enter_delayed(extraSleepTimer, *((AbsoluteTime *) &autoWakeEnd));
1747 return;
1748 }
1749
1750 // accelerate disk spin down if spin down timer is non-zero
1751 setQuickSpinDownTimeout();
1752
1753 sleepASAP = true;
1754 adjustPowerState();
1755 }
1756
1757
1758 //******************************************************************************
1759 // stopIgnoringClamshellEventsDuringWakeup
1760 //
1761 //******************************************************************************
1762
1763 void IOPMrootDomain::stopIgnoringClamshellEventsDuringWakeup( void )
1764 {
1765 if (!getPMworkloop()->inGate())
1766 {
1767 getPMworkloop()->runAction(
1768 OSMemberFunctionCast(IOWorkLoop::Action, this,
1769 &IOPMrootDomain::stopIgnoringClamshellEventsDuringWakeup),
1770 this);
1771 return;
1772 }
1773
1774 ASSERT_GATED();
1775
1776 // Allow clamshell-induced sleep now
1777 ignoringClamshellOnWake = false;
1778
1779 // Re-send clamshell event, in case it causes a sleep
1780 if (clamshellIsClosed)
1781 handlePowerNotification( kLocalEvalClamshellCommand );
1782 }
1783
1784
1785 //******************************************************************************
1786 // sleepSystem
1787 //
1788 //******************************************************************************
1789
1790 /* public */
1791 IOReturn IOPMrootDomain::sleepSystem( void )
1792 {
1793 return sleepSystemOptions(NULL);
1794 }
1795
1796 /* private */
1797 IOReturn IOPMrootDomain::sleepSystemOptions( OSDictionary *options )
1798 {
1799 /* sleepSystem is a public function, and may be called by any kernel driver.
1800 * And that's bad - drivers should sleep the system by calling
1801 * receivePowerNotification() instead. Drivers should not use sleepSystem.
1802 *
1803 * Note that user space app calls to IOPMSleepSystem() will also travel
1804 * this code path and thus be correctly identified as software sleeps.
1805 */
1806
1807 if (options && options->getObject("OSSwitch"))
1808 {
1809
1810 // Log specific sleep cause for OS Switch hibernation
1811 return privateSleepSystem( kIOPMSleepReasonOSSwitchHibernation);
1812
1813 } else {
1814
1815 return privateSleepSystem( kIOPMSleepReasonSoftware);
1816
1817 }
1818 }
1819
1820 /* private */
1821 IOReturn IOPMrootDomain::privateSleepSystem( uint32_t sleepReason )
1822 {
1823 static const char * IOPMSleepReasons[kIOPMSleepReasonMax] = {
1824 "",
1825 kIOPMClamshellSleepKey,
1826 kIOPMPowerButtonSleepKey,
1827 kIOPMSoftwareSleepKey,
1828 kIOPMOSSwitchHibernationKey,
1829 kIOPMIdleSleepKey,
1830 kIOPMLowPowerSleepKey,
1831 kIOPMClamshellSleepKey,
1832 kIOPMThermalEmergencySleepKey
1833 };
1834 if ( userDisabledAllSleep )
1835 {
1836 LOG("Sleep prevented by user disable\n");
1837
1838 /* Prevent sleep of all kinds if directed to by user space */
1839 return kIOReturnNotPermitted;
1840 }
1841
1842 if ( systemBooting || systemShutdown || !allowSleep )
1843 {
1844 LOG("Sleep prevented by SB %d, SS %d, AS %d\n",
1845 systemBooting, systemShutdown, allowSleep);
1846
1847 // Unable to sleep because system is in the process of booting or
1848 // shutting down, or sleep has otherwise been disallowed.
1849 return kIOReturnError;
1850 }
1851
1852 // Record sleep cause in IORegistry
1853 lastSleepReason = sleepReason;
1854 if (sleepReason && (sleepReason < kIOPMSleepReasonMax)) {
1855 setProperty(kRootDomainSleepReasonKey, IOPMSleepReasons[sleepReason]);
1856 }
1857
1858 patriarch->sleepSystem();
1859 return kIOReturnSuccess;
1860 }
1861
1862
1863 //******************************************************************************
1864 // shutdownSystem
1865 //
1866 //******************************************************************************
1867
1868 IOReturn IOPMrootDomain::shutdownSystem( void )
1869 {
1870 //patriarch->shutDownSystem();
1871 return kIOReturnUnsupported;
1872 }
1873
1874
1875 //******************************************************************************
1876 // restartSystem
1877 //
1878 //******************************************************************************
1879
1880 IOReturn IOPMrootDomain::restartSystem( void )
1881 {
1882 //patriarch->restartSystem();
1883 return kIOReturnUnsupported;
1884 }
1885
1886
1887 //******************************************************************************
1888 // powerChangeDone
1889 //
1890 // This overrides powerChangeDone in IOService.
1891 //
1892 // Menu sleep and idle sleep move us from the ON state to the SLEEP_STATE.
1893 // In this case:
1894 // If we finished going to the SLEEP_STATE, and the platform is capable of
1895 // true sleep, then sleep the kernel. Otherwise switch up to the DOZE_STATE
1896 // which will keep almost everything as off as it can get.
1897 //******************************************************************************
1898
1899 void IOPMrootDomain::powerChangeDone( unsigned long previousState )
1900 {
1901 ASSERT_GATED();
1902 DLOG("PowerChangeDone: %u->%u\n",
1903 (uint32_t) previousState, (uint32_t) getPowerState());
1904
1905 switch ( getPowerState() ) {
1906 case SLEEP_STATE:
1907 if ( previousState != ON_STATE )
1908 break;
1909
1910 if ( canSleep )
1911 {
1912 // re-enable this timer for next sleep
1913 cancelIdleSleepTimer();
1914 wranglerTickled = true;
1915
1916 clock_sec_t secs;
1917 clock_usec_t microsecs;
1918 clock_get_calendar_microtime(&secs, &microsecs);
1919 logtime(secs);
1920 gIOLastSleepTime.tv_sec = secs;
1921 gIOLastSleepTime.tv_usec = microsecs;
1922 gIOLastWakeTime.tv_sec = 0;
1923 gIOLastWakeTime.tv_usec = 0;
1924
1925 #if HIBERNATION
1926 LOG("System %sSleep\n", gIOHibernateState ? "Safe" : "");
1927
1928 tracePoint(kIOPMTracePointSystemHibernatePhase);
1929
1930 IOHibernateSystemHasSlept();
1931
1932 evaluateSystemSleepPolicyFinal();
1933 #else
1934 LOG("System Sleep\n");
1935 #endif
1936
1937 tracePoint(kIOPMTracePointSystemSleepPlatformPhase);
1938
1939 getPlatform()->sleepKernel();
1940
1941 // The CPU(s) are off at this point. When they're awakened by CPU interrupt,
1942 // code will resume execution here.
1943
1944 // Now we're waking...
1945 tracePoint(kIOPMTracePointSystemWakeDriversPhase);
1946
1947 #if HIBERNATION
1948 IOHibernateSystemWake();
1949 #endif
1950
1951 // sleep transition complete
1952 gSleepOrShutdownPending = 0;
1953
1954 // trip the reset of the calendar clock
1955 clock_wakeup_calendar();
1956
1957 // get us some power
1958 patriarch->wakeSystem();
1959
1960 // Set indicator if UUID was set - allow it to be cleared.
1961 if (getProperty(kIOPMSleepWakeUUIDKey))
1962 gSleepWakeUUIDIsSet = true;
1963
1964 #if !ROOT_DOMAIN_RUN_STATES
1965 tellClients(kIOMessageSystemWillPowerOn, clientMessageFilter);
1966 #endif
1967
1968 #if HIBERNATION
1969 LOG("System %sWake\n", gIOHibernateState ? "SafeSleep " : "");
1970 #endif
1971
1972 // log system wake
1973 getPlatform()->PMLog(kIOPMrootDomainClass, kPMLogSystemWake, 0, 0);
1974 lowBatteryCondition = false;
1975
1976 #ifndef __LP64__
1977 // tell the tree we're waking
1978 systemWake();
1979 #endif
1980
1981
1982 #if defined(__i386__) || defined(__x86_64__)
1983 sleepTimerMaintenance = false;
1984 #if ROOT_DOMAIN_RUN_STATES
1985 OSString * wakeType = OSDynamicCast(
1986 OSString, getProperty(kIOPMRootDomainWakeTypeKey));
1987 if (wakeType && wakeType->isEqualTo(kIOPMrootDomainWakeTypeLowBattery))
1988 {
1989 lowBatteryCondition = true;
1990 updateRunState(kRStateMaintenance);
1991 wranglerTickled = false;
1992 }
1993 else if (wakeType && !hibernateAborted && wakeType->isEqualTo(kIOPMRootDomainWakeTypeSleepTimer))
1994 {
1995 sleepTimerMaintenance = true;
1996 updateRunState(kRStateMaintenance);
1997 wranglerTickled = false;
1998 }
1999 else if (wakeType && !hibernateAborted && wakeType->isEqualTo(kIOPMRootDomainWakeTypeMaintenance))
2000 {
2001 updateRunState(kRStateMaintenance);
2002 wranglerTickled = false;
2003 }
2004 else
2005 #endif /* ROOT_DOMAIN_RUN_STATES */
2006 {
2007 updateRunState(kRStateNormal);
2008 reportUserInput();
2009 }
2010 #else /* !__i386__ && !__x86_64__ */
2011 // stay awake for at least 30 seconds
2012 startIdleSleepTimer(30);
2013 reportUserInput();
2014 #endif
2015
2016 changePowerStateToPriv(ON_STATE);
2017 } else {
2018 updateRunState(kRStateNormal);
2019
2020 // allow us to step up a power state
2021 patriarch->sleepToDoze();
2022
2023 // ignore children's request for higher power during doze.
2024 changePowerStateWithOverrideTo(DOZE_STATE);
2025 }
2026 break;
2027
2028 case DOZE_STATE:
2029 if ( previousState != DOZE_STATE )
2030 {
2031 LOG("System Doze\n");
2032 }
2033 // re-enable this timer for next sleep
2034 cancelIdleSleepTimer();
2035 gSleepOrShutdownPending = 0;
2036
2037 // Invalidate prior activity tickles to allow wake from doze.
2038 if (wrangler) wrangler->changePowerStateTo(0);
2039 break;
2040
2041 #if ROOT_DOMAIN_RUN_STATES
2042 case ON_STATE:
2043 // SLEEP -> ON (Maintenance)
2044 // Go back to sleep, unless cancelled by a HID event.
2045
2046 if ((previousState == SLEEP_STATE) &&
2047 (runStateIndex == kRStateMaintenance) &&
2048 !wranglerTickled)
2049 {
2050 if (lowBatteryCondition)
2051 {
2052 lastSleepReason = kIOPMSleepReasonLowPower;
2053 setProperty(kRootDomainSleepReasonKey, kIOPMLowPowerSleepKey);
2054 }
2055 else
2056 {
2057 lastSleepReason = kIOPMSleepReasonMaintenance;
2058 setProperty(kRootDomainSleepReasonKey, kIOPMMaintenanceSleepKey);
2059 }
2060 changePowerStateWithOverrideTo(SLEEP_STATE);
2061 }
2062
2063 // ON -> ON triggered by R-state changes.
2064
2065 if ((previousState == ON_STATE) &&
2066 (runStateIndex != nextRunStateIndex) &&
2067 (nextRunStateIndex < kRStateCount))
2068 {
2069 LOG("R-state changed %u->%u\n",
2070 runStateIndex, nextRunStateIndex);
2071 updateRunState(nextRunStateIndex);
2072
2073 DLOG("kIOMessageSystemHasPoweredOn (%u)\n",
2074 gMessageClientType);
2075 tellClients(kIOMessageSystemHasPoweredOn, clientMessageFilter);
2076 }
2077
2078 break;
2079 #endif /* ROOT_DOMAIN_RUN_STATES */
2080 }
2081 }
2082
2083
2084 //******************************************************************************
2085 // wakeFromDoze
2086 //
2087 // The Display Wrangler calls here when it switches to its highest state.
2088 // If the system is currently dozing, allow it to wake by making sure the
2089 // parent is providing power.
2090 //******************************************************************************
2091
2092 void IOPMrootDomain::wakeFromDoze( void )
2093 {
2094 if ( getPowerState() == DOZE_STATE )
2095 {
2096 tracePoint(kIOPMTracePointSystemWakeDriversPhase);
2097 changePowerStateToPriv(ON_STATE);
2098 patriarch->wakeSystem();
2099 }
2100 }
2101
2102
2103 //******************************************************************************
2104 // publishFeature
2105 //
2106 // Adds a new feature to the supported features dictionary
2107 //******************************************************************************
2108
2109 void IOPMrootDomain::publishFeature( const char * feature )
2110 {
2111 publishFeature(feature, kRD_AllPowerSources, NULL);
2112 }
2113
2114
2115 //******************************************************************************
2116 // publishFeature (with supported power source specified)
2117 //
2118 // Adds a new feature to the supported features dictionary
2119 //******************************************************************************
2120
2121 void IOPMrootDomain::publishFeature(
2122 const char *feature,
2123 uint32_t supportedWhere,
2124 uint32_t *uniqueFeatureID)
2125 {
2126 static uint16_t next_feature_id = 500;
2127
2128 OSNumber *new_feature_data = NULL;
2129 OSNumber *existing_feature = NULL;
2130 OSArray *existing_feature_arr = NULL;
2131 OSObject *osObj = NULL;
2132 uint32_t feature_value = 0;
2133
2134 supportedWhere &= kRD_AllPowerSources; // mask off any craziness!
2135
2136 if(!supportedWhere) {
2137 // Feature isn't supported anywhere!
2138 return;
2139 }
2140
2141 if(next_feature_id > 5000) {
2142 // Far, far too many features!
2143 return;
2144 }
2145
2146 if(featuresDictLock) IOLockLock(featuresDictLock);
2147
2148 OSDictionary *features =
2149 (OSDictionary *) getProperty(kRootDomainSupportedFeatures);
2150
2151 // Create new features dict if necessary
2152 if ( features && OSDynamicCast(OSDictionary, features)) {
2153 features = OSDictionary::withDictionary(features);
2154 } else {
2155 features = OSDictionary::withCapacity(1);
2156 }
2157
2158 // Create OSNumber to track new feature
2159
2160 next_feature_id += 1;
2161 if( uniqueFeatureID ) {
2162 // We don't really mind if the calling kext didn't give us a place
2163 // to stash their unique id. Many kexts don't plan to unload, and thus
2164 // have no need to remove themselves later.
2165 *uniqueFeatureID = next_feature_id;
2166 }
2167
2168 feature_value = (uint32_t)next_feature_id;
2169 feature_value <<= 16;
2170 feature_value += supportedWhere;
2171
2172 new_feature_data = OSNumber::withNumber(
2173 (unsigned long long)feature_value, 32);
2174
2175 // Does features object already exist?
2176 if( (osObj = features->getObject(feature)) )
2177 {
2178 if(( existing_feature = OSDynamicCast(OSNumber, osObj) ))
2179 {
2180 // We need to create an OSArray to hold the now 2 elements.
2181 existing_feature_arr = OSArray::withObjects(
2182 (const OSObject **)&existing_feature, 1, 2);
2183 } else if(( existing_feature_arr = OSDynamicCast(OSArray, osObj) ))
2184 {
2185 // Add object to existing array
2186 existing_feature_arr = OSArray::withArray(
2187 existing_feature_arr,
2188 existing_feature_arr->getCount() + 1);
2189 }
2190
2191 if (existing_feature_arr)
2192 {
2193 existing_feature_arr->setObject(new_feature_data);
2194 features->setObject(feature, existing_feature_arr);
2195 existing_feature_arr->release();
2196 existing_feature_arr = 0;
2197 }
2198 } else {
2199 // The easy case: no previously existing features listed. We simply
2200 // set the OSNumber at key 'feature' and we're on our way.
2201 features->setObject(feature, new_feature_data);
2202 }
2203
2204 new_feature_data->release();
2205
2206 setProperty(kRootDomainSupportedFeatures, features);
2207
2208 features->release();
2209
2210 if(featuresDictLock) IOLockUnlock(featuresDictLock);
2211
2212 // Notify EnergySaver and all those in user space so they might
2213 // re-populate their feature specific UI
2214 if(pmPowerStateQueue) {
2215 pmPowerStateQueue->submitPowerEvent( kPowerEventFeatureChanged );
2216 }
2217 }
2218
2219
2220 //******************************************************************************
2221 // removePublishedFeature
2222 //
2223 // Removes previously published feature
2224 //******************************************************************************
2225
2226 IOReturn IOPMrootDomain::removePublishedFeature( uint32_t removeFeatureID )
2227 {
2228 IOReturn ret = kIOReturnError;
2229 uint32_t feature_value = 0;
2230 uint16_t feature_id = 0;
2231 bool madeAChange = false;
2232
2233 OSSymbol *dictKey = NULL;
2234 OSCollectionIterator *dictIterator = NULL;
2235 OSArray *arrayMember = NULL;
2236 OSNumber *numberMember = NULL;
2237 OSObject *osObj = NULL;
2238 OSNumber *osNum = NULL;
2239 OSArray *arrayMemberCopy;
2240
2241 if(featuresDictLock) IOLockLock(featuresDictLock);
2242
2243 OSDictionary *features =
2244 (OSDictionary *) getProperty(kRootDomainSupportedFeatures);
2245
2246 if ( features && OSDynamicCast(OSDictionary, features) )
2247 {
2248 // Any modifications to the dictionary are made to the copy to prevent
2249 // races & crashes with userland clients. Dictionary updated
2250 // automically later.
2251 features = OSDictionary::withDictionary(features);
2252 } else {
2253 features = NULL;
2254 ret = kIOReturnNotFound;
2255 goto exit;
2256 }
2257
2258 // We iterate 'features' dictionary looking for an entry tagged
2259 // with 'removeFeatureID'. If found, we remove it from our tracking
2260 // structures and notify the OS via a general interest message.
2261
2262 dictIterator = OSCollectionIterator::withCollection(features);
2263 if(!dictIterator) {
2264 goto exit;
2265 }
2266
2267 while( (dictKey = OSDynamicCast(OSSymbol, dictIterator->getNextObject())) )
2268 {
2269 osObj = features->getObject(dictKey);
2270
2271 // Each Feature is either tracked by an OSNumber
2272 if( osObj && (numberMember = OSDynamicCast(OSNumber, osObj)) )
2273 {
2274 feature_value = numberMember->unsigned32BitValue();
2275 feature_id = (uint16_t)(feature_value >> 16);
2276
2277 if( feature_id == (uint16_t)removeFeatureID )
2278 {
2279 // Remove this node
2280 features->removeObject(dictKey);
2281 madeAChange = true;
2282 break;
2283 }
2284
2285 // Or tracked by an OSArray of OSNumbers
2286 } else if( osObj && (arrayMember = OSDynamicCast(OSArray, osObj)) )
2287 {
2288 unsigned int arrayCount = arrayMember->getCount();
2289
2290 for(unsigned int i=0; i<arrayCount; i++)
2291 {
2292 osNum = OSDynamicCast(OSNumber, arrayMember->getObject(i));
2293 if(!osNum) {
2294 continue;
2295 }
2296
2297 feature_value = osNum->unsigned32BitValue();
2298 feature_id = (uint16_t)(feature_value >> 16);
2299
2300 if( feature_id == (uint16_t)removeFeatureID )
2301 {
2302 // Remove this node
2303 if( 1 == arrayCount ) {
2304 // If the array only contains one element, remove
2305 // the whole thing.
2306 features->removeObject(dictKey);
2307 } else {
2308 // Otherwise remove the element from a copy of the array.
2309 arrayMemberCopy = OSArray::withArray(arrayMember);
2310 if (arrayMemberCopy)
2311 {
2312 arrayMemberCopy->removeObject(i);
2313 features->setObject(dictKey, arrayMemberCopy);
2314 arrayMemberCopy->release();
2315 }
2316 }
2317
2318 madeAChange = true;
2319 break;
2320 }
2321 }
2322 }
2323 }
2324
2325 dictIterator->release();
2326
2327 if( madeAChange )
2328 {
2329 ret = kIOReturnSuccess;
2330
2331 setProperty(kRootDomainSupportedFeatures, features);
2332
2333 // Notify EnergySaver and all those in user space so they might
2334 // re-populate their feature specific UI
2335 if(pmPowerStateQueue) {
2336 pmPowerStateQueue->submitPowerEvent( kPowerEventFeatureChanged );
2337 }
2338 } else {
2339 ret = kIOReturnNotFound;
2340 }
2341
2342 exit:
2343 if(features) features->release();
2344 if(featuresDictLock) IOLockUnlock(featuresDictLock);
2345 return ret;
2346 }
2347
2348
2349 //******************************************************************************
2350 // announcePowerSourceChange
2351 //
2352 // Notifies "interested parties" that the battery state has changed
2353 //******************************************************************************
2354
2355 void IOPMrootDomain::announcePowerSourceChange( void )
2356 {
2357 #ifdef __ppc__
2358 IORegistryEntry *_batteryRegEntry = (IORegistryEntry *) getProperty("BatteryEntry");
2359
2360 // (if possible) re-publish power source state under IOPMrootDomain;
2361 // only do so if the battery controller publishes an IOResource
2362 // defining battery location. Called from ApplePMU battery driver.
2363
2364 if(_batteryRegEntry)
2365 {
2366 OSArray *batt_info;
2367 batt_info = (OSArray *) _batteryRegEntry->getProperty(kIOBatteryInfoKey);
2368 if(batt_info)
2369 setProperty(kIOBatteryInfoKey, batt_info);
2370 }
2371 #endif
2372 }
2373
2374
2375 //******************************************************************************
2376 // setPMSetting (private)
2377 //
2378 // Internal helper to relay PM settings changes from user space to individual
2379 // drivers. Should be called only by IOPMrootDomain::setProperties.
2380 //******************************************************************************
2381
2382 IOReturn IOPMrootDomain::setPMSetting(
2383 const OSSymbol *type,
2384 OSObject *obj)
2385 {
2386 OSArray *arr = NULL;
2387 PMSettingObject *p_obj = NULL;
2388 int count;
2389 int i;
2390
2391 if(NULL == type) return kIOReturnBadArgument;
2392
2393 IORecursiveLockLock(settingsCtrlLock);
2394
2395 fPMSettingsDict->setObject(type, obj);
2396
2397 arr = (OSArray *)settingsCallbacks->getObject(type);
2398 if(NULL == arr) goto exit;
2399 count = arr->getCount();
2400 for(i=0; i<count; i++) {
2401 p_obj = (PMSettingObject *)OSDynamicCast(PMSettingObject, arr->getObject(i));
2402 if(p_obj) p_obj->setPMSetting(type, obj);
2403 }
2404
2405 exit:
2406 IORecursiveLockUnlock(settingsCtrlLock);
2407 return kIOReturnSuccess;
2408 }
2409
2410
2411 //******************************************************************************
2412 // copyPMSetting (public)
2413 //
2414 // Allows kexts to safely read setting values, without being subscribed to
2415 // notifications.
2416 //******************************************************************************
2417
2418 OSObject * IOPMrootDomain::copyPMSetting(
2419 OSSymbol *whichSetting)
2420 {
2421 OSObject *obj = NULL;
2422
2423 if(!whichSetting) return NULL;
2424
2425 IORecursiveLockLock(settingsCtrlLock);
2426 obj = fPMSettingsDict->getObject(whichSetting);
2427 if(obj) {
2428 obj->retain();
2429 }
2430 IORecursiveLockUnlock(settingsCtrlLock);
2431
2432 return obj;
2433 }
2434
2435
2436 //******************************************************************************
2437 // registerPMSettingController (public)
2438 //
2439 // direct wrapper to registerPMSettingController with uint32_t power source arg
2440 //******************************************************************************
2441
2442 IOReturn IOPMrootDomain::registerPMSettingController(
2443 const OSSymbol * settings[],
2444 IOPMSettingControllerCallback func,
2445 OSObject *target,
2446 uintptr_t refcon,
2447 OSObject **handle)
2448 {
2449 return registerPMSettingController(
2450 settings,
2451 (kIOPMSupportedOnAC | kIOPMSupportedOnBatt | kIOPMSupportedOnUPS),
2452 func, target, refcon, handle);
2453 }
2454
2455
2456 //******************************************************************************
2457 // registerPMSettingController (public)
2458 //
2459 // Kexts may register for notifications when a particular setting is changed.
2460 // A list of settings is available in IOPM.h.
2461 // Arguments:
2462 // * settings - An OSArray containing OSSymbols. Caller should populate this
2463 // array with a list of settings caller wants notifications from.
2464 // * func - A C function callback of the type IOPMSettingControllerCallback
2465 // * target - caller may provide an OSObject *, which PM will pass as an
2466 // target to calls to "func"
2467 // * refcon - caller may provide an void *, which PM will pass as an
2468 // argument to calls to "func"
2469 // * handle - This is a return argument. We will populate this pointer upon
2470 // call success. Hold onto this and pass this argument to
2471 // IOPMrootDomain::deRegisterPMSettingCallback when unloading your kext
2472 // Returns:
2473 // kIOReturnSuccess on success
2474 //******************************************************************************
2475
2476 IOReturn IOPMrootDomain::registerPMSettingController(
2477 const OSSymbol * settings[],
2478 uint32_t supportedPowerSources,
2479 IOPMSettingControllerCallback func,
2480 OSObject *target,
2481 uintptr_t refcon,
2482 OSObject **handle)
2483 {
2484 PMSettingObject *pmso = NULL;
2485 OSArray *list = NULL;
2486 IOReturn ret = kIOReturnSuccess;
2487 int i;
2488
2489 if( NULL == settings ||
2490 NULL == func ||
2491 NULL == handle)
2492 {
2493 return kIOReturnBadArgument;
2494 }
2495
2496 pmso = PMSettingObject::pmSettingObject(
2497 (IOPMrootDomain *)this, func, target,
2498 refcon, supportedPowerSources, settings);
2499
2500 if(!pmso) {
2501 ret = kIOReturnInternalError;
2502 goto bail_no_unlock;
2503 }
2504
2505 IORecursiveLockLock(settingsCtrlLock);
2506 for(i=0; settings[i]; i++)
2507 {
2508 list = (OSArray *)settingsCallbacks->getObject(settings[i]);
2509 if(!list) {
2510 // New array of callbacks for this setting
2511 list = OSArray::withCapacity(1);
2512 settingsCallbacks->setObject(settings[i], list);
2513 list->release();
2514 }
2515
2516 // Add caller to the callback list
2517 list->setObject(pmso);
2518 }
2519
2520 IORecursiveLockUnlock(settingsCtrlLock);
2521
2522 ret = kIOReturnSuccess;
2523
2524 // Track this instance by its OSData ptr from now on
2525 *handle = pmso;
2526
2527 bail_no_unlock:
2528 if(kIOReturnSuccess != ret)
2529 {
2530 // Error return case
2531 if(pmso) pmso->release();
2532 if(handle) *handle = NULL;
2533 }
2534 return ret;
2535 }
2536
2537
2538 //******************************************************************************
2539 // sleepOnClamshellClosed
2540 //
2541 // contains the logic to determine if the system should sleep when the clamshell
2542 // is closed.
2543 //******************************************************************************
2544
2545 bool IOPMrootDomain::shouldSleepOnClamshellClosed( void )
2546 {
2547 DLOG("clamshell state %d, EX %d, IG %d, IW %d, DT %d, AC %d\n",
2548 clamshellIsClosed, clamshellExists, ignoringClamshell,
2549 ignoringClamshellOnWake, desktopMode, acAdaptorConnected);
2550
2551 return ( !ignoringClamshell
2552 && !ignoringClamshellOnWake
2553 && !(desktopMode && acAdaptorConnected) );
2554 }
2555
2556 void IOPMrootDomain::sendClientClamshellNotification( void )
2557 {
2558 /* Only broadcast clamshell alert if clamshell exists. */
2559 if (!clamshellExists)
2560 return;
2561
2562 setProperty(kAppleClamshellStateKey,
2563 clamshellIsClosed ? kOSBooleanTrue : kOSBooleanFalse);
2564
2565 setProperty(kAppleClamshellCausesSleepKey,
2566 shouldSleepOnClamshellClosed() ? kOSBooleanTrue : kOSBooleanFalse);
2567
2568 /* Argument to message is a bitfiel of
2569 * ( kClamshellStateBit | kClamshellSleepBit )
2570 */
2571 messageClients(kIOPMMessageClamshellStateChange,
2572 (void *) ( (clamshellIsClosed ? kClamshellStateBit : 0)
2573 | ( shouldSleepOnClamshellClosed() ? kClamshellSleepBit : 0)) );
2574 }
2575
2576
2577 //******************************************************************************
2578 // informCPUStateChange
2579 //
2580 // Call into PM CPU code so that CPU power savings may dynamically adjust for
2581 // running on battery, with the lid closed, etc.
2582 //
2583 // informCPUStateChange is a no-op on non x86 systems
2584 // only x86 has explicit support in the IntelCPUPowerManagement kext
2585 //******************************************************************************
2586
2587 void IOPMrootDomain::informCPUStateChange(
2588 uint32_t type,
2589 uint32_t value )
2590 {
2591 #if defined(__i386__) || defined(__x86_64__)
2592
2593 pmioctlVariableInfo_t varInfoStruct;
2594 int pmCPUret = 0;
2595 const char *varNameStr = NULL;
2596 int32_t *varIndex = NULL;
2597
2598 if (kInformAC == type) {
2599 varNameStr = kIOPMRootDomainBatPowerCString;
2600 varIndex = &idxPMCPULimitedPower;
2601 } else if (kInformLid == type) {
2602 varNameStr = kIOPMRootDomainLidCloseCString;
2603 varIndex = &idxPMCPUClamshell;
2604 } else {
2605 return;
2606 }
2607
2608 // Set the new value!
2609 // pmCPUControl will assign us a new ID if one doesn't exist yet
2610 bzero(&varInfoStruct, sizeof(pmioctlVariableInfo_t));
2611 varInfoStruct.varID = *varIndex;
2612 varInfoStruct.varType = vBool;
2613 varInfoStruct.varInitValue = value;
2614 varInfoStruct.varCurValue = value;
2615 strncpy( (char *)varInfoStruct.varName,
2616 (const char *)varNameStr,
2617 strlen(varNameStr) + 1 );
2618
2619 // Set!
2620 pmCPUret = pmCPUControl( PMIOCSETVARINFO, (void *)&varInfoStruct );
2621
2622 // pmCPU only assigns numerical id's when a new varName is specified
2623 if ((0 == pmCPUret)
2624 && (*varIndex == kCPUUnknownIndex))
2625 {
2626 // pmCPUControl has assigned us a new variable ID.
2627 // Let's re-read the structure we just SET to learn that ID.
2628 pmCPUret = pmCPUControl( PMIOCGETVARNAMEINFO, (void *)&varInfoStruct );
2629
2630 if (0 == pmCPUret)
2631 {
2632 // Store it in idxPMCPUClamshell or idxPMCPULimitedPower
2633 *varIndex = varInfoStruct.varID;
2634 }
2635 }
2636
2637 return;
2638
2639 #endif /* __i386__ || __x86_64__ */
2640 }
2641
2642
2643 #if HIBERNATION
2644
2645 //******************************************************************************
2646 // evaluateSystemSleepPolicy
2647 //******************************************************************************
2648
2649 struct IOPMSystemSleepPolicyEntry
2650 {
2651 uint32_t factorMask;
2652 uint32_t factorBits;
2653 uint32_t sleepFlags;
2654 uint32_t wakeEvents;
2655 };
2656
2657 struct IOPMSystemSleepPolicyTable
2658 {
2659 uint8_t signature[4];
2660 uint16_t version;
2661 uint16_t entryCount;
2662 IOPMSystemSleepPolicyEntry entries[];
2663 };
2664
2665 enum {
2666 kIOPMSleepFactorSleepTimerWake = 0x00000001,
2667 kIOPMSleepFactorLidOpen = 0x00000002,
2668 kIOPMSleepFactorACPower = 0x00000004,
2669 kIOPMSleepFactorLowBattery = 0x00000008,
2670 kIOPMSleepFactorDeepSleepNoDelay = 0x00000010,
2671 kIOPMSleepFactorDeepSleepDemand = 0x00000020,
2672 kIOPMSleepFactorDeepSleepDisable = 0x00000040,
2673 kIOPMSleepFactorUSBExternalDevice = 0x00000080,
2674 kIOPMSleepFactorBluetoothHIDDevice = 0x00000100,
2675 kIOPMSleepFactorExternalMediaMounted = 0x00000200,
2676 kIOPMSleepFactorDriverAssertBit5 = 0x00000400,
2677 kIOPMSleepFactorDriverAssertBit6 = 0x00000800,
2678 kIOPMSleepFactorDriverAssertBit7 = 0x00001000
2679 };
2680
2681 bool IOPMrootDomain::evaluateSystemSleepPolicy( IOPMSystemSleepParameters * p )
2682 {
2683 const IOPMSystemSleepPolicyTable * pt;
2684 OSObject * prop = 0;
2685 OSData * policyData;
2686 uint32_t currentFactors;
2687 uint32_t deepSleepDelay = 0;
2688 bool success = false;
2689
2690 if (getProperty(kIOPMDeepSleepEnabledKey) != kOSBooleanTrue)
2691 return false;
2692
2693 getSleepOption(kIOPMDeepSleepDelayKey, &deepSleepDelay);
2694
2695 prop = getServiceRoot()->copyProperty(kIOPlatformSystemSleepPolicyKey);
2696 if (!prop)
2697 return false;
2698
2699 policyData = OSDynamicCast(OSData, prop);
2700 if (!policyData ||
2701 (policyData->getLength() < sizeof(IOPMSystemSleepPolicyTable)))
2702 {
2703 goto done;
2704 }
2705
2706 pt = (const IOPMSystemSleepPolicyTable *) policyData->getBytesNoCopy();
2707 if ((pt->signature[0] != 'S') ||
2708 (pt->signature[1] != 'L') ||
2709 (pt->signature[2] != 'P') ||
2710 (pt->signature[3] != 'T') ||
2711 (pt->version != 1) ||
2712 (pt->entryCount == 0))
2713 {
2714 goto done;
2715 }
2716
2717 if ((policyData->getLength() - sizeof(IOPMSystemSleepPolicyTable)) !=
2718 (sizeof(IOPMSystemSleepPolicyEntry) * pt->entryCount))
2719 {
2720 goto done;
2721 }
2722
2723 currentFactors = 0;
2724 if (getPMAssertionLevel(kIOPMDriverAssertionUSBExternalDeviceBit) !=
2725 kIOPMDriverAssertionLevelOff)
2726 currentFactors |= kIOPMSleepFactorUSBExternalDevice;
2727 if (getPMAssertionLevel(kIOPMDriverAssertionBluetoothHIDDevicePairedBit) !=
2728 kIOPMDriverAssertionLevelOff)
2729 currentFactors |= kIOPMSleepFactorBluetoothHIDDevice;
2730 if (getPMAssertionLevel(kIOPMDriverAssertionExternalMediaMountedBit) !=
2731 kIOPMDriverAssertionLevelOff)
2732 currentFactors |= kIOPMSleepFactorExternalMediaMounted;
2733 if (getPMAssertionLevel(kIOPMDriverAssertionReservedBit5) !=
2734 kIOPMDriverAssertionLevelOff)
2735 currentFactors |= kIOPMSleepFactorDriverAssertBit5;
2736 if (getPMAssertionLevel(kIOPMDriverAssertionReservedBit6) !=
2737 kIOPMDriverAssertionLevelOff)
2738 currentFactors |= kIOPMSleepFactorDriverAssertBit6;
2739 if (getPMAssertionLevel(kIOPMDriverAssertionReservedBit7) !=
2740 kIOPMDriverAssertionLevelOff)
2741 currentFactors |= kIOPMSleepFactorDriverAssertBit7;
2742 if (0 == deepSleepDelay)
2743 currentFactors |= kIOPMSleepFactorDeepSleepNoDelay;
2744 if (!clamshellIsClosed)
2745 currentFactors |= kIOPMSleepFactorLidOpen;
2746 if (acAdaptorConnected)
2747 currentFactors |= kIOPMSleepFactorACPower;
2748 if (lowBatteryCondition)
2749 currentFactors |= kIOPMSleepFactorLowBattery;
2750 if (sleepTimerMaintenance)
2751 currentFactors |= kIOPMSleepFactorSleepTimerWake;
2752
2753 // pmset overrides
2754 if ((hibernateMode & kIOHibernateModeOn) == 0)
2755 currentFactors |= kIOPMSleepFactorDeepSleepDisable;
2756 else if ((hibernateMode & kIOHibernateModeSleep) == 0)
2757 currentFactors |= kIOPMSleepFactorDeepSleepDemand;
2758
2759 DLOG("Sleep policy %u entries, current factors 0x%x\n",
2760 pt->entryCount, currentFactors);
2761
2762 for (uint32_t i = 0; i < pt->entryCount; i++)
2763 {
2764 const IOPMSystemSleepPolicyEntry * policyEntry = &pt->entries[i];
2765
2766 DLOG("factor mask 0x%08x, bits 0x%08x, flags 0x%08x, wake 0x%08x\n",
2767 policyEntry->factorMask, policyEntry->factorBits,
2768 policyEntry->sleepFlags, policyEntry->wakeEvents);
2769
2770 if ((currentFactors ^ policyEntry->factorBits) & policyEntry->factorMask)
2771 continue; // mismatch, try next
2772
2773 if (p)
2774 {
2775 p->version = 1;
2776 p->sleepFlags = policyEntry->sleepFlags;
2777 p->sleepTimer = 0;
2778 p->wakeEvents = policyEntry->wakeEvents;
2779 if (p->sleepFlags & kIOPMSleepFlagSleepTimerEnable)
2780 {
2781 p->sleepTimer = deepSleepDelay;
2782 }
2783 }
2784
2785 DLOG("matched policy entry %u\n", i);
2786 success = true;
2787 break;
2788 }
2789
2790 done:
2791 if (prop)
2792 prop->release();
2793
2794 return success;
2795 }
2796
2797 void IOPMrootDomain::evaluateSystemSleepPolicyEarly( void )
2798 {
2799 IOPMSystemSleepParameters params;
2800
2801 // Evaluate sleep policy before driver sleep phase.
2802
2803 DLOG("%s\n", __FUNCTION__);
2804 removeProperty(kIOPMSystemSleepParametersKey);
2805
2806 hibernateDisabled = false;
2807 hibernateMode = 0;
2808 getSleepOption(kIOHibernateModeKey, &hibernateMode);
2809
2810 if (!hibernateNoDefeat &&
2811 evaluateSystemSleepPolicy(&params) &&
2812 ((params.sleepFlags & kIOPMSleepFlagHibernate) == 0))
2813 {
2814 hibernateDisabled = true;
2815 }
2816 }
2817
2818 void IOPMrootDomain::evaluateSystemSleepPolicyFinal( void )
2819 {
2820 IOPMSystemSleepParameters params;
2821 OSData * paramsData;
2822
2823 // Evaluate sleep policy after drivers but before platform sleep.
2824
2825 DLOG("%s\n", __FUNCTION__);
2826
2827 if (evaluateSystemSleepPolicy(&params))
2828 {
2829 if ((hibernateDisabled || hibernateAborted) &&
2830 (params.sleepFlags & kIOPMSleepFlagHibernate))
2831 {
2832 // Should hibernate but unable to or aborted.
2833 // Arm timer for a short sleep and retry or wake fully.
2834
2835 params.sleepFlags &= ~kIOPMSleepFlagHibernate;
2836 params.sleepFlags |= kIOPMSleepFlagSleepTimerEnable;
2837 params.sleepTimer = 1;
2838 hibernateNoDefeat = true;
2839 DLOG("wake in %u secs for hibernateDisabled %d, hibernateAborted %d\n",
2840 params.sleepTimer, hibernateDisabled, hibernateAborted);
2841 }
2842 else
2843 hibernateNoDefeat = false;
2844
2845 paramsData = OSData::withBytes(&params, sizeof(params));
2846 if (paramsData)
2847 {
2848 setProperty(kIOPMSystemSleepParametersKey, paramsData);
2849 paramsData->release();
2850 }
2851
2852 if (params.sleepFlags & kIOPMSleepFlagHibernate)
2853 {
2854 // Force hibernate
2855 gIOHibernateMode &= ~kIOHibernateModeSleep;
2856 }
2857 }
2858 }
2859
2860 bool IOPMrootDomain::getHibernateSettings(
2861 uint32_t * hibernateMode,
2862 uint32_t * hibernateFreeRatio,
2863 uint32_t * hibernateFreeTime )
2864 {
2865 bool ok = getSleepOption(kIOHibernateModeKey, hibernateMode);
2866 getSleepOption(kIOHibernateFreeRatioKey, hibernateFreeRatio);
2867 getSleepOption(kIOHibernateFreeTimeKey, hibernateFreeTime);
2868 if (hibernateDisabled)
2869 *hibernateMode = 0;
2870 DLOG("hibernateMode 0x%x\n", *hibernateMode);
2871 return ok;
2872 }
2873
2874 bool IOPMrootDomain::getSleepOption( const char * key, uint32_t * option )
2875 {
2876 OSObject * optionsProp;
2877 OSDictionary * optionsDict;
2878 OSObject * obj = 0;
2879 OSNumber * num;
2880 bool ok = false;
2881
2882 optionsProp = copyProperty(kRootDomainSleepOptionsKey);
2883 optionsDict = OSDynamicCast(OSDictionary, optionsProp);
2884
2885 if (optionsDict)
2886 {
2887 obj = optionsDict->getObject(key);
2888 if (obj) obj->retain();
2889 }
2890 if (!obj)
2891 {
2892 obj = copyProperty(key);
2893 }
2894 if (obj && (num = OSDynamicCast(OSNumber, obj)))
2895 {
2896 *option = num->unsigned32BitValue();
2897 ok = true;
2898 }
2899
2900 if (obj)
2901 obj->release();
2902 if (optionsProp)
2903 optionsProp->release();
2904
2905 return true;
2906 }
2907 #endif /* HIBERNATION */
2908
2909
2910 //******************************************************************************
2911 // dispatchPowerEvent
2912 //
2913 // IOPMPowerStateQueue callback function. Running on PM work loop thread.
2914 //******************************************************************************
2915
2916 void IOPMrootDomain::dispatchPowerEvent(
2917 uint32_t event, void * arg0, uint64_t arg1 )
2918 {
2919 DLOG("power event %u args %p 0x%llx\n", event, arg0, arg1);
2920 ASSERT_GATED();
2921
2922 switch (event)
2923 {
2924 case kPowerEventFeatureChanged:
2925 messageClients(kIOPMMessageFeatureChange, this);
2926 break;
2927
2928 case kPowerEventReceivedPowerNotification:
2929 handlePowerNotification( (UInt32)(uintptr_t) arg0 );
2930 break;
2931
2932 case kPowerEventSystemBootCompleted:
2933 if (systemBooting)
2934 {
2935 systemBooting = false;
2936 adjustPowerState();
2937
2938 // If lid is closed, re-send lid closed notification
2939 // now that booting is complete.
2940 if( clamshellIsClosed )
2941 {
2942 handlePowerNotification(kLocalEvalClamshellCommand);
2943 }
2944 }
2945 break;
2946
2947 case kPowerEventSystemShutdown:
2948 if (kOSBooleanTrue == (OSBoolean *) arg0)
2949 {
2950 /* We set systemShutdown = true during shutdown
2951 to prevent sleep at unexpected times while loginwindow is trying
2952 to shutdown apps and while the OS is trying to transition to
2953 complete power of.
2954
2955 Set to true during shutdown, as soon as loginwindow shows
2956 the "shutdown countdown dialog", through individual app
2957 termination, and through black screen kernel shutdown.
2958 */
2959 LOG("systemShutdown true\n");
2960 systemShutdown = true;
2961 } else {
2962 /*
2963 A shutdown was initiated, but then the shutdown
2964 was cancelled, clearing systemShutdown to false here.
2965 */
2966 LOG("systemShutdown false\n");
2967 systemShutdown = false;
2968 }
2969 break;
2970
2971 case kPowerEventUserDisabledSleep:
2972 userDisabledAllSleep = (kOSBooleanTrue == (OSBoolean *) arg0);
2973 break;
2974
2975 #if ROOT_DOMAIN_RUN_STATES
2976 case kPowerEventConfigdRegisteredInterest:
2977 if (gConfigdNotifier)
2978 {
2979 gConfigdNotifier->release();
2980 gConfigdNotifier = 0;
2981 }
2982 if (arg0)
2983 {
2984 gConfigdNotifier = (IONotifier *) arg0;
2985 }
2986 break;
2987 #endif
2988
2989 case kPowerEventAggressivenessChanged:
2990 aggressivenessChanged();
2991 break;
2992
2993 case kPowerEventAssertionCreate:
2994 if (pmAssertions) {
2995 pmAssertions->handleCreateAssertion((OSData *)arg0);
2996 }
2997 break;
2998
2999 case kPowerEventAssertionRelease:
3000 if (pmAssertions) {
3001 pmAssertions->handleReleaseAssertion(arg1);
3002 }
3003 break;
3004
3005 case kPowerEventAssertionSetLevel:
3006 if (pmAssertions) {
3007 pmAssertions->handleSetAssertionLevel(arg1, (IOPMDriverAssertionLevel)(uintptr_t)arg0);
3008 }
3009 break;
3010 }
3011 }
3012
3013
3014 //******************************************************************************
3015 // systemPowerEventOccurred
3016 //
3017 // The power controller is notifying us of a hardware-related power management
3018 // event that we must handle.
3019 //
3020 // systemPowerEventOccurred covers the same functionality that
3021 // receivePowerNotification does; it simply provides a richer API for conveying
3022 // more information.
3023 //******************************************************************************
3024
3025 IOReturn IOPMrootDomain::systemPowerEventOccurred(
3026 const OSSymbol *event,
3027 uint32_t intValue)
3028 {
3029 IOReturn attempt = kIOReturnSuccess;
3030 OSNumber *newNumber = NULL;
3031
3032 if (!event)
3033 return kIOReturnBadArgument;
3034
3035 newNumber = OSNumber::withNumber(intValue, 8*sizeof(intValue));
3036 if (!newNumber)
3037 return kIOReturnInternalError;
3038
3039 attempt = systemPowerEventOccurred(event, (OSObject *)newNumber);
3040
3041 newNumber->release();
3042
3043 return attempt;
3044 }
3045
3046 IOReturn IOPMrootDomain::systemPowerEventOccurred(
3047 const OSSymbol *event,
3048 OSObject *value)
3049 {
3050 OSDictionary *thermalsDict = NULL;
3051 bool shouldUpdate = true;
3052
3053 if (!event || !value)
3054 return kIOReturnBadArgument;
3055
3056 // LOCK
3057 // We reuse featuresDict Lock because it already exists and guards
3058 // the very infrequently used publish/remove feature mechanism; so there's zero rsk
3059 // of stepping on that lock.
3060 if (featuresDictLock) IOLockLock(featuresDictLock);
3061
3062 thermalsDict = (OSDictionary *)getProperty(kIOPMRootDomainPowerStatusKey);
3063
3064 if (thermalsDict && OSDynamicCast(OSDictionary, thermalsDict)) {
3065 thermalsDict = OSDictionary::withDictionary(thermalsDict);
3066 } else {
3067 thermalsDict = OSDictionary::withCapacity(1);
3068 }
3069
3070 if (!thermalsDict) {
3071 shouldUpdate = false;
3072 goto exit;
3073 }
3074
3075 thermalsDict->setObject (event, value);
3076
3077 setProperty (kIOPMRootDomainPowerStatusKey, thermalsDict);
3078
3079 thermalsDict->release();
3080
3081 exit:
3082 // UNLOCK
3083 if (featuresDictLock) IOLockUnlock(featuresDictLock);
3084
3085 if (shouldUpdate)
3086 messageClients (kIOPMMessageSystemPowerEventOccurred, (void *)NULL);
3087
3088 return kIOReturnSuccess;
3089 }
3090
3091
3092 //******************************************************************************
3093 // receivePowerNotification
3094 //
3095 // The power controller is notifying us of a hardware-related power management
3096 // event that we must handle. This may be a result of an 'environment' interrupt
3097 // from the power mgt micro.
3098 //******************************************************************************
3099
3100 IOReturn IOPMrootDomain::receivePowerNotification( UInt32 msg )
3101 {
3102 pmPowerStateQueue->submitPowerEvent(
3103 kPowerEventReceivedPowerNotification, (void *) msg );
3104 return kIOReturnSuccess;
3105 }
3106
3107 void IOPMrootDomain::handlePowerNotification( UInt32 msg )
3108 {
3109 bool eval_clamshell = false;
3110
3111 ASSERT_GATED();
3112
3113 /*
3114 * Local (IOPMrootDomain only) eval clamshell command
3115 */
3116 if (msg & kLocalEvalClamshellCommand)
3117 {
3118 eval_clamshell = true;
3119 }
3120
3121 /*
3122 * Overtemp
3123 */
3124 if (msg & kIOPMOverTemp)
3125 {
3126 LOG("PowerManagement emergency overtemp signal. Going to sleep!");
3127 privateSleepSystem (kIOPMSleepReasonThermalEmergency);
3128 }
3129
3130 #ifdef __ppc__
3131 /*
3132 * PMU Processor Speed Change
3133 */
3134 if (msg & kIOPMProcessorSpeedChange)
3135 {
3136 IOService *pmu = waitForService(serviceMatching("ApplePMU"));
3137 pmu->callPlatformFunction("prepareForSleep", false, 0, 0, 0, 0);
3138 getPlatform()->sleepKernel();
3139 pmu->callPlatformFunction("recoverFromSleep", false, 0, 0, 0, 0);
3140 }
3141 #endif
3142
3143 /*
3144 * Sleep Now!
3145 */
3146 if (msg & kIOPMSleepNow)
3147 {
3148 privateSleepSystem (kIOPMSleepReasonSoftware);
3149 }
3150
3151 /*
3152 * Power Emergency
3153 */
3154 if (msg & kIOPMPowerEmergency)
3155 {
3156 lowBatteryCondition = true;
3157 privateSleepSystem (kIOPMSleepReasonLowPower);
3158 }
3159
3160 /*
3161 * Clamshell OPEN
3162 */
3163 if (msg & kIOPMClamshellOpened)
3164 {
3165 // Received clamshel open message from clamshell controlling driver
3166 // Update our internal state and tell general interest clients
3167 clamshellIsClosed = false;
3168 clamshellExists = true;
3169
3170 // Tell PMCPU
3171 informCPUStateChange(kInformLid, 0);
3172
3173 // Tell general interest clients
3174 sendClientClamshellNotification();
3175
3176 bool aborting = ((lastSleepReason == kIOPMSleepReasonClamshell)
3177 || (lastSleepReason == kIOPMSleepReasonIdle)
3178 || (lastSleepReason == kIOPMSleepReasonMaintenance));
3179 if (aborting) userActivityCount++;
3180 DLOG("clamshell tickled %d lastSleepReason %d\n", userActivityCount, lastSleepReason);
3181 }
3182
3183 /*
3184 * Clamshell CLOSED
3185 * Send the clamshell interest notification since the lid is closing.
3186 */
3187 if (msg & kIOPMClamshellClosed)
3188 {
3189 // Received clamshel open message from clamshell controlling driver
3190 // Update our internal state and tell general interest clients
3191 clamshellIsClosed = true;
3192 clamshellExists = true;
3193
3194 // Tell PMCPU
3195 informCPUStateChange(kInformLid, 1);
3196
3197 // Tell general interest clients
3198 sendClientClamshellNotification();
3199
3200 // And set eval_clamshell = so we can attempt
3201 eval_clamshell = true;
3202 }
3203
3204 /*
3205 * Set Desktop mode (sent from graphics)
3206 *
3207 * -> reevaluate lid state
3208 */
3209 if (msg & kIOPMSetDesktopMode)
3210 {
3211 desktopMode = (0 != (msg & kIOPMSetValue));
3212 msg &= ~(kIOPMSetDesktopMode | kIOPMSetValue);
3213
3214 sendClientClamshellNotification();
3215
3216 // Re-evaluate the lid state
3217 if( clamshellIsClosed )
3218 {
3219 eval_clamshell = true;
3220 }
3221 }
3222
3223 /*
3224 * AC Adaptor connected
3225 *
3226 * -> reevaluate lid state
3227 */
3228 if (msg & kIOPMSetACAdaptorConnected)
3229 {
3230 acAdaptorConnected = (0 != (msg & kIOPMSetValue));
3231 msg &= ~(kIOPMSetACAdaptorConnected | kIOPMSetValue);
3232
3233 // Tell CPU PM
3234 informCPUStateChange(kInformAC, !acAdaptorConnected);
3235
3236 // Tell BSD if AC is connected
3237 // 0 == external power source; 1 == on battery
3238 post_sys_powersource(acAdaptorConnected ? 0:1);
3239
3240 sendClientClamshellNotification();
3241
3242 // Re-evaluate the lid state
3243 if( clamshellIsClosed )
3244 {
3245 eval_clamshell = true;
3246 }
3247 }
3248
3249 /*
3250 * Enable Clamshell (external display disappear)
3251 *
3252 * -> reevaluate lid state
3253 */
3254 if (msg & kIOPMEnableClamshell)
3255 {
3256 // Re-evaluate the lid state
3257 // System should sleep on external display disappearance
3258 // in lid closed operation.
3259 if( clamshellIsClosed && (true == ignoringClamshell) )
3260 {
3261 eval_clamshell = true;
3262 }
3263
3264 ignoringClamshell = false;
3265
3266 sendClientClamshellNotification();
3267 }
3268
3269 /*
3270 * Disable Clamshell (external display appeared)
3271 * We don't bother re-evaluating clamshell state. If the system is awake,
3272 * the lid is probably open.
3273 */
3274 if (msg & kIOPMDisableClamshell)
3275 {
3276 ignoringClamshell = true;
3277
3278 sendClientClamshellNotification();
3279 }
3280
3281 /*
3282 * Evaluate clamshell and SLEEP if appropiate
3283 */
3284 if ( eval_clamshell && shouldSleepOnClamshellClosed() )
3285 {
3286
3287
3288 // SLEEP!
3289 privateSleepSystem (kIOPMSleepReasonClamshell);
3290 }
3291
3292 /*
3293 * Power Button
3294 */
3295 if (msg & kIOPMPowerButton)
3296 {
3297 // toggle state of sleep/wake
3298 // are we dozing?
3299 if ( getPowerState() == DOZE_STATE )
3300 {
3301 #ifndef __LP64__
3302 // yes, tell the tree we're waking
3303 systemWake();
3304 #endif
3305 // wake the Display Wrangler
3306 reportUserInput();
3307 }
3308 else {
3309 OSString *pbs = OSString::withCString("DisablePowerButtonSleep");
3310 // Check that power button sleep is enabled
3311 if( pbs ) {
3312 if( kOSBooleanTrue != getProperty(pbs))
3313 privateSleepSystem (kIOPMSleepReasonPowerButton);
3314 }
3315 }
3316 }
3317
3318 /*
3319 * Allow Sleep
3320 *
3321 */
3322 if ( (msg & kIOPMAllowSleep) && !allowSleep )
3323 {
3324 allowSleep = true;
3325 adjustPowerState();
3326 }
3327
3328 /*
3329 * Prevent Sleep
3330 *
3331 */
3332 if (msg & kIOPMPreventSleep) {
3333 allowSleep = false;
3334 // are we dozing?
3335 if ( getPowerState() == DOZE_STATE ) {
3336 #ifndef __LP64__
3337 // yes, tell the tree we're waking
3338 systemWake();
3339 #endif
3340 adjustPowerState();
3341 // wake the Display Wrangler
3342 reportUserInput();
3343 } else {
3344 adjustPowerState();
3345 // make sure we have power to clamp
3346 patriarch->wakeSystem();
3347 }
3348 }
3349 }
3350
3351
3352 //******************************************************************************
3353 // getSleepSupported
3354 //
3355 //******************************************************************************
3356
3357 IOOptionBits IOPMrootDomain::getSleepSupported( void )
3358 {
3359 return( platformSleepSupport );
3360 }
3361
3362
3363 //******************************************************************************
3364 // setSleepSupported
3365 //
3366 //******************************************************************************
3367
3368 void IOPMrootDomain::setSleepSupported( IOOptionBits flags )
3369 {
3370 DLOG("setSleepSupported(%x)\n", (uint32_t) flags);
3371 OSBitOrAtomic(flags, &platformSleepSupport);
3372 }
3373
3374
3375 //******************************************************************************
3376 // requestPowerDomainState
3377 //
3378 // The root domain intercepts this call to the superclass.
3379 // Called on the PM work loop thread.
3380 //
3381 // If the clamp bit is not set in the desire, then the child doesn't need the power
3382 // state it's requesting; it just wants it. The root ignores desires but not needs.
3383 // If the clamp bit is not set, the root takes it that the child can tolerate no
3384 // power and interprets the request accordingly. If all children can thus tolerate
3385 // no power, we are on our way to idle sleep.
3386 //******************************************************************************
3387
3388 IOReturn IOPMrootDomain::requestPowerDomainState (
3389 IOPMPowerFlags desiredFlags,
3390 IOPowerConnection * whichChild,
3391 unsigned long specification )
3392 {
3393 OSIterator *iter;
3394 OSObject *next;
3395 IOPowerConnection *connection;
3396 IOPMPowerFlags powerRequestFlag = 0;
3397 IOPMPowerFlags editedDesire;
3398
3399 ASSERT_GATED();
3400
3401 if (kIOLogPMRootDomain & gIOKitDebug)
3402 {
3403 IOService * powerChild =
3404 (IOService *) whichChild->getChildEntry(gIOPowerPlane);
3405 DLOG("child %p, flags %lx, spec %lx - %s\n",
3406 powerChild, desiredFlags, specification,
3407 powerChild ? powerChild->getName() : "?");
3408 }
3409
3410 // Force the child's input power requirements to 0 unless the prevent
3411 // idle-sleep flag is set. No input power flags map to our state 0.
3412 // Our power clamp (deviceDesire) keeps the minimum power state at 2.
3413
3414 if (desiredFlags & kIOPMPreventIdleSleep)
3415 editedDesire = kIOPMPreventIdleSleep | kIOPMPowerOn;
3416 else
3417 editedDesire = 0;
3418
3419 // Recompute sleep supported flag (doze if not supported)
3420 sleepIsSupported = true;
3421
3422 iter = getChildIterator(gIOPowerPlane);
3423 if ( iter )
3424 {
3425 while ( (next = iter->getNextObject()) )
3426 {
3427 if ( (connection = OSDynamicCast(IOPowerConnection, next)) )
3428 {
3429 // Ignore child that are in the process of joining.
3430 if (connection->getReadyFlag() == false)
3431 continue;
3432
3433 // Is this connection attached to the child that called
3434 // requestPowerDomainState()?
3435
3436 if (connection == whichChild)
3437 {
3438 // OR in the child's input power requirements.
3439 powerRequestFlag |= editedDesire;
3440
3441 if ( desiredFlags & kIOPMPreventSystemSleep )
3442 sleepIsSupported = false;
3443 }
3444 else
3445 {
3446 if (kIOLogPMRootDomain & gIOKitDebug)
3447 {
3448 IOService * powerChild =
3449 (IOService *) connection->getChildEntry(gIOPowerPlane);
3450 DLOG("child %p, state %ld, noIdle %d, noSleep %d - %s\n",
3451 powerChild,
3452 connection->getDesiredDomainState(),
3453 connection->getPreventIdleSleepFlag(),
3454 connection->getPreventSystemSleepFlag(),
3455 powerChild ? powerChild->getName() : "?");
3456 }
3457
3458 // OR in the child's desired power state (0 or ON_STATE).
3459 powerRequestFlag |= connection->getDesiredDomainState();
3460
3461 if ( connection->getPreventSystemSleepFlag() )
3462 sleepIsSupported = false;
3463 }
3464 }
3465 }
3466 iter->release();
3467 }
3468
3469 DLOG("childPowerFlags 0x%lx, extraSleepDelay %ld\n",
3470 powerRequestFlag, extraSleepDelay);
3471
3472 if ( !powerRequestFlag && !systemBooting )
3473 {
3474 if (!wrangler)
3475 {
3476 sleepASAP = false;
3477 changePowerStateToPriv(ON_STATE);
3478 if (idleSeconds)
3479 {
3480 // stay awake for at least idleSeconds
3481 startIdleSleepTimer(idleSeconds);
3482 }
3483 }
3484 else if (!extraSleepDelay && !idleSleepTimerPending)
3485 {
3486 sleepASAP = true;
3487 }
3488 }
3489
3490 // Drop our power clamp to SLEEP_STATE when all children became idle,
3491 // and the system sleep and display sleep values are equal.
3492
3493 adjustPowerState();
3494
3495 // If our power clamp has already dropped to SLEEP_STATE, and no child
3496 // is keeping us at ON_STATE, then this will trigger idle sleep.
3497
3498 editedDesire |= (desiredFlags & kIOPMPreventSystemSleep);
3499
3500 return super::requestPowerDomainState(
3501 editedDesire, whichChild, specification);
3502 }
3503
3504
3505 //******************************************************************************
3506 // handlePlatformHaltRestart
3507 //
3508 //******************************************************************************
3509
3510 struct HaltRestartApplierContext {
3511 IOPMrootDomain * RootDomain;
3512 unsigned long PowerState;
3513 IOPMPowerFlags PowerFlags;
3514 UInt32 MessageType;
3515 UInt32 Counter;
3516 };
3517
3518 static void
3519 platformHaltRestartApplier( OSObject * object, void * context )
3520 {
3521 IOPowerStateChangeNotification notify;
3522 HaltRestartApplierContext * ctx;
3523 AbsoluteTime startTime;
3524 UInt32 deltaTime;
3525
3526 ctx = (HaltRestartApplierContext *) context;
3527
3528 memset(&notify, 0, sizeof(notify));
3529 notify.powerRef = (void *)ctx->Counter;
3530 notify.returnValue = 0;
3531 notify.stateNumber = ctx->PowerState;
3532 notify.stateFlags = ctx->PowerFlags;
3533
3534 clock_get_uptime(&startTime);
3535 ctx->RootDomain->messageClient( ctx->MessageType, object, (void *)&notify );
3536 deltaTime = computeDeltaTimeMS(&startTime);
3537
3538 if ((deltaTime > kPMHaltTimeoutMS) || (gIOKitDebug & kIOLogDebugPower))
3539 {
3540 _IOServiceInterestNotifier * notifier;
3541 notifier = OSDynamicCast(_IOServiceInterestNotifier, object);
3542
3543 // IOService children of IOPMrootDomain are not instrumented.
3544 // Only IORootParent currently falls under that group.
3545
3546 if (notifier)
3547 {
3548 KLOG("%s handler %p took %u ms\n",
3549 (ctx->MessageType == kIOMessageSystemWillPowerOff) ?
3550 "PowerOff" : "Restart",
3551 notifier->handler, (uint32_t) deltaTime );
3552 }
3553 }
3554
3555 ctx->Counter++;
3556 }
3557
3558 void IOPMrootDomain::handlePlatformHaltRestart( UInt32 pe_type )
3559 {
3560 HaltRestartApplierContext ctx;
3561 AbsoluteTime startTime;
3562 UInt32 deltaTime;
3563
3564 memset(&ctx, 0, sizeof(ctx));
3565 ctx.RootDomain = this;
3566
3567 clock_get_uptime(&startTime);
3568 switch (pe_type)
3569 {
3570 case kPEHaltCPU:
3571 case kPEUPSDelayHaltCPU:
3572 ctx.PowerState = OFF_STATE;
3573 ctx.MessageType = kIOMessageSystemWillPowerOff;
3574 break;
3575
3576 case kPERestartCPU:
3577 ctx.PowerState = RESTART_STATE;
3578 ctx.MessageType = kIOMessageSystemWillRestart;
3579 break;
3580
3581 default:
3582 return;
3583 }
3584
3585 // Notify legacy clients
3586 applyToInterested(gIOPriorityPowerStateInterest, platformHaltRestartApplier, &ctx);
3587
3588 // For UPS shutdown leave File Server Mode intact, otherwise turn it off.
3589 if (kPEUPSDelayHaltCPU != pe_type)
3590 {
3591 const OSSymbol * setting = OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey);
3592 OSNumber * num = OSNumber::withNumber((unsigned long long) 0, 32);
3593 if (setting && num)
3594 {
3595 setPMSetting(setting, num);
3596 setting->release();
3597 num->release();
3598 }
3599 }
3600
3601 // Notify in power tree order
3602 notifySystemShutdown(this, ctx.MessageType);
3603
3604 deltaTime = computeDeltaTimeMS(&startTime);
3605 KLOG("%s all drivers took %u ms\n",
3606 (ctx.MessageType == kIOMessageSystemWillPowerOff) ?
3607 "PowerOff" : "Restart",
3608 (uint32_t) deltaTime );
3609 }
3610
3611
3612 //******************************************************************************
3613 // registerInterest
3614 //
3615 //******************************************************************************
3616
3617 IONotifier * IOPMrootDomain::registerInterest(
3618 const OSSymbol * typeOfInterest,
3619 IOServiceInterestHandler handler,
3620 void * target, void * ref )
3621 {
3622 IONotifier * notifier;
3623 bool isConfigd;
3624
3625 isConfigd = typeOfInterest &&
3626 typeOfInterest->isEqualTo(kIOPMPrivilegedPowerInterest);
3627
3628 if (isConfigd)
3629 typeOfInterest = gIOAppPowerStateInterest;
3630
3631 notifier = super::registerInterest(typeOfInterest, handler, target, ref);
3632
3633 #if ROOT_DOMAIN_RUN_STATES
3634 if (isConfigd && notifier && pmPowerStateQueue)
3635 {
3636 notifier->retain();
3637 if (pmPowerStateQueue->submitPowerEvent(
3638 kPowerEventConfigdRegisteredInterest, notifier) == false)
3639 notifier->release();
3640 }
3641 #endif
3642
3643 return notifier;
3644 }
3645
3646 static bool clientMessageFilter( OSObject * object, void * arg )
3647 {
3648 #if ROOT_DOMAIN_RUN_STATES
3649 #if LOG_INTEREST_CLIENTS
3650 IOPMInterestContext * context = (IOPMInterestContext *) arg;
3651 #endif
3652 bool allow = false;
3653
3654 switch (gMessageClientType)
3655 {
3656 case kMessageClientNone:
3657 allow = false;
3658 break;
3659
3660 case kMessageClientAll:
3661 allow = true;
3662 break;
3663
3664 case kMessageClientConfigd:
3665 allow = ((object == (OSObject *) gConfigdNotifier) ||
3666 (object == (OSObject *) gSysPowerDownNotifier));
3667 break;
3668 }
3669
3670 #if LOG_INTEREST_CLIENTS
3671 if (allow)
3672 DLOG("system message %x to %p\n",
3673 context->msgType, object);
3674 #endif
3675
3676 return allow;
3677 #else
3678 return true;
3679 #endif
3680 }
3681
3682
3683 //******************************************************************************
3684 // tellChangeDown
3685 //
3686 // We override the superclass implementation so we can send a different message
3687 // type to the client or application being notified.
3688 //******************************************************************************
3689
3690 bool IOPMrootDomain::tellChangeDown( unsigned long stateNum )
3691 {
3692 bool done;
3693
3694 DLOG("tellChangeDown %u->%u, R-state %u\n",
3695 (uint32_t) getPowerState(), (uint32_t) stateNum, runStateIndex);
3696
3697 switch ( stateNum ) {
3698 case DOZE_STATE:
3699 case SLEEP_STATE:
3700
3701 if (!ignoreChangeDown)
3702 {
3703 userActivityAtSleep = userActivityCount;
3704 hibernateAborted = false;
3705 DLOG("tellChangeDown::userActivityAtSleep %d\n", userActivityAtSleep);
3706
3707 // Direct callout into OSKext so it can disable kext unloads
3708 // during sleep/wake to prevent deadlocks.
3709 OSKextSystemSleepOrWake( kIOMessageSystemWillSleep );
3710
3711 if ( (SLEEP_STATE == stateNum) && sleepSupportedPEFunction )
3712 {
3713 // Reset PCI prevent sleep flag before calling platform driver.
3714 OSBitAndAtomic(~kPCICantSleep, &platformSleepSupport);
3715
3716 // Skip PCI check for maintenance sleep.
3717 if ((runStateFlags & kRStateFlagSuppressPCICheck) == 0)
3718 {
3719 // Determine if the machine supports sleep, or must doze.
3720 getPlatform()->callPlatformFunction(
3721 sleepSupportedPEFunction, false,
3722 NULL, NULL, NULL, NULL);
3723 }
3724
3725 // If the machine only supports doze, the callPlatformFunction call
3726 // boils down to IOPMrootDomain::setSleepSupported(kPCICantSleep),
3727 // otherwise nothing.
3728 }
3729
3730 // Notify platform that sleep has begun
3731 getPlatform()->callPlatformFunction(
3732 sleepMessagePEFunction, false,
3733 (void *)(uintptr_t) kIOMessageSystemWillSleep,
3734 NULL, NULL, NULL);
3735
3736 // Update canSleep and kIOSleepSupportedKey property so drivers
3737 // can tell if platform is going to sleep versus doze.
3738
3739 #if CONFIG_SLEEP
3740 canSleep = true;
3741 #else
3742 canSleep = false;
3743 #endif
3744 if (!sleepIsSupported)
3745 canSleep = false;
3746 if (platformSleepSupport & kPCICantSleep)
3747 canSleep = false;
3748 setProperty(kIOSleepSupportedKey, canSleep);
3749 DLOG("canSleep %d\n", canSleep);
3750
3751 // Publish the new sleep-wake UUID
3752 publishSleepWakeUUID(true);
3753
3754 // Two change downs are sent by IOServicePM. Ignore the 2nd.
3755 ignoreChangeDown = true;
3756
3757 tracePoint( kIOPMTracePointSystemSleepAppsPhase);
3758 }
3759
3760 DLOG("kIOMessageSystemWillSleep (%d)\n", gMessageClientType);
3761 done = super::tellClientsWithResponse(
3762 kIOMessageSystemWillSleep, clientMessageFilter);
3763 break;
3764
3765 default:
3766 done = super::tellChangeDown(stateNum);
3767 break;
3768 }
3769 return done;
3770 }
3771
3772
3773 //******************************************************************************
3774 // askChangeDown
3775 //
3776 // We override the superclass implementation so we can send a different message
3777 // type to the client or application being notified.
3778 //
3779 // This must be idle sleep since we don't ask during any other power change.
3780 //******************************************************************************
3781
3782 bool IOPMrootDomain::askChangeDown( unsigned long stateNum )
3783 {
3784 DLOG("askChangeDown %u->%u, R-state %u\n",
3785 (uint32_t) getPowerState(), (uint32_t) stateNum, runStateIndex);
3786 DLOG("kIOMessageCanSystemSleep (%d)\n", gMessageClientType);
3787
3788 return super::tellClientsWithResponse(
3789 kIOMessageCanSystemSleep,
3790 clientMessageFilter);
3791 }
3792
3793
3794 //******************************************************************************
3795 // tellNoChangeDown
3796 //
3797 // Notify registered applications and kernel clients that we are not dropping
3798 // power.
3799 //
3800 // We override the superclass implementation so we can send a different message
3801 // type to the client or application being notified.
3802 //
3803 // This must be a vetoed idle sleep, since no other power change can be vetoed.
3804 //******************************************************************************
3805
3806 void IOPMrootDomain::tellNoChangeDown( unsigned long stateNum )
3807 {
3808 DLOG("tellNoChangeDown %u->%u, R-state %u\n",
3809 (uint32_t) getPowerState(), (uint32_t) stateNum, runStateIndex);
3810
3811 // Sleep canceled, clear the sleep trace point.
3812 tracePoint(kIOPMTracePointSystemUp);
3813
3814 if (idleSeconds && !wrangler)
3815 {
3816 // stay awake for at least idleSeconds
3817 sleepASAP = false;
3818 startIdleSleepTimer(idleSeconds);
3819 }
3820 DLOG("kIOMessageSystemWillNotSleep (%d)\n", gMessageClientType);
3821 return tellClients(kIOMessageSystemWillNotSleep, clientMessageFilter);
3822 }
3823
3824
3825 //******************************************************************************
3826 // tellChangeUp
3827 //
3828 // Notify registered applications and kernel clients that we are raising power.
3829 //
3830 // We override the superclass implementation so we can send a different message
3831 // type to the client or application being notified.
3832 //******************************************************************************
3833
3834 void IOPMrootDomain::tellChangeUp( unsigned long stateNum )
3835 {
3836 OSData *publishPMStats = NULL;
3837
3838 DLOG("tellChangeUp %u->%u, R-state %u\n",
3839 (uint32_t) getPowerState(), (uint32_t) stateNum, runStateIndex);
3840
3841 ignoreChangeDown = false;
3842
3843 if ( stateNum == ON_STATE )
3844 {
3845 // Direct callout into OSKext so it can disable kext unloads
3846 // during sleep/wake to prevent deadlocks.
3847 OSKextSystemSleepOrWake( kIOMessageSystemHasPoweredOn );
3848
3849 // Notify platform that sleep was cancelled or resumed.
3850 getPlatform()->callPlatformFunction(
3851 sleepMessagePEFunction, false,
3852 (void *)(uintptr_t) kIOMessageSystemHasPoweredOn,
3853 NULL, NULL, NULL);
3854
3855 if (getPowerState() == ON_STATE)
3856 {
3857 // this is a quick wake from aborted sleep
3858 if (idleSeconds && !wrangler)
3859 {
3860 // stay awake for at least idleSeconds
3861 sleepASAP = false;
3862 startIdleSleepTimer(idleSeconds);
3863 }
3864 DLOG("kIOMessageSystemWillPowerOn (%d)\n", gMessageClientType);
3865 tellClients(kIOMessageSystemWillPowerOn, clientMessageFilter);
3866 }
3867 #if HIBERNATION
3868 else
3869 {
3870 IOHibernateSystemPostWake();
3871 }
3872 #endif
3873
3874 tracePoint(kIOPMTracePointSystemWakeAppsPhase);
3875 publishPMStats = OSData::withBytes(&pmStats, sizeof(pmStats));
3876 setProperty(kIOPMSleepStatisticsKey, publishPMStats);
3877 publishPMStats->release();
3878 bzero(&pmStats, sizeof(pmStats));
3879
3880 if (pmStatsAppResponses)
3881 {
3882 setProperty(kIOPMSleepStatisticsAppsKey, pmStatsAppResponses);
3883 pmStatsAppResponses->release();
3884 pmStatsAppResponses = OSArray::withCapacity(5);
3885 }
3886
3887 DLOG("kIOMessageSystemHasPoweredOn (%d)\n", gMessageClientType);
3888 tellClients(kIOMessageSystemHasPoweredOn, clientMessageFilter);
3889
3890 tracePoint(kIOPMTracePointSystemUp);
3891 }
3892 }
3893
3894
3895 //******************************************************************************
3896 // reportUserInput
3897 //
3898 //******************************************************************************
3899
3900 void IOPMrootDomain::reportUserInput( void )
3901 {
3902 #if !NO_KERNEL_HID
3903 OSIterator * iter;
3904
3905 if(!wrangler)
3906 {
3907 iter = getMatchingServices(serviceMatching("IODisplayWrangler"));
3908 if(iter)
3909 {
3910 wrangler = (IOService *) iter->getNextObject();
3911 iter->release();
3912 }
3913 }
3914
3915 if(wrangler)
3916 wrangler->activityTickle(0,0);
3917 #endif
3918 }
3919
3920
3921 //******************************************************************************
3922 // setQuickSpinDownTimeout
3923 //
3924 //******************************************************************************
3925
3926 void IOPMrootDomain::setQuickSpinDownTimeout( void )
3927 {
3928 ASSERT_GATED();
3929 setAggressiveness(
3930 kPMMinutesToSpinDown, 0, kAggressivesOptionQuickSpindownEnable );
3931 }
3932
3933
3934 //******************************************************************************
3935 // restoreUserSpinDownTimeout
3936 //
3937 //******************************************************************************
3938
3939 void IOPMrootDomain::restoreUserSpinDownTimeout( void )
3940 {
3941 ASSERT_GATED();
3942 setAggressiveness(
3943 kPMMinutesToSpinDown, 0, kAggressivesOptionQuickSpindownDisable );
3944 }
3945
3946
3947 //******************************************************************************
3948 // changePowerStateTo & changePowerStateToPriv
3949 //
3950 // Override of these methods for logging purposes.
3951 //******************************************************************************
3952
3953 IOReturn IOPMrootDomain::changePowerStateTo( unsigned long ordinal )
3954 {
3955 return kIOReturnUnsupported; // ignored
3956 }
3957
3958 IOReturn IOPMrootDomain::changePowerStateToPriv( unsigned long ordinal )
3959 {
3960 DLOG("changePowerStateToPriv(%lu)\n", ordinal);
3961
3962 if ( (getPowerState() == DOZE_STATE) && (ordinal != ON_STATE) )
3963 {
3964 return kIOReturnSuccess;
3965 }
3966
3967 if ( (userDisabledAllSleep || systemBooting || systemShutdown) &&
3968 (ordinal == SLEEP_STATE) )
3969 {
3970 DLOG("SLEEP rejected, forced to ON state (UD %d, SB %d, SS %d)\n",
3971 userDisabledAllSleep, systemBooting, systemShutdown);
3972
3973 super::changePowerStateToPriv(ON_STATE);
3974 }
3975
3976 return super::changePowerStateToPriv(ordinal);
3977 }
3978
3979 //******************************************************************************
3980 // activity detect
3981 //
3982 //******************************************************************************
3983
3984 bool IOPMrootDomain::activitySinceSleep(void)
3985 {
3986 return (userActivityCount != userActivityAtSleep);
3987 }
3988
3989 bool IOPMrootDomain::abortHibernation(void)
3990 {
3991 bool ret = activitySinceSleep();
3992
3993 if (ret && !hibernateAborted)
3994 {
3995 DLOG("activitySinceSleep ABORT [%d, %d]\n", userActivityCount, userActivityAtSleep);
3996 hibernateAborted = true;
3997 }
3998 return (ret);
3999 }
4000
4001 extern "C" int
4002 hibernate_should_abort(void)
4003 {
4004 if (gRootDomain)
4005 return (gRootDomain->abortHibernation());
4006 else
4007 return (0);
4008 }
4009
4010 //******************************************************************************
4011 // updateRunState
4012 //
4013 //******************************************************************************
4014
4015 void IOPMrootDomain::updateRunState( uint32_t inRunState )
4016 {
4017 #if ROOT_DOMAIN_RUN_STATES
4018 if (inRunState < kRStateCount)
4019 {
4020 runStateIndex = nextRunStateIndex = inRunState;
4021 runStateFlags = gRStateFlags[inRunState];
4022
4023 setProperty(
4024 kIOPMRootDomainRunStateKey,
4025 (unsigned long long) inRunState, 32);
4026 }
4027 #endif
4028 }
4029
4030
4031 #if ROOT_DOMAIN_RUN_STATES
4032 //******************************************************************************
4033 // tagPowerPlaneService
4034 //
4035 // Running on PM work loop thread.
4036 //******************************************************************************
4037
4038 void IOPMrootDomain::tagPowerPlaneService(
4039 IOService * service,
4040 uint32_t * rdFlags )
4041 {
4042 *rdFlags = 0;
4043
4044 if (service->getProperty("IOPMStrictTreeOrder") ||
4045 service->metaCast("IODisplayWrangler") ||
4046 OSDynamicCast(OSNumber,
4047 service->getProperty("IOPMUnattendedWakePowerState")))
4048 {
4049 *rdFlags |= kServiceFlagGraphics;
4050 DLOG("tagged device %s %x\n", service->getName(), *rdFlags);
4051 }
4052
4053 // Locate the first PCI host bridge.
4054 if (!pciHostBridgeDevice && service->metaCast("IOPCIBridge"))
4055 {
4056 IOService * provider = service->getProvider();
4057 if (OSDynamicCast(IOPlatformDevice, provider) &&
4058 provider->inPlane(gIODTPlane))
4059 {
4060 pciHostBridgeDevice = provider;
4061 DLOG("PMTrace found PCI host bridge %s->%s\n",
4062 provider->getName(), service->getName());
4063 }
4064 }
4065
4066 // Tag top-level PCI devices. The order of PMinit() call does not
4067 // change across boots and is used as the PCI bit number.
4068 if (pciHostBridgeDevice && service->metaCast("IOPCIDevice"))
4069 {
4070 // Would prefer to check built-in property, but tagPowerPlaneService()
4071 // is called before pciDevice->registerService().
4072 IORegistryEntry * parent = service->getParentEntry(gIODTPlane);
4073 if ((parent == pciHostBridgeDevice) && service->getProperty("acpi-device"))
4074 {
4075 int bit = pmTracer->recordTopLevelPCIDevice( service );
4076 if (bit >= 0)
4077 {
4078 // Save the assigned bit for fast lookup.
4079 bit &= 0xff;
4080 *rdFlags |= (kServiceFlagTopLevelPCI | (bit << 8));
4081 }
4082 }
4083 }
4084 }
4085
4086
4087 //******************************************************************************
4088 // handleActivityTickleForService
4089 //
4090 // Called by IOService::activityTickle() for a tickle that is requesting the
4091 // service to raise power state. Called from driver thread.
4092 //******************************************************************************
4093
4094 void IOPMrootDomain::handleActivityTickleForService( IOService * service,
4095 unsigned long type,
4096 unsigned long currentPowerState,
4097 uint32_t activityTickleCount )
4098 {
4099 if ((service == wrangler)
4100 )
4101 {
4102 bool aborting = ((lastSleepReason == kIOPMSleepReasonIdle)
4103 || (lastSleepReason == kIOPMSleepReasonMaintenance));
4104 if (aborting) userActivityCount++;
4105 DLOG("display wrangler tickled1 %d lastSleepReason %d\n", userActivityCount, lastSleepReason);
4106 }
4107
4108 // Tickle directed to IODisplayWrangler while graphics is disabled.
4109 // Bring graphics online.
4110
4111 if ((!currentPowerState) &&
4112 (service == wrangler) &&
4113 (runStateIndex > kRStateNormal) &&
4114 (false == wranglerTickled) &&
4115 (false == lowBatteryCondition))
4116 {
4117 DLOG("display wrangler tickled\n");
4118 if (kIOLogPMRootDomain & gIOKitDebug)
4119 OSReportWithBacktrace("Display Tickle");
4120 wranglerTickled = true;
4121 synchronizePowerTree();
4122 }
4123 }
4124
4125 //******************************************************************************
4126 // handlePowerChangeStartForService
4127 //
4128 // Running on PM work loop thread.
4129 //******************************************************************************
4130
4131 void IOPMrootDomain::handlePowerChangeStartForService(
4132 IOService * service,
4133 uint32_t * rdFlags,
4134 uint32_t newPowerState,
4135 uint32_t changeFlags )
4136 {
4137 if (service == this)
4138 {
4139 uint32_t currentPowerState = (uint32_t) getPowerState();
4140 uint32_t nextRunStateFlags;
4141
4142 assert(nextRunStateIndex < kRStateCount);
4143 nextRunStateFlags = gRStateFlags[nextRunStateIndex];
4144
4145 gMessageClientType = kMessageClientNone;
4146
4147 // Transition towards or away from ON power state.
4148
4149 if ((currentPowerState != newPowerState) &&
4150 ((ON_STATE == newPowerState) || (ON_STATE == currentPowerState)))
4151 {
4152 if ((runStateFlags & kRStateFlagSuppressMessages) == 0)
4153 gMessageClientType = kMessageClientAll;
4154 else
4155 gMessageClientType = kMessageClientConfigd;
4156 }
4157
4158 // Transition caused by deassertion of system notification suppression.
4159
4160 if ((ON_STATE == newPowerState) &&
4161 (ON_STATE == currentPowerState) &&
4162 ((runStateFlags ^ nextRunStateFlags) & kRStateFlagSuppressMessages))
4163 {
4164 gMessageClientType = kMessageClientAll;
4165 }
4166
4167 if (ON_STATE == newPowerState)
4168 {
4169 DLOG("kIOMessageSystemWillPowerOn (%d)\n",
4170 gMessageClientType);
4171 tellClients(kIOMessageSystemWillPowerOn, clientMessageFilter);
4172 }
4173
4174 if (SLEEP_STATE == newPowerState)
4175 {
4176 tracePoint(kIOPMTracePointSleepStarted);
4177 }
4178 }
4179
4180 if (*rdFlags & kServiceFlagTopLevelPCI)
4181 {
4182 pmTracer->tracePCIPowerChange(
4183 PMTraceWorker::kPowerChangeStart,
4184 service, changeFlags,
4185 (*rdFlags >> 8) & 0xff);
4186 }
4187 }
4188
4189
4190 //******************************************************************************
4191 // handlePowerChangeDoneForService
4192 //
4193 // Running on PM work loop thread.
4194 //******************************************************************************
4195
4196 void IOPMrootDomain::handlePowerChangeDoneForService(
4197 IOService * service,
4198 uint32_t * rdFlags,
4199 uint32_t newPowerState,
4200 uint32_t changeFlags )
4201 {
4202 if (*rdFlags & kServiceFlagTopLevelPCI)
4203 {
4204 pmTracer->tracePCIPowerChange(
4205 PMTraceWorker::kPowerChangeCompleted,
4206 service, changeFlags,
4207 (*rdFlags >> 8) & 0xff);
4208 }
4209 }
4210
4211
4212 //******************************************************************************
4213 // overridePowerStateForService
4214 //
4215 // Runs on PM work loop thread.
4216 //******************************************************************************
4217
4218 void IOPMrootDomain::overridePowerStateForService(
4219 IOService * service,
4220 uint32_t * rdFlags,
4221 unsigned long * powerState,
4222 uint32_t changeFlags )
4223 {
4224 uint32_t inPowerState = (uint32_t) *powerState;
4225
4226 if ((service == this) && (inPowerState == ON_STATE) &&
4227 (changeFlags & kIOPMSynchronize))
4228 {
4229 DLOG("sync root domain %u->%u\n",
4230 (uint32_t) getPowerState(), inPowerState);
4231
4232 // Root Domain is in a reduced R-state, and a HID tickle has
4233 // requested a PM tree sync. Begin R-state transition.
4234
4235 if (runStateIndex != kRStateNormal)
4236 {
4237 sleepTimerMaintenance = false;
4238 hibernateNoDefeat = false;
4239 nextRunStateIndex = kRStateNormal;
4240 setProperty(
4241 kIOPMRootDomainRunStateKey,
4242 (unsigned long long) kRStateNormal, 32);
4243 }
4244 }
4245
4246 if (*rdFlags & kServiceFlagGraphics)
4247 {
4248 DLOG("graphics device %s %u->%u (flags 0x%x)\n",
4249 service->getName(), (uint32_t) service->getPowerState(),
4250 inPowerState, changeFlags);
4251
4252 if (inPowerState == 0)
4253 {
4254 // Graphics device is powering down, apply limit preventing
4255 // device from powering back up later unless we consent.
4256
4257 if ((*rdFlags & kServiceFlagNoPowerUp) == 0)
4258 {
4259 *rdFlags |= kServiceFlagNoPowerUp;
4260 DLOG("asserted power limit for %s\n",
4261 service->getName());
4262 }
4263 }
4264 else
4265 {
4266 uint32_t nextRunStateFlags;
4267
4268 assert(nextRunStateIndex < kRStateCount);
4269 nextRunStateFlags = gRStateFlags[nextRunStateIndex];
4270
4271 // Graphics device is powering up. Release power limit at the
4272 // did-change machine state.
4273
4274 if (changeFlags & kIOPMSynchronize)
4275 {
4276 if ((runStateFlags & kRStateFlagSuppressGraphics) &&
4277 ((nextRunStateFlags & kRStateFlagSuppressGraphics) == 0) &&
4278 (changeFlags & kIOPMDomainDidChange))
4279 {
4280 // Woke up without graphics power, but
4281 // HID event has tickled display wrangler.
4282 *rdFlags &= ~kServiceFlagNoPowerUp;
4283 DLOG("removed power limit for %s\n",
4284 service->getName());
4285 }
4286 }
4287 else if ((runStateFlags & kRStateFlagSuppressGraphics) == 0)
4288 {
4289 *rdFlags &= ~kServiceFlagNoPowerUp;
4290 }
4291
4292 if (*rdFlags & kServiceFlagNoPowerUp)
4293 {
4294 DLOG("limited %s to power state 0\n",
4295 service->getName());
4296 *powerState = 0;
4297 }
4298 }
4299 }
4300 }
4301
4302
4303 //******************************************************************************
4304 // setMaintenanceWakeCalendar
4305 //
4306 //******************************************************************************
4307
4308 IOReturn IOPMrootDomain::setMaintenanceWakeCalendar(
4309 const IOPMCalendarStruct * calendar )
4310 {
4311 OSData * data;
4312 IOReturn ret;
4313
4314 if (!calendar)
4315 return kIOReturnBadArgument;
4316
4317 data = OSData::withBytesNoCopy((void *) calendar, sizeof(*calendar));
4318 if (!data)
4319 return kIOReturnNoMemory;
4320
4321 ret = setPMSetting(gIOPMSettingMaintenanceWakeCalendarKey, data);
4322
4323 data->release();
4324 return ret;
4325 }
4326 #endif /* ROOT_DOMAIN_RUN_STATES */
4327
4328
4329 //******************************************************************************
4330 // sysPowerDownHandler
4331 //
4332 // Receives a notification when the RootDomain changes state.
4333 //
4334 // Allows us to take action on system sleep, power down, and restart after
4335 // applications have received their power change notifications and replied,
4336 // but before drivers have powered down. We perform a vfs sync on power down.
4337 //******************************************************************************
4338
4339 IOReturn IOPMrootDomain::sysPowerDownHandler( void * target, void * refCon,
4340 UInt32 messageType, IOService * service,
4341 void * messageArgument, vm_size_t argSize )
4342 {
4343 IOReturn ret;
4344 IOPowerStateChangeNotification *params = (IOPowerStateChangeNotification *) messageArgument;
4345 IOPMrootDomain *rootDomain = OSDynamicCast(IOPMrootDomain, service);
4346
4347 DLOG("sysPowerDownHandler message %x\n", (uint32_t) messageType);
4348
4349 if(!rootDomain)
4350 return kIOReturnUnsupported;
4351
4352 switch (messageType) {
4353 case kIOMessageSystemWillSleep:
4354 // Interested applications have been notified of an impending power
4355 // change and have acked (when applicable).
4356 // This is our chance to save whatever state we can before powering
4357 // down.
4358 // We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c,
4359 // via callout
4360 #if HIBERNATION
4361 rootDomain->evaluateSystemSleepPolicyEarly();
4362 if (rootDomain->hibernateMode && !rootDomain->hibernateDisabled)
4363 {
4364 // We will ack within 240 seconds
4365 params->returnValue = 240 * 1000 * 1000;
4366 }
4367 else
4368 #endif
4369 // We will ack within 20 seconds
4370 params->returnValue = 20 * 1000 * 1000;
4371 DLOG("sysPowerDownHandler timeout %d s\n", (int) (params->returnValue / 1000 / 1000));
4372 if ( ! OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending ) )
4373 {
4374 // Purposely delay the ack and hope that shutdown occurs quickly.
4375 // Another option is not to schedule the thread and wait for
4376 // ack timeout...
4377 AbsoluteTime deadline;
4378 clock_interval_to_deadline( 30, kSecondScale, &deadline );
4379 thread_call_enter1_delayed( rootDomain->diskSyncCalloutEntry,
4380 (thread_call_param_t)params->powerRef,
4381 deadline );
4382 }
4383 else
4384 thread_call_enter1(rootDomain->diskSyncCalloutEntry, (thread_call_param_t)params->powerRef);
4385 ret = kIOReturnSuccess;
4386 break;
4387
4388 case kIOMessageSystemWillPowerOff:
4389 case kIOMessageSystemWillRestart:
4390 ret = kIOReturnUnsupported;
4391 break;
4392
4393 default:
4394 ret = kIOReturnUnsupported;
4395 break;
4396 }
4397 return ret;
4398 }
4399
4400 //******************************************************************************
4401 // publishSleepWakeUUID
4402 //
4403 //
4404 //******************************************************************************
4405 void IOPMrootDomain::publishSleepWakeUUID( bool shouldPublish )
4406 {
4407 if (shouldPublish)
4408 {
4409 if (queuedSleepWakeUUIDString)
4410 {
4411 if (OSCompareAndSwap(/*old*/ true, /*new*/ false, &gSleepWakeUUIDIsSet))
4412 {
4413 // Upon wake, it takes some time for userland to invalidate the
4414 // UUID. If another sleep is initiated during that period, force
4415 // a CLEAR message to balance the upcoming SET message.
4416
4417 messageClients( kIOPMMessageSleepWakeUUIDChange,
4418 kIOPMMessageSleepWakeUUIDCleared );
4419
4420 DLOG("SleepWake UUID forced clear\n");
4421 }
4422
4423 setProperty(kIOPMSleepWakeUUIDKey, queuedSleepWakeUUIDString);
4424 DLOG("SleepWake UUID published: %s\n", queuedSleepWakeUUIDString->getCStringNoCopy());
4425 queuedSleepWakeUUIDString->release();
4426 queuedSleepWakeUUIDString = NULL;
4427 messageClients(kIOPMMessageSleepWakeUUIDChange,
4428 kIOPMMessageSleepWakeUUIDSet);
4429 }
4430 } else {
4431 if (OSCompareAndSwap(/*old*/ true, /*new*/ false, &gSleepWakeUUIDIsSet))
4432 {
4433 DLOG("SleepWake UUID cleared\n");
4434 removeProperty(kIOPMSleepWakeUUIDKey);
4435 messageClients(kIOPMMessageSleepWakeUUIDChange,
4436 kIOPMMessageSleepWakeUUIDCleared);
4437 }
4438 }
4439 }
4440
4441
4442 //******************************************************************************
4443 // displayWranglerNotification
4444 //
4445 // Receives a notification when the IODisplayWrangler changes state.
4446 //
4447 // Allows us to take action on display dim/undim.
4448 //
4449 // When the display sleeps we:
4450 // - Start the idle sleep timer
4451 // - set the quick spin down timeout
4452 //
4453 // On wake from display sleep:
4454 // - Cancel the idle sleep timer
4455 // - restore the user's chosen spindown timer from the "quick" spin down value
4456 //******************************************************************************
4457
4458 IOReturn IOPMrootDomain::displayWranglerNotification(
4459 void * target, void * refCon,
4460 UInt32 messageType, IOService * service,
4461 void * messageArgument, vm_size_t argSize )
4462 {
4463 #if !NO_KERNEL_HID
4464 int displayPowerState;
4465 IOPowerStateChangeNotification * params =
4466 (IOPowerStateChangeNotification *) messageArgument;
4467
4468 if ((messageType != kIOMessageDeviceWillPowerOff) &&
4469 (messageType != kIOMessageDeviceHasPoweredOn))
4470 return kIOReturnUnsupported;
4471
4472 ASSERT_GATED();
4473 if (!gRootDomain)
4474 return kIOReturnUnsupported;
4475
4476 displayPowerState = params->stateNumber;
4477 DLOG("DisplayWrangler message 0x%x, new power state %d\n",
4478 (uint32_t) messageType, displayPowerState);
4479
4480 switch (messageType) {
4481 case kIOMessageDeviceWillPowerOff:
4482
4483 // The display wrangler has dropped power because of idle display sleep
4484 // or force system sleep.
4485 //
4486 // 4 Display ON
4487 // 3 Display Dim
4488 // 2 Display Sleep
4489 // 1 Not visible to user
4490 // 0 Not visible to user
4491
4492 if (gRootDomain->wranglerAsleep || (displayPowerState > 2))
4493 break;
4494
4495 // Record the time the display wrangler went to sleep.
4496
4497 gRootDomain->wranglerAsleep = true;
4498 clock_get_uptime(&gRootDomain->wranglerSleepTime);
4499
4500 // We start a timer here if the System Sleep timer is greater than the
4501 // Display Sleep timer. We kick off this timer when the display sleeps.
4502 //
4503 // Note that, although Display Dim timings may change adaptively accordingly
4504 // to the user's activity patterns, Display Sleep _always_ occurs at the
4505 // specified interval since last user activity.
4506
4507 if ( gRootDomain->extraSleepDelay )
4508 {
4509 gRootDomain->startIdleSleepTimer(gRootDomain->extraSleepDelay * 60);
4510 }
4511 else if ( gRootDomain->sleepSlider )
4512 {
4513 // Accelerate disk spindown if system sleep and display sleep
4514 // sliders are set to the same value (e.g. both set to 5 min),
4515 // and display is about to go dark. Check that spin down timer
4516 // is non-zero (zero = never spin down) and system sleep is
4517 // not set to never sleep.
4518
4519 gRootDomain->setQuickSpinDownTimeout();
4520 }
4521
4522 break;
4523
4524 case kIOMessageDeviceHasPoweredOn:
4525
4526 // The display wrangler has powered on either because of user activity
4527 // or wake from sleep/doze.
4528
4529 if ( 4 != displayPowerState )
4530 break;
4531
4532 gRootDomain->wranglerAsleep = false;
4533 gRootDomain->adjustPowerState();
4534 gRootDomain->cancelIdleSleepTimer();
4535
4536 // Change the spindown value back to the user's selection from our
4537 // accelerated setting.
4538 gRootDomain->restoreUserSpinDownTimeout();
4539
4540 break;
4541
4542 default:
4543 break;
4544 }
4545 #endif
4546 return kIOReturnUnsupported;
4547 }
4548
4549
4550 //******************************************************************************
4551 // displayWranglerPublished
4552 //
4553 // Receives a notification when the IODisplayWrangler is published.
4554 // When it's published we install a power state change handler.
4555 //******************************************************************************
4556
4557 bool IOPMrootDomain::displayWranglerPublished(
4558 void * target,
4559 void * refCon,
4560 IOService * newService)
4561 {
4562 #if !NO_KERNEL_HID
4563 if(!gRootDomain)
4564 return false;
4565
4566 gRootDomain->wrangler = newService;
4567
4568 // we found the display wrangler, now install a handler
4569 if( !gRootDomain->wrangler->registerInterest( gIOGeneralInterest,
4570 &displayWranglerNotification, target, 0) )
4571 {
4572 return false;
4573 }
4574 #endif
4575 return true;
4576 }
4577
4578
4579 //******************************************************************************
4580 // batteryPublished
4581 //
4582 // Notification on battery class IOPowerSource appearance
4583 //******************************************************************************
4584
4585 bool IOPMrootDomain::batteryPublished(
4586 void * target,
4587 void * root_domain,
4588 IOService * resourceService )
4589 {
4590 // rdar://2936060&4435589
4591 // All laptops have dimmable LCD displays
4592 // All laptops have batteries
4593 // So if this machine has a battery, publish the fact that the backlight
4594 // supports dimming.
4595 ((IOPMrootDomain *)root_domain)->publishFeature("DisplayDims");
4596
4597 return (true);
4598 }
4599
4600
4601 //******************************************************************************
4602 // adjustPowerState
4603 //
4604 // Some condition that affects our wake/sleep/doze decision has changed.
4605 //
4606 // If the sleep slider is in the off position, we cannot sleep or doze.
4607 // If the enclosure is open, we cannot sleep or doze.
4608 // If the system is still booting, we cannot sleep or doze.
4609 //
4610 // In those circumstances, we prevent sleep and doze by holding power on with
4611 // changePowerStateToPriv(ON).
4612 //
4613 // If the above conditions do not exist, and also the sleep timer has expired,
4614 // we allow sleep or doze to occur with either changePowerStateToPriv(SLEEP) or
4615 // changePowerStateToPriv(DOZE) depending on whether or not we already know the
4616 // platform cannot sleep.
4617 //
4618 // In this case, sleep or doze will either occur immediately or at the next time
4619 // that no children are holding the system out of idle sleep via the
4620 // kIOPMPreventIdleSleep flag in their power state arrays.
4621 //******************************************************************************
4622
4623 void IOPMrootDomain::adjustPowerState( void )
4624 {
4625 DLOG("adjustPowerState "
4626 "PS %u, ASAP %d, SL %ld, AS %d, SB %d, SS %d, UD %d\n",
4627 (uint32_t) getPowerState(), sleepASAP, sleepSlider,
4628 allowSleep, systemBooting, systemShutdown, userDisabledAllSleep);
4629
4630 ASSERT_GATED();
4631
4632 if ( (sleepSlider == 0)
4633 || !allowSleep
4634 || systemBooting
4635 || systemShutdown
4636 || userDisabledAllSleep
4637 || (runStateFlags & kRStateFlagDisableIdleSleep) )
4638 {
4639 changePowerStateToPriv(ON_STATE);
4640 } else {
4641 if ( sleepASAP )
4642 {
4643 /* Convenient place to run any code at idle sleep time
4644 * IOPMrootDomain initiates an idle sleep here
4645 *
4646 * Set last sleep cause accordingly.
4647 */
4648 lastSleepReason = kIOPMSleepReasonIdle;
4649 setProperty(kRootDomainSleepReasonKey, kIOPMIdleSleepKey);
4650
4651 sleepASAP = false;
4652 changePowerStateToPriv(SLEEP_STATE);
4653 }
4654 }
4655 }
4656
4657 void IOPMrootDomain::pmStatsRecordEvent(
4658 int eventIndex,
4659 AbsoluteTime timestamp)
4660 {
4661 bool starting = eventIndex & kIOPMStatsEventStartFlag ? true:false;
4662 bool stopping = eventIndex & kIOPMStatsEventStopFlag ? true:false;
4663 uint64_t delta;
4664 uint64_t nsec;
4665
4666 eventIndex &= ~(kIOPMStatsEventStartFlag | kIOPMStatsEventStopFlag);
4667
4668 absolutetime_to_nanoseconds(timestamp, &nsec);
4669
4670 switch (eventIndex) {
4671 case kIOPMStatsHibernateImageWrite:
4672 if (starting)
4673 pmStats.hibWrite.start = nsec;
4674 else if (stopping)
4675 pmStats.hibWrite.stop = nsec;
4676
4677 if (stopping) {
4678 delta = pmStats.hibWrite.stop - pmStats.hibWrite.start;
4679 IOLog("PMStats: Hibernate write took %qd ms\n", delta/1000000ULL);
4680 }
4681 break;
4682 case kIOPMStatsHibernateImageRead:
4683 if (starting)
4684 pmStats.hibRead.start = nsec;
4685 else if (stopping)
4686 pmStats.hibRead.stop = nsec;
4687
4688 if (stopping) {
4689 delta = pmStats.hibRead.stop - pmStats.hibRead.start;
4690 IOLog("PMStats: Hibernate read took %qd ms\n", delta/1000000ULL);
4691 }
4692 break;
4693 }
4694 }
4695
4696 /*
4697 * Appends a record of the application response to
4698 * IOPMrootDomain::pmStatsAppResponses
4699 */
4700 void IOPMrootDomain::pmStatsRecordApplicationResponse(
4701 const OSSymbol *response,
4702 const char *name,
4703 int messageType,
4704 uint32_t delay_ms,
4705 int app_pid)
4706 {
4707 OSDictionary *responseDescription = NULL;
4708 OSNumber *delayNum = NULL;
4709 OSNumber *pidNum = NULL;
4710 OSNumber *msgNum = NULL;
4711 const OSSymbol *appname;
4712 const OSSymbol *entryName;
4713 OSObject *entryType;
4714 int i;
4715
4716 if (!pmStatsAppResponses || pmStatsAppResponses->getCount() > 50)
4717 return;
4718
4719 i = 0;
4720 while ((responseDescription = (OSDictionary *) pmStatsAppResponses->getObject(i++)))
4721 {
4722 entryType = responseDescription->getObject(_statsResponseTypeKey);
4723 entryName = (OSSymbol *) responseDescription->getObject(_statsNameKey);
4724 if (entryName && (entryType == response) && entryName->isEqualTo(name))
4725 {
4726 OSNumber * entryValue;
4727 entryValue = (OSNumber *) responseDescription->getObject(_statsTimeMSKey);
4728 if (entryValue && (entryValue->unsigned32BitValue() < delay_ms))
4729 entryValue->setValue(delay_ms);
4730 return;
4731 }
4732 }
4733
4734 responseDescription = OSDictionary::withCapacity(5);
4735 if (responseDescription)
4736 {
4737 if (response) {
4738 responseDescription->setObject(_statsResponseTypeKey, response);
4739 }
4740
4741 if (messageType != 0) {
4742 msgNum = OSNumber::withNumber(messageType, 32);
4743 if (msgNum) {
4744 responseDescription->setObject(_statsMessageTypeKey, msgNum);
4745 msgNum->release();
4746 }
4747 }
4748
4749 if (name && (strlen(name) > 0))
4750 {
4751 appname = OSSymbol::withCString(name);
4752 if (appname) {
4753 responseDescription->setObject(_statsNameKey, appname);
4754 appname->release();
4755 }
4756 }
4757
4758 if (app_pid != -1) {
4759 pidNum = OSNumber::withNumber(app_pid, 32);
4760 if (pidNum) {
4761 responseDescription->setObject(_statsPIDKey, pidNum);
4762 pidNum->release();
4763 }
4764 }
4765
4766 delayNum = OSNumber::withNumber(delay_ms, 32);
4767 if (delayNum) {
4768 responseDescription->setObject(_statsTimeMSKey, delayNum);
4769 delayNum->release();
4770 }
4771
4772 if (pmStatsAppResponses) {
4773 pmStatsAppResponses->setObject(responseDescription);
4774 }
4775
4776 responseDescription->release();
4777 }
4778 return;
4779 }
4780
4781
4782 //******************************************************************************
4783 // TracePoint support
4784 //
4785 //******************************************************************************
4786
4787 #define kIOPMRegisterNVRAMTracePointHandlerKey \
4788 "IOPMRegisterNVRAMTracePointHandler"
4789
4790 IOReturn IOPMrootDomain::callPlatformFunction(
4791 const OSSymbol * functionName,
4792 bool waitForFunction,
4793 void * param1, void * param2,
4794 void * param3, void * param4 )
4795 {
4796 if (pmTracer && functionName &&
4797 functionName->isEqualTo(kIOPMRegisterNVRAMTracePointHandlerKey) &&
4798 !pmTracer->tracePointHandler && !pmTracer->tracePointTarget)
4799 {
4800 uint32_t tracePointPhases, tracePointPCI;
4801 uint64_t statusCode;
4802
4803 pmTracer->tracePointHandler = (IOPMTracePointHandler) param1;
4804 pmTracer->tracePointTarget = (void *) param2;
4805 tracePointPCI = (uint32_t)(uintptr_t) param3;
4806 tracePointPhases = (uint32_t)(uintptr_t) param4;
4807 statusCode = (((uint64_t)tracePointPCI) << 32) | tracePointPhases;
4808 if ((tracePointPhases >> 24) != kIOPMTracePointSystemUp)
4809 {
4810 LOG("Sleep failure code 0x%08x 0x%08x\n",
4811 tracePointPCI, tracePointPhases);
4812 }
4813 setProperty(kIOPMSleepWakeFailureCodeKey, statusCode, 64);
4814 pmTracer->tracePointHandler( pmTracer->tracePointTarget, 0, 0 );
4815
4816 return kIOReturnSuccess;
4817 }
4818
4819 return super::callPlatformFunction(
4820 functionName, waitForFunction, param1, param2, param3, param4);
4821 }
4822
4823 void IOPMrootDomain::tracePoint( uint8_t point )
4824 {
4825 pmTracer->tracePoint(point);
4826 }
4827
4828 //******************************************************************************
4829 // PMTraceWorker Class
4830 //
4831 //******************************************************************************
4832
4833 #undef super
4834 #define super OSObject
4835 OSDefineMetaClassAndStructors(PMTraceWorker, OSObject)
4836
4837 #define kPMBestGuessPCIDevicesCount 25
4838 #define kPMMaxRTCBitfieldSize 32
4839
4840 PMTraceWorker *PMTraceWorker::tracer(IOPMrootDomain *owner)
4841 {
4842 PMTraceWorker *me;
4843
4844 me = OSTypeAlloc( PMTraceWorker );
4845 if (!me || !me->init())
4846 {
4847 return NULL;
4848 }
4849
4850 DLOG("PMTraceWorker %p\n", me);
4851
4852 // Note that we cannot instantiate the PCI device -> bit mappings here, since
4853 // the IODeviceTree has not yet been created by IOPlatformExpert. We create
4854 // this dictionary lazily.
4855 me->owner = owner;
4856 me->pciDeviceBitMappings = NULL;
4857 me->pciMappingLock = IOLockAlloc();
4858 me->tracePhase = kIOPMTracePointSystemUp;
4859 me->loginWindowPhase = 0;
4860 me->pciBusyBitMask = 0;
4861 return me;
4862 }
4863
4864 void PMTraceWorker::RTC_TRACE(void)
4865 {
4866 if (tracePointHandler && tracePointTarget)
4867 {
4868 uint32_t wordA;
4869
4870 wordA = tracePhase; // destined for bits 24-31
4871 wordA <<= 8;
4872 wordA |= loginWindowPhase; // destined for bits 16-23
4873 wordA <<= 16;
4874
4875 tracePointHandler( tracePointTarget, pciBusyBitMask, wordA );
4876 DLOG("RTC_TRACE wrote 0x%08x 0x%08x\n", pciBusyBitMask, wordA);
4877 }
4878 }
4879
4880 int PMTraceWorker::recordTopLevelPCIDevice(IOService * pciDevice)
4881 {
4882 const OSSymbol * deviceName;
4883 int index = -1;
4884
4885 IOLockLock(pciMappingLock);
4886
4887 if (!pciDeviceBitMappings)
4888 {
4889 pciDeviceBitMappings = OSArray::withCapacity(kPMBestGuessPCIDevicesCount);
4890 if (!pciDeviceBitMappings)
4891 goto exit;
4892 }
4893
4894 // Check for bitmask overflow.
4895 if (pciDeviceBitMappings->getCount() >= kPMMaxRTCBitfieldSize)
4896 goto exit;
4897
4898 if ((deviceName = pciDevice->copyName()) &&
4899 (pciDeviceBitMappings->getNextIndexOfObject(deviceName, 0) == (unsigned int)-1) &&
4900 pciDeviceBitMappings->setObject(deviceName))
4901 {
4902 index = pciDeviceBitMappings->getCount() - 1;
4903 DLOG("PMTrace PCI array: set object %s => %d\n",
4904 deviceName->getCStringNoCopy(), index);
4905 }
4906 if (deviceName)
4907 deviceName->release();
4908 if (!addedToRegistry && (index >= 0))
4909 addedToRegistry = owner->setProperty("PCITopLevel", this);
4910
4911 exit:
4912 IOLockUnlock(pciMappingLock);
4913 return index;
4914 }
4915
4916 bool PMTraceWorker::serialize(OSSerialize *s) const
4917 {
4918 bool ok = false;
4919 if (pciDeviceBitMappings)
4920 {
4921 IOLockLock(pciMappingLock);
4922 ok = pciDeviceBitMappings->serialize(s);
4923 IOLockUnlock(pciMappingLock);
4924 }
4925 return ok;
4926 }
4927
4928 void PMTraceWorker::tracePoint(uint8_t phase)
4929 {
4930 tracePhase = phase;
4931
4932 DLOG("IOPMrootDomain: trace point 0x%02x\n", tracePhase);
4933 RTC_TRACE();
4934 }
4935
4936 void PMTraceWorker::traceLoginWindowPhase(uint8_t phase)
4937 {
4938 loginWindowPhase = phase;
4939
4940 DLOG("IOPMrootDomain: loginwindow tracepoint 0x%02x\n", loginWindowPhase);
4941 RTC_TRACE();
4942 }
4943
4944 void PMTraceWorker::tracePCIPowerChange(
4945 change_t type, IOService *service, uint32_t changeFlags, uint32_t bitNum)
4946 {
4947 uint32_t bitMask;
4948 uint32_t expectedFlag;
4949
4950 // Ignore PCI changes outside of system sleep/wake.
4951 if ((kIOPMTracePointSystemSleepDriversPhase != tracePhase) &&
4952 (kIOPMTracePointSystemWakeDriversPhase != tracePhase))
4953 return;
4954
4955 // Only record the WillChange transition when going to sleep,
4956 // and the DidChange on the way up.
4957 changeFlags &= (kIOPMDomainWillChange | kIOPMDomainDidChange);
4958 expectedFlag = (kIOPMTracePointSystemSleepDriversPhase == tracePhase) ?
4959 kIOPMDomainWillChange : kIOPMDomainDidChange;
4960 if (changeFlags != expectedFlag)
4961 return;
4962
4963 // Mark this device off in our bitfield
4964 if (bitNum < kPMMaxRTCBitfieldSize)
4965 {
4966 bitMask = (1 << bitNum);
4967
4968 if (kPowerChangeStart == type)
4969 {
4970 pciBusyBitMask |= bitMask;
4971 DLOG("PMTrace: Device %s started - bit %2d mask 0x%08x => 0x%08x\n",
4972 service->getName(), bitNum, bitMask, pciBusyBitMask);
4973 }
4974 else
4975 {
4976 pciBusyBitMask &= ~bitMask;
4977 DLOG("PMTrace: Device %s finished - bit %2d mask 0x%08x => 0x%08x\n",
4978 service->getName(), bitNum, bitMask, pciBusyBitMask);
4979 }
4980
4981 RTC_TRACE();
4982 }
4983 }
4984
4985
4986 //******************************************************************************
4987 // PMHaltWorker Class
4988 //
4989 //******************************************************************************
4990
4991 static unsigned int gPMHaltBusyCount;
4992 static unsigned int gPMHaltIdleCount;
4993 static int gPMHaltDepth;
4994 static unsigned long gPMHaltEvent;
4995 static IOLock * gPMHaltLock = 0;
4996 static OSArray * gPMHaltArray = 0;
4997 static const OSSymbol * gPMHaltClientAcknowledgeKey = 0;
4998
4999 PMHaltWorker * PMHaltWorker::worker( void )
5000 {
5001 PMHaltWorker * me;
5002 IOThread thread;
5003
5004 do {
5005 me = OSTypeAlloc( PMHaltWorker );
5006 if (!me || !me->init())
5007 break;
5008
5009 me->lock = IOLockAlloc();
5010 if (!me->lock)
5011 break;
5012
5013 DLOG("PMHaltWorker %p\n", me);
5014 me->retain(); // thread holds extra retain
5015 if (KERN_SUCCESS != kernel_thread_start(&PMHaltWorker::main, (void *) me, &thread))
5016 {
5017 me->release();
5018 break;
5019 }
5020 thread_deallocate(thread);
5021 return me;
5022
5023 } while (false);
5024
5025 if (me) me->release();
5026 return 0;
5027 }
5028
5029 void PMHaltWorker::free( void )
5030 {
5031 DLOG("PMHaltWorker free %p\n", this);
5032 if (lock)
5033 {
5034 IOLockFree(lock);
5035 lock = 0;
5036 }
5037 return OSObject::free();
5038 }
5039
5040 void PMHaltWorker::main( void * arg, wait_result_t waitResult )
5041 {
5042 PMHaltWorker * me = (PMHaltWorker *) arg;
5043
5044 IOLockLock( gPMHaltLock );
5045 gPMHaltBusyCount++;
5046 me->depth = gPMHaltDepth;
5047 IOLockUnlock( gPMHaltLock );
5048
5049 while (me->depth >= 0)
5050 {
5051 PMHaltWorker::work( me );
5052
5053 IOLockLock( gPMHaltLock );
5054 if (++gPMHaltIdleCount >= gPMHaltBusyCount)
5055 {
5056 // This is the last thread to finish work on this level,
5057 // inform everyone to start working on next lower level.
5058 gPMHaltDepth--;
5059 me->depth = gPMHaltDepth;
5060 gPMHaltIdleCount = 0;
5061 thread_wakeup((event_t) &gPMHaltIdleCount);
5062 }
5063 else
5064 {
5065 // One or more threads are still working on this level,
5066 // this thread must wait.
5067 me->depth = gPMHaltDepth - 1;
5068 do {
5069 IOLockSleep(gPMHaltLock, &gPMHaltIdleCount, THREAD_UNINT);
5070 } while (me->depth != gPMHaltDepth);
5071 }
5072 IOLockUnlock( gPMHaltLock );
5073 }
5074
5075 // No more work to do, terminate thread
5076 DLOG("All done for worker: %p (visits = %u)\n", me, me->visits);
5077 thread_wakeup( &gPMHaltDepth );
5078 me->release();
5079 }
5080
5081 void PMHaltWorker::work( PMHaltWorker * me )
5082 {
5083 IOService * service;
5084 OSSet * inner;
5085 AbsoluteTime startTime;
5086 UInt32 deltaTime;
5087 bool timeout;
5088
5089 while (true)
5090 {
5091 service = 0;
5092 timeout = false;
5093
5094 // Claim an unit of work from the shared pool
5095 IOLockLock( gPMHaltLock );
5096 inner = (OSSet *)gPMHaltArray->getObject(me->depth);
5097 if (inner)
5098 {
5099 service = (IOService *)inner->getAnyObject();
5100 if (service)
5101 {
5102 service->retain();
5103 inner->removeObject(service);
5104 }
5105 }
5106 IOLockUnlock( gPMHaltLock );
5107 if (!service)
5108 break; // no more work at this depth
5109
5110 clock_get_uptime(&startTime);
5111
5112 if (!service->isInactive() &&
5113 service->setProperty(gPMHaltClientAcknowledgeKey, me))
5114 {
5115 IOLockLock(me->lock);
5116 me->startTime = startTime;
5117 me->service = service;
5118 me->timeout = false;
5119 IOLockUnlock(me->lock);
5120
5121 service->systemWillShutdown( gPMHaltEvent );
5122
5123 // Wait for driver acknowledgement
5124 IOLockLock(me->lock);
5125 while (service->getProperty(gPMHaltClientAcknowledgeKey))
5126 {
5127 IOLockSleep(me->lock, me, THREAD_UNINT);
5128 }
5129 me->service = 0;
5130 timeout = me->timeout;
5131 IOLockUnlock(me->lock);
5132 }
5133
5134 deltaTime = computeDeltaTimeMS(&startTime);
5135 if ((deltaTime > kPMHaltTimeoutMS) || timeout ||
5136 (gIOKitDebug & (kIOLogDebugPower | kIOLogPMRootDomain)))
5137 {
5138 KLOG("%s driver %s (%p) took %u ms\n",
5139 (gPMHaltEvent == kIOMessageSystemWillPowerOff) ?
5140 "PowerOff" : "Restart",
5141 service->getName(), service,
5142 (uint32_t) deltaTime );
5143 }
5144
5145 service->release();
5146 me->visits++;
5147 }
5148 }
5149
5150 void PMHaltWorker::checkTimeout( PMHaltWorker * me, AbsoluteTime * now )
5151 {
5152 UInt64 nano;
5153 AbsoluteTime startTime;
5154 AbsoluteTime endTime;
5155
5156 endTime = *now;
5157
5158 IOLockLock(me->lock);
5159 if (me->service && !me->timeout)
5160 {
5161 startTime = me->startTime;
5162 nano = 0;
5163 if (CMP_ABSOLUTETIME(&endTime, &startTime) > 0)
5164 {
5165 SUB_ABSOLUTETIME(&endTime, &startTime);
5166 absolutetime_to_nanoseconds(endTime, &nano);
5167 }
5168 if (nano > 3000000000ULL)
5169 {
5170 me->timeout = true;
5171 LOG("%s still waiting on %s\n",
5172 (gPMHaltEvent == kIOMessageSystemWillPowerOff) ?
5173 "PowerOff" : "Restart",
5174 me->service->getName());
5175 }
5176 }
5177 IOLockUnlock(me->lock);
5178 }
5179
5180
5181 //******************************************************************************
5182 // acknowledgeSystemWillShutdown
5183 //
5184 // Acknowledgement from drivers that they have prepared for shutdown/restart.
5185 //******************************************************************************
5186
5187 void IOPMrootDomain::acknowledgeSystemWillShutdown( IOService * from )
5188 {
5189 PMHaltWorker * worker;
5190 OSObject * prop;
5191
5192 if (!from)
5193 return;
5194
5195 //DLOG("%s acknowledged\n", from->getName());
5196 prop = from->copyProperty( gPMHaltClientAcknowledgeKey );
5197 if (prop)
5198 {
5199 worker = (PMHaltWorker *) prop;
5200 IOLockLock(worker->lock);
5201 from->removeProperty( gPMHaltClientAcknowledgeKey );
5202 thread_wakeup((event_t) worker);
5203 IOLockUnlock(worker->lock);
5204 worker->release();
5205 }
5206 else
5207 {
5208 DLOG("%s acknowledged without worker property\n",
5209 from->getName());
5210 }
5211 }
5212
5213
5214 //******************************************************************************
5215 // notifySystemShutdown
5216 //
5217 // Notify all objects in PM tree that system will shutdown or restart
5218 //******************************************************************************
5219
5220 static void
5221 notifySystemShutdown( IOService * root, unsigned long event )
5222 {
5223 #define PLACEHOLDER ((OSSet *)gPMHaltArray)
5224 IORegistryIterator * iter;
5225 IORegistryEntry * entry;
5226 IOService * node;
5227 OSSet * inner;
5228 PMHaltWorker * workers[kPMHaltMaxWorkers];
5229 AbsoluteTime deadline;
5230 unsigned int totalNodes = 0;
5231 unsigned int depth;
5232 unsigned int rootDepth;
5233 unsigned int numWorkers;
5234 unsigned int count;
5235 int waitResult;
5236 void * baseFunc;
5237 bool ok;
5238
5239 DLOG("%s event = %lx\n", __FUNCTION__, event);
5240
5241 baseFunc = OSMemberFunctionCast(void *, root, &IOService::systemWillShutdown);
5242
5243 // Iterate the entire PM tree starting from root
5244
5245 rootDepth = root->getDepth( gIOPowerPlane );
5246 if (!rootDepth) goto done;
5247
5248 // debug - for repeated test runs
5249 while (PMHaltWorker::metaClass->getInstanceCount())
5250 IOSleep(1);
5251
5252 if (!gPMHaltArray)
5253 {
5254 gPMHaltArray = OSArray::withCapacity(40);
5255 if (!gPMHaltArray) goto done;
5256 }
5257 else // debug
5258 gPMHaltArray->flushCollection();
5259
5260 if (!gPMHaltLock)
5261 {
5262 gPMHaltLock = IOLockAlloc();
5263 if (!gPMHaltLock) goto done;
5264 }
5265
5266 if (!gPMHaltClientAcknowledgeKey)
5267 {
5268 gPMHaltClientAcknowledgeKey =
5269 OSSymbol::withCStringNoCopy("PMShutdown");
5270 if (!gPMHaltClientAcknowledgeKey) goto done;
5271 }
5272
5273 gPMHaltEvent = event;
5274
5275 // Depth-first walk of PM plane
5276
5277 iter = IORegistryIterator::iterateOver(
5278 root, gIOPowerPlane, kIORegistryIterateRecursively);
5279
5280 if (iter)
5281 {
5282 while ((entry = iter->getNextObject()))
5283 {
5284 node = OSDynamicCast(IOService, entry);
5285 if (!node)
5286 continue;
5287
5288 if (baseFunc ==
5289 OSMemberFunctionCast(void *, node, &IOService::systemWillShutdown))
5290 continue;
5291
5292 depth = node->getDepth( gIOPowerPlane );
5293 if (depth <= rootDepth)
5294 continue;
5295
5296 ok = false;
5297
5298 // adjust to zero based depth
5299 depth -= (rootDepth + 1);
5300
5301 // gPMHaltArray is an array of containers, each container
5302 // refers to nodes with the same depth.
5303
5304 count = gPMHaltArray->getCount();
5305 while (depth >= count)
5306 {
5307 // expand array and insert placeholders
5308 gPMHaltArray->setObject(PLACEHOLDER);
5309 count++;
5310 }
5311 count = gPMHaltArray->getCount();
5312 if (depth < count)
5313 {
5314 inner = (OSSet *)gPMHaltArray->getObject(depth);
5315 if (inner == PLACEHOLDER)
5316 {
5317 inner = OSSet::withCapacity(40);
5318 if (inner)
5319 {
5320 gPMHaltArray->replaceObject(depth, inner);
5321 inner->release();
5322 }
5323 }
5324
5325 // PM nodes that appear more than once in the tree will have
5326 // the same depth, OSSet will refuse to add the node twice.
5327 if (inner)
5328 ok = inner->setObject(node);
5329 }
5330 if (!ok)
5331 DLOG("Skipped PM node %s\n", node->getName());
5332 }
5333 iter->release();
5334 }
5335
5336 // debug only
5337 for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i)); i++)
5338 {
5339 count = 0;
5340 if (inner != PLACEHOLDER)
5341 count = inner->getCount();
5342 DLOG("Nodes at depth %u = %u\n", i, count);
5343 }
5344
5345 // strip placeholders (not all depths are populated)
5346 numWorkers = 0;
5347 for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i)); )
5348 {
5349 if (inner == PLACEHOLDER)
5350 {
5351 gPMHaltArray->removeObject(i);
5352 continue;
5353 }
5354 count = inner->getCount();
5355 if (count > numWorkers)
5356 numWorkers = count;
5357 totalNodes += count;
5358 i++;
5359 }
5360
5361 if (gPMHaltArray->getCount() == 0 || !numWorkers)
5362 goto done;
5363
5364 gPMHaltBusyCount = 0;
5365 gPMHaltIdleCount = 0;
5366 gPMHaltDepth = gPMHaltArray->getCount() - 1;
5367
5368 // Create multiple workers (and threads)
5369
5370 if (numWorkers > kPMHaltMaxWorkers)
5371 numWorkers = kPMHaltMaxWorkers;
5372
5373 DLOG("PM nodes = %u, maxDepth = %u, workers = %u\n",
5374 totalNodes, gPMHaltArray->getCount(), numWorkers);
5375
5376 for (unsigned int i = 0; i < numWorkers; i++)
5377 workers[i] = PMHaltWorker::worker();
5378
5379 // Wait for workers to exhaust all available work
5380
5381 IOLockLock(gPMHaltLock);
5382 while (gPMHaltDepth >= 0)
5383 {
5384 clock_interval_to_deadline(1000, kMillisecondScale, &deadline);
5385
5386 waitResult = IOLockSleepDeadline(
5387 gPMHaltLock, &gPMHaltDepth, deadline, THREAD_UNINT);
5388 if (THREAD_TIMED_OUT == waitResult)
5389 {
5390 AbsoluteTime now;
5391 clock_get_uptime(&now);
5392
5393 IOLockUnlock(gPMHaltLock);
5394 for (unsigned int i = 0 ; i < numWorkers; i++)
5395 {
5396 if (workers[i])
5397 PMHaltWorker::checkTimeout(workers[i], &now);
5398 }
5399 IOLockLock(gPMHaltLock);
5400 }
5401 }
5402 IOLockUnlock(gPMHaltLock);
5403
5404 // Release all workers
5405
5406 for (unsigned int i = 0; i < numWorkers; i++)
5407 {
5408 if (workers[i])
5409 workers[i]->release();
5410 // worker also retained by it's own thread
5411 }
5412
5413 done:
5414 DLOG("%s done\n", __FUNCTION__);
5415 return;
5416 }
5417
5418 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
5419
5420 IOPMDriverAssertionID IOPMrootDomain::createPMAssertion(
5421 IOPMDriverAssertionType whichAssertionBits,
5422 IOPMDriverAssertionLevel assertionLevel,
5423 IOService *ownerService,
5424 const char *ownerDescription)
5425 {
5426 IOReturn ret;
5427 IOPMDriverAssertionID newAssertion;
5428
5429 if (!pmAssertions)
5430 return 0;
5431
5432 ret = pmAssertions->createAssertion(whichAssertionBits, assertionLevel, ownerService, ownerDescription, &newAssertion);
5433
5434 if (kIOReturnSuccess == ret)
5435 return newAssertion;
5436 else
5437 return 0;
5438 }
5439
5440 IOReturn IOPMrootDomain::releasePMAssertion(IOPMDriverAssertionID releaseAssertion)
5441 {
5442 if (!pmAssertions)
5443 return kIOReturnInternalError;
5444
5445 return pmAssertions->releaseAssertion(releaseAssertion);
5446 }
5447
5448 IOReturn IOPMrootDomain::setPMAssertionLevel(
5449 IOPMDriverAssertionID assertionID,
5450 IOPMDriverAssertionLevel assertionLevel)
5451 {
5452 return pmAssertions->setAssertionLevel(assertionID, assertionLevel);
5453 }
5454
5455 IOPMDriverAssertionLevel IOPMrootDomain::getPMAssertionLevel(IOPMDriverAssertionType whichAssertion)
5456 {
5457 IOPMDriverAssertionType sysLevels;
5458
5459 if (!pmAssertions || whichAssertion == 0)
5460 return kIOPMDriverAssertionLevelOff;
5461
5462 sysLevels = pmAssertions->getActivatedAssertions();
5463
5464 // Check that every bit set in argument 'whichAssertion' is asserted
5465 // in the aggregate bits.
5466 if ((sysLevels & whichAssertion) == whichAssertion)
5467 return kIOPMDriverAssertionLevelOn;
5468 else
5469 return kIOPMDriverAssertionLevelOff;
5470 }
5471
5472 IOReturn IOPMrootDomain::setPMAssertionUserLevels(IOPMDriverAssertionType inLevels)
5473 {
5474 if (!pmAssertions)
5475 return kIOReturnNotFound;
5476
5477 return pmAssertions->setUserAssertionLevels(inLevels);
5478 }
5479
5480 bool IOPMrootDomain::serializeProperties( OSSerialize * s ) const
5481 {
5482 if (pmAssertions)
5483 {
5484 pmAssertions->publishProperties();
5485 }
5486 return( IOService::serializeProperties(s) );
5487 }
5488
5489 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
5490
5491
5492 #undef super
5493 #define super OSObject
5494 OSDefineMetaClassAndFinalStructors(PMSettingObject, OSObject)
5495
5496 void PMSettingObject::setPMSetting(const OSSymbol *type, OSObject *obj)
5497 {
5498 (*func)(target, type, obj, refcon);
5499 }
5500
5501 /*
5502 * Static constructor/initializer for PMSettingObject
5503 */
5504 PMSettingObject *PMSettingObject::pmSettingObject(
5505 IOPMrootDomain *parent_arg,
5506 IOPMSettingControllerCallback handler_arg,
5507 OSObject *target_arg,
5508 uintptr_t refcon_arg,
5509 uint32_t supportedPowerSources,
5510 const OSSymbol * settings[])
5511 {
5512 uint32_t objCount = 0;
5513 PMSettingObject *pmso;
5514
5515 if( !parent_arg || !handler_arg || !settings ) return NULL;
5516
5517 // count OSSymbol entries in NULL terminated settings array
5518 while( settings[objCount] ) {
5519 objCount++;
5520 }
5521 if(0 == objCount) return NULL;
5522
5523 pmso = new PMSettingObject;
5524 if(!pmso || !pmso->init()) return NULL;
5525
5526 pmso->parent = parent_arg;
5527 pmso->func = handler_arg;
5528 pmso->target = target_arg;
5529 pmso->refcon = refcon_arg;
5530 pmso->releaseAtCount = objCount + 1; // release when it has count+1 retains
5531
5532 pmso->publishedFeatureID = (uint32_t *)IOMalloc(sizeof(uint32_t)*objCount);
5533 if(pmso->publishedFeatureID) {
5534 for(unsigned int i=0; i<objCount; i++) {
5535 // Since there is now at least one listener to this setting, publish
5536 // PM root domain support for it.
5537 parent_arg->publishFeature( settings[i]->getCStringNoCopy(),
5538 supportedPowerSources, &pmso->publishedFeatureID[i] );
5539 }
5540 }
5541
5542 return pmso;
5543 }
5544
5545 void PMSettingObject::free(void)
5546 {
5547 OSCollectionIterator *settings_iter;
5548 OSSymbol *sym;
5549 OSArray *arr;
5550 int arr_idx;
5551 int i;
5552 int objCount = releaseAtCount - 1;
5553
5554 if(publishedFeatureID) {
5555 for(i=0; i<objCount; i++) {
5556 if(0 != publishedFeatureID[i]) {
5557 parent->removePublishedFeature( publishedFeatureID[i] );
5558 }
5559 }
5560
5561 IOFree(publishedFeatureID, sizeof(uint32_t) * objCount);
5562 }
5563
5564 IORecursiveLockLock(parent->settingsCtrlLock);
5565
5566 // Search each PM settings array in the kernel.
5567 settings_iter = OSCollectionIterator::withCollection(parent->settingsCallbacks);
5568 if(settings_iter)
5569 {
5570 while(( sym = OSDynamicCast(OSSymbol, settings_iter->getNextObject()) ))
5571 {
5572 arr = (OSArray *)parent->settingsCallbacks->getObject(sym);
5573 arr_idx = arr->getNextIndexOfObject(this, 0);
5574 if(-1 != arr_idx) {
5575 // 'this' was found in the array; remove it
5576 arr->removeObject(arr_idx);
5577 }
5578 }
5579
5580 settings_iter->release();
5581 }
5582
5583 IORecursiveLockUnlock(parent->settingsCtrlLock);
5584
5585 super::free();
5586 }
5587
5588 void PMSettingObject::taggedRelease(const void *tag, const int when) const
5589 {
5590 // We have n+1 retains - 1 per array that this PMSettingObject is a member
5591 // of, and 1 retain to ourself. When we get a release with n+1 retains
5592 // remaining, we go ahead and free ourselves, cleaning up array pointers
5593 // in free();
5594
5595 super::taggedRelease(tag, releaseAtCount);
5596 }
5597
5598 // MARK: -
5599 // MARK: PMAssertionsTracker
5600
5601 //*********************************************************************************
5602 //*********************************************************************************
5603 //*********************************************************************************
5604 // class PMAssertionsTracker Implementation
5605
5606 #define kAssertUniqueIDStart 500
5607
5608 PMAssertionsTracker *PMAssertionsTracker::pmAssertionsTracker( IOPMrootDomain *rootDomain )
5609 {
5610 PMAssertionsTracker *myself;
5611
5612 myself = new PMAssertionsTracker;
5613
5614 if (myself) {
5615 myself->init();
5616 myself->owner = rootDomain;
5617 myself->issuingUniqueID = kAssertUniqueIDStart;
5618 myself->assertionsArray = OSArray::withCapacity(5);
5619 myself->assertionsKernel = 0;
5620 myself->assertionsUser = 0;
5621 myself->assertionsCombined = 0;
5622 myself->assertionsArrayLock = IOLockAlloc();
5623 myself->tabulateProducerCount = myself->tabulateConsumerCount = 0;
5624
5625 if (!myself->assertionsArray || !myself->assertionsArrayLock)
5626 myself = NULL;
5627 }
5628
5629 return myself;
5630 }
5631
5632 /* tabulate
5633 * - Update assertionsKernel to reflect the state of all
5634 * assertions in the kernel.
5635 * - Update assertionsCombined to reflect both kernel & user space.
5636 */
5637 void PMAssertionsTracker::tabulate(void)
5638 {
5639 int i;
5640 int count;
5641 PMAssertStruct *_a = NULL;
5642 OSData *_d = NULL;
5643
5644 IOPMDriverAssertionType oldKernel = assertionsKernel;
5645 IOPMDriverAssertionType oldCombined = assertionsCombined;
5646
5647 ASSERT_GATED();
5648
5649 assertionsKernel = 0;
5650 assertionsCombined = 0;
5651
5652 if (!assertionsArray)
5653 return;
5654
5655 if ((count = assertionsArray->getCount()))
5656 {
5657 for (i=0; i<count; i++)
5658 {
5659 _d = OSDynamicCast(OSData, assertionsArray->getObject(i));
5660 if (_d)
5661 {
5662 _a = (PMAssertStruct *)_d->getBytesNoCopy();
5663 if (_a && (kIOPMDriverAssertionLevelOn == _a->level))
5664 assertionsKernel |= _a->assertionBits;
5665 }
5666 }
5667 }
5668
5669 tabulateProducerCount++;
5670 assertionsCombined = assertionsKernel | assertionsUser;
5671
5672 if ((assertionsKernel != oldKernel) ||
5673 (assertionsCombined != oldCombined))
5674 {
5675 owner->messageClients(kIOPMMessageDriverAssertionsChanged);
5676 }
5677 }
5678
5679 void PMAssertionsTracker::publishProperties( void )
5680 {
5681 OSArray *assertionsSummary = NULL;
5682
5683 if (tabulateConsumerCount != tabulateProducerCount)
5684 {
5685 IOLockLock(assertionsArrayLock);
5686
5687 tabulateConsumerCount = tabulateProducerCount;
5688
5689 /* Publish the IOPMrootDomain property "DriverPMAssertionsDetailed"
5690 */
5691 assertionsSummary = copyAssertionsArray();
5692 if (assertionsSummary)
5693 {
5694 owner->setProperty(kIOPMAssertionsDriverDetailedKey, assertionsSummary);
5695 assertionsSummary->release();
5696 }
5697 else
5698 {
5699 owner->removeProperty(kIOPMAssertionsDriverDetailedKey);
5700 }
5701
5702 /* Publish the IOPMrootDomain property "DriverPMAssertions"
5703 */
5704 owner->setProperty(kIOPMAssertionsDriverKey, assertionsKernel, 64);
5705
5706 IOLockUnlock(assertionsArrayLock);
5707 }
5708 }
5709
5710 PMAssertionsTracker::PMAssertStruct *PMAssertionsTracker::detailsForID(IOPMDriverAssertionID _id, int *index)
5711 {
5712 PMAssertStruct *_a = NULL;
5713 OSData *_d = NULL;
5714 int found = -1;
5715 int count = 0;
5716 int i = 0;
5717
5718 if (assertionsArray
5719 && (count = assertionsArray->getCount()))
5720 {
5721 for (i=0; i<count; i++)
5722 {
5723 _d = OSDynamicCast(OSData, assertionsArray->getObject(i));
5724 if (_d)
5725 {
5726 _a = (PMAssertStruct *)_d->getBytesNoCopy();
5727 if (_a && (_id == _a->id)) {
5728 found = i;
5729 break;
5730 }
5731 }
5732 }
5733 }
5734
5735 if (-1 == found) {
5736 return NULL;
5737 } else {
5738 if (index)
5739 *index = found;
5740 return _a;
5741 }
5742 }
5743
5744 /* PMAssertionsTracker::handleCreateAssertion
5745 * Perform assertion work on the PM workloop. Do not call directly.
5746 */
5747 IOReturn PMAssertionsTracker::handleCreateAssertion(OSData *newAssertion)
5748 {
5749 ASSERT_GATED();
5750
5751 if (newAssertion)
5752 {
5753 IOLockLock(assertionsArrayLock);
5754 assertionsArray->setObject(newAssertion);
5755 IOLockUnlock(assertionsArrayLock);
5756 newAssertion->release();
5757
5758 tabulate();
5759 }
5760 return kIOReturnSuccess;
5761 }
5762
5763 /* PMAssertionsTracker::createAssertion
5764 * createAssertion allocates memory for a new PM assertion, and affects system behavior, if
5765 * appropiate.
5766 */
5767 IOReturn PMAssertionsTracker::createAssertion(
5768 IOPMDriverAssertionType which,
5769 IOPMDriverAssertionLevel level,
5770 IOService *serviceID,
5771 const char *whoItIs,
5772 IOPMDriverAssertionID *outID)
5773 {
5774 OSData *dataStore = NULL;
5775 PMAssertStruct track;
5776
5777 // Warning: trillions and trillions of created assertions may overflow the unique ID.
5778 #ifdef __ppc__
5779 track.id = issuingUniqueID++; // FIXME: need OSIncrementAtomic64() for ppc
5780 #else
5781 track.id = OSIncrementAtomic64((SInt64*) &issuingUniqueID);
5782 #endif
5783 track.level = level;
5784 track.assertionBits = which;
5785 track.ownerString = whoItIs ? OSSymbol::withCString(whoItIs) : 0;
5786 track.ownerService = serviceID;
5787 track.modifiedTime = 0;
5788 pmEventTimeStamp(&track.createdTime);
5789
5790 dataStore = OSData::withBytes(&track, sizeof(PMAssertStruct));
5791 if (!dataStore)
5792 {
5793 if (track.ownerString)
5794 track.ownerString->release();
5795 return kIOReturnNoMemory;
5796 }
5797
5798 *outID = track.id;
5799
5800 if (owner && owner->pmPowerStateQueue) {
5801 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionCreate, (void *)dataStore);
5802 }
5803
5804 return kIOReturnSuccess;
5805 }
5806
5807 /* PMAssertionsTracker::handleReleaseAssertion
5808 * Runs in PM workloop. Do not call directly.
5809 */
5810 IOReturn PMAssertionsTracker::handleReleaseAssertion(
5811 IOPMDriverAssertionID _id)
5812 {
5813 ASSERT_GATED();
5814
5815 int index;
5816 PMAssertStruct *assertStruct = detailsForID(_id, &index);
5817
5818 if (!assertStruct)
5819 return kIOReturnNotFound;
5820
5821 IOLockLock(assertionsArrayLock);
5822 if (assertStruct->ownerString)
5823 assertStruct->ownerString->release();
5824
5825 assertionsArray->removeObject(index);
5826 IOLockUnlock(assertionsArrayLock);
5827
5828 tabulate();
5829 return kIOReturnSuccess;
5830 }
5831
5832 /* PMAssertionsTracker::releaseAssertion
5833 * Releases an assertion and affects system behavior if appropiate.
5834 * Actual work happens on PM workloop.
5835 */
5836 IOReturn PMAssertionsTracker::releaseAssertion(
5837 IOPMDriverAssertionID _id)
5838 {
5839 if (owner && owner->pmPowerStateQueue) {
5840 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionRelease, 0, _id);
5841 }
5842 return kIOReturnSuccess;
5843 }
5844
5845 /* PMAssertionsTracker::handleSetAssertionLevel
5846 * Runs in PM workloop. Do not call directly.
5847 */
5848 IOReturn PMAssertionsTracker::handleSetAssertionLevel(
5849 IOPMDriverAssertionID _id,
5850 IOPMDriverAssertionLevel _level)
5851 {
5852 PMAssertStruct *assertStruct = detailsForID(_id, NULL);
5853
5854 ASSERT_GATED();
5855
5856 if (!assertStruct) {
5857 return kIOReturnNotFound;
5858 }
5859
5860 IOLockLock(assertionsArrayLock);
5861 pmEventTimeStamp(&assertStruct->modifiedTime);
5862 assertStruct->level = _level;
5863 IOLockUnlock(assertionsArrayLock);
5864
5865 tabulate();
5866 return kIOReturnSuccess;
5867 }
5868
5869 /* PMAssertionsTracker::setAssertionLevel
5870 */
5871 IOReturn PMAssertionsTracker::setAssertionLevel(
5872 IOPMDriverAssertionID _id,
5873 IOPMDriverAssertionLevel _level)
5874 {
5875 if (owner && owner->pmPowerStateQueue) {
5876 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionSetLevel,
5877 (void *)_level, _id);
5878 }
5879
5880 return kIOReturnSuccess;
5881 }
5882
5883 IOReturn PMAssertionsTracker::handleSetUserAssertionLevels(void * arg0)
5884 {
5885 IOPMDriverAssertionType new_user_levels = *(IOPMDriverAssertionType *) arg0;
5886
5887 ASSERT_GATED();
5888
5889 if (new_user_levels != assertionsUser)
5890 {
5891 assertionsUser = new_user_levels;
5892 DLOG("assertionsUser 0x%llx\n", assertionsUser);
5893 }
5894
5895 tabulate();
5896 return kIOReturnSuccess;
5897 }
5898
5899 IOReturn PMAssertionsTracker::setUserAssertionLevels(
5900 IOPMDriverAssertionType new_user_levels)
5901 {
5902 if (gIOPMWorkLoop) {
5903 gIOPMWorkLoop->runAction(
5904 OSMemberFunctionCast(
5905 IOWorkLoop::Action,
5906 this,
5907 &PMAssertionsTracker::handleSetUserAssertionLevels),
5908 this,
5909 (void *) &new_user_levels, 0, 0, 0);
5910 }
5911
5912 return kIOReturnSuccess;
5913 }
5914
5915
5916 OSArray *PMAssertionsTracker::copyAssertionsArray(void)
5917 {
5918 int count;
5919 int i;
5920 OSArray *outArray = NULL;
5921
5922 if (!assertionsArray ||
5923 (0 == (count = assertionsArray->getCount())) ||
5924 (NULL == (outArray = OSArray::withCapacity(count))))
5925 {
5926 goto exit;
5927 }
5928
5929 for (i=0; i<count; i++)
5930 {
5931 PMAssertStruct *_a = NULL;
5932 OSData *_d = NULL;
5933 OSDictionary *details = NULL;
5934
5935 _d = OSDynamicCast(OSData, assertionsArray->getObject(i));
5936 if (_d && (_a = (PMAssertStruct *)_d->getBytesNoCopy()))
5937 {
5938 OSNumber *_n = NULL;
5939
5940 details = OSDictionary::withCapacity(7);
5941 if (!details)
5942 continue;
5943
5944 outArray->setObject(details);
5945 details->release();
5946
5947 _n = OSNumber::withNumber(_a->id, 64);
5948 if (_n) {
5949 details->setObject(kIOPMDriverAssertionIDKey, _n);
5950 _n->release();
5951 }
5952 _n = OSNumber::withNumber(_a->createdTime, 64);
5953 if (_n) {
5954 details->setObject(kIOPMDriverAssertionCreatedTimeKey, _n);
5955 _n->release();
5956 }
5957 _n = OSNumber::withNumber(_a->modifiedTime, 64);
5958 if (_n) {
5959 details->setObject(kIOPMDriverAssertionModifiedTimeKey, _n);
5960 _n->release();
5961 }
5962 _n = OSNumber::withNumber((uintptr_t)_a->ownerService, 64);
5963 if (_n) {
5964 details->setObject(kIOPMDriverAssertionOwnerServiceKey, _n);
5965 _n->release();
5966 }
5967 _n = OSNumber::withNumber(_a->level, 64);
5968 if (_n) {
5969 details->setObject(kIOPMDriverAssertionLevelKey, _n);
5970 _n->release();
5971 }
5972 _n = OSNumber::withNumber(_a->assertionBits, 64);
5973 if (_n) {
5974 details->setObject(kIOPMDriverAssertionAssertedKey, _n);
5975 _n->release();
5976 }
5977
5978 if (_a->ownerString) {
5979 details->setObject(kIOPMDriverAssertionOwnerStringKey, _a->ownerString);
5980 }
5981 }
5982 }
5983
5984 exit:
5985 return outArray;
5986 }
5987
5988 IOPMDriverAssertionType PMAssertionsTracker::getActivatedAssertions(void)
5989 {
5990 return assertionsCombined;
5991 }
5992
5993 IOPMDriverAssertionLevel PMAssertionsTracker::getAssertionLevel(
5994 IOPMDriverAssertionType type)
5995 {
5996 if (type && ((type & assertionsKernel) == assertionsKernel))
5997 {
5998 return kIOPMDriverAssertionLevelOn;
5999 } else {
6000 return kIOPMDriverAssertionLevelOff;
6001 }
6002 }
6003
6004 //*********************************************************************************
6005 //*********************************************************************************
6006 //*********************************************************************************
6007
6008 static void pmEventTimeStamp(uint64_t *recordTS)
6009 {
6010 clock_sec_t tsec;
6011 clock_usec_t tusec;
6012
6013 if (!recordTS)
6014 return;
6015
6016 // We assume tsec fits into 32 bits; 32 bits holds enough
6017 // seconds for 136 years since the epoch in 1970.
6018 clock_get_calendar_microtime(&tsec, &tusec);
6019
6020
6021 // Pack the sec & microsec calendar time into a uint64_t, for fun.
6022 *recordTS = 0;
6023 *recordTS |= (uint32_t)tusec;
6024 *recordTS |= ((uint64_t)tsec << 32);
6025
6026 return;
6027 }
6028
6029 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
6030
6031 #undef super
6032 #define super IOService
6033
6034 OSDefineMetaClassAndFinalStructors(IORootParent, IOService)
6035
6036 // This array exactly parallels the state array for the root domain.
6037 // Power state changes initiated by a device can be vetoed by a client of the device, and
6038 // power state changes initiated by the parent of a device cannot be vetoed by a client of the device,
6039 // so when the root domain wants a power state change that cannot be vetoed (e.g. demand sleep), it asks
6040 // its parent to make the change. That is the reason for this complexity.
6041
6042 static IOPMPowerState patriarchPowerStates[NUM_POWER_STATES] =
6043 {
6044 {1,0,0,0,0,0,0,0,0,0,0,0}, // off (not used)
6045 {1,0,RESTART_POWER,0,0,0,0,0,0,0,0,0}, // reset (not used)
6046 {1,0,SLEEP_POWER,0,0,0,0,0,0,0,0,0}, // sleep
6047 {1,0,DOZE_POWER,0,0,0,0,0,0,0,0,0}, // doze
6048 {1,0,ON_POWER,0,0,0,0,0,0,0,0,0}, // running
6049 };
6050
6051 bool IORootParent::start( IOService * nub )
6052 {
6053 mostRecentChange = ON_STATE;
6054 super::start(nub);
6055 attachToParent( getRegistryRoot(), gIOPowerPlane );
6056 PMinit();
6057 registerPowerDriver(this, patriarchPowerStates, NUM_POWER_STATES);
6058 wakeSystem();
6059 powerOverrideOnPriv();
6060 return true;
6061 }
6062
6063 void IORootParent::shutDownSystem( void )
6064 {
6065 }
6066
6067 void IORootParent::restartSystem( void )
6068 {
6069 }
6070
6071 void IORootParent::sleepSystem( void )
6072 {
6073 mostRecentChange = SLEEP_STATE;
6074 changePowerStateToPriv(SLEEP_STATE);
6075 }
6076
6077 void IORootParent::dozeSystem( void )
6078 {
6079 mostRecentChange = DOZE_STATE;
6080 changePowerStateToPriv(DOZE_STATE);
6081 }
6082
6083 // Called in demand sleep when sleep discovered to be impossible after actually attaining that state.
6084 // This brings the parent to doze, which allows the root to step up from sleep to doze.
6085
6086 // In idle sleep, do nothing because the parent is still on and the root can freely change state.
6087
6088 void IORootParent::sleepToDoze( void )
6089 {
6090 if ( mostRecentChange == SLEEP_STATE ) {
6091 changePowerStateToPriv(DOZE_STATE);
6092 }
6093 }
6094
6095 void IORootParent::wakeSystem( void )
6096 {
6097 mostRecentChange = ON_STATE;
6098 changePowerStateToPriv(ON_STATE);
6099 }