]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOPMrootDomain.cpp
3ccda1a1b5b0fd50031e57d3eb070b3398a9a58c
[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 if (msg & kIOPMSetValue)
3171 {
3172 reportUserInput();
3173 }
3174
3175 // Tell PMCPU
3176 informCPUStateChange(kInformLid, 0);
3177
3178 // Tell general interest clients
3179 sendClientClamshellNotification();
3180
3181 bool aborting = ((lastSleepReason == kIOPMSleepReasonClamshell)
3182 || (lastSleepReason == kIOPMSleepReasonIdle)
3183 || (lastSleepReason == kIOPMSleepReasonMaintenance));
3184 if (aborting) userActivityCount++;
3185 DLOG("clamshell tickled %d lastSleepReason %d\n", userActivityCount, lastSleepReason);
3186 }
3187
3188 /*
3189 * Clamshell CLOSED
3190 * Send the clamshell interest notification since the lid is closing.
3191 */
3192 if (msg & kIOPMClamshellClosed)
3193 {
3194 // Received clamshel open message from clamshell controlling driver
3195 // Update our internal state and tell general interest clients
3196 clamshellIsClosed = true;
3197 clamshellExists = true;
3198
3199 // Tell PMCPU
3200 informCPUStateChange(kInformLid, 1);
3201
3202 // Tell general interest clients
3203 sendClientClamshellNotification();
3204
3205 // And set eval_clamshell = so we can attempt
3206 eval_clamshell = true;
3207 }
3208
3209 /*
3210 * Set Desktop mode (sent from graphics)
3211 *
3212 * -> reevaluate lid state
3213 */
3214 if (msg & kIOPMSetDesktopMode)
3215 {
3216 desktopMode = (0 != (msg & kIOPMSetValue));
3217 msg &= ~(kIOPMSetDesktopMode | kIOPMSetValue);
3218
3219 sendClientClamshellNotification();
3220
3221 // Re-evaluate the lid state
3222 if( clamshellIsClosed )
3223 {
3224 eval_clamshell = true;
3225 }
3226 }
3227
3228 /*
3229 * AC Adaptor connected
3230 *
3231 * -> reevaluate lid state
3232 */
3233 if (msg & kIOPMSetACAdaptorConnected)
3234 {
3235 acAdaptorConnected = (0 != (msg & kIOPMSetValue));
3236 msg &= ~(kIOPMSetACAdaptorConnected | kIOPMSetValue);
3237
3238 // Tell CPU PM
3239 informCPUStateChange(kInformAC, !acAdaptorConnected);
3240
3241 // Tell BSD if AC is connected
3242 // 0 == external power source; 1 == on battery
3243 post_sys_powersource(acAdaptorConnected ? 0:1);
3244
3245 sendClientClamshellNotification();
3246
3247 // Re-evaluate the lid state
3248 if( clamshellIsClosed )
3249 {
3250 eval_clamshell = true;
3251 }
3252 }
3253
3254 /*
3255 * Enable Clamshell (external display disappear)
3256 *
3257 * -> reevaluate lid state
3258 */
3259 if (msg & kIOPMEnableClamshell)
3260 {
3261 // Re-evaluate the lid state
3262 // System should sleep on external display disappearance
3263 // in lid closed operation.
3264 if( clamshellIsClosed && (true == ignoringClamshell) )
3265 {
3266 eval_clamshell = true;
3267 }
3268
3269 ignoringClamshell = false;
3270
3271 sendClientClamshellNotification();
3272 }
3273
3274 /*
3275 * Disable Clamshell (external display appeared)
3276 * We don't bother re-evaluating clamshell state. If the system is awake,
3277 * the lid is probably open.
3278 */
3279 if (msg & kIOPMDisableClamshell)
3280 {
3281 ignoringClamshell = true;
3282
3283 sendClientClamshellNotification();
3284 }
3285
3286 /*
3287 * Evaluate clamshell and SLEEP if appropiate
3288 */
3289 if ( eval_clamshell && shouldSleepOnClamshellClosed() )
3290 {
3291
3292
3293 // SLEEP!
3294 privateSleepSystem (kIOPMSleepReasonClamshell);
3295 }
3296
3297 /*
3298 * Power Button
3299 */
3300 if (msg & kIOPMPowerButton)
3301 {
3302 // toggle state of sleep/wake
3303 // are we dozing?
3304 if ( getPowerState() == DOZE_STATE )
3305 {
3306 #ifndef __LP64__
3307 // yes, tell the tree we're waking
3308 systemWake();
3309 #endif
3310 // wake the Display Wrangler
3311 reportUserInput();
3312 }
3313 else {
3314 OSString *pbs = OSString::withCString("DisablePowerButtonSleep");
3315 // Check that power button sleep is enabled
3316 if( pbs ) {
3317 if( kOSBooleanTrue != getProperty(pbs))
3318 privateSleepSystem (kIOPMSleepReasonPowerButton);
3319 }
3320 }
3321 }
3322
3323 /*
3324 * Allow Sleep
3325 *
3326 */
3327 if ( (msg & kIOPMAllowSleep) && !allowSleep )
3328 {
3329 allowSleep = true;
3330 adjustPowerState();
3331 }
3332
3333 /*
3334 * Prevent Sleep
3335 *
3336 */
3337 if (msg & kIOPMPreventSleep) {
3338 allowSleep = false;
3339 // are we dozing?
3340 if ( getPowerState() == DOZE_STATE ) {
3341 #ifndef __LP64__
3342 // yes, tell the tree we're waking
3343 systemWake();
3344 #endif
3345 adjustPowerState();
3346 // wake the Display Wrangler
3347 reportUserInput();
3348 } else {
3349 adjustPowerState();
3350 // make sure we have power to clamp
3351 patriarch->wakeSystem();
3352 }
3353 }
3354 }
3355
3356
3357 //******************************************************************************
3358 // getSleepSupported
3359 //
3360 //******************************************************************************
3361
3362 IOOptionBits IOPMrootDomain::getSleepSupported( void )
3363 {
3364 return( platformSleepSupport );
3365 }
3366
3367
3368 //******************************************************************************
3369 // setSleepSupported
3370 //
3371 //******************************************************************************
3372
3373 void IOPMrootDomain::setSleepSupported( IOOptionBits flags )
3374 {
3375 DLOG("setSleepSupported(%x)\n", (uint32_t) flags);
3376 OSBitOrAtomic(flags, &platformSleepSupport);
3377 }
3378
3379
3380 //******************************************************************************
3381 // requestPowerDomainState
3382 //
3383 // The root domain intercepts this call to the superclass.
3384 // Called on the PM work loop thread.
3385 //
3386 // If the clamp bit is not set in the desire, then the child doesn't need the power
3387 // state it's requesting; it just wants it. The root ignores desires but not needs.
3388 // If the clamp bit is not set, the root takes it that the child can tolerate no
3389 // power and interprets the request accordingly. If all children can thus tolerate
3390 // no power, we are on our way to idle sleep.
3391 //******************************************************************************
3392
3393 IOReturn IOPMrootDomain::requestPowerDomainState (
3394 IOPMPowerFlags desiredFlags,
3395 IOPowerConnection * whichChild,
3396 unsigned long specification )
3397 {
3398 OSIterator *iter;
3399 OSObject *next;
3400 IOPowerConnection *connection;
3401 IOPMPowerFlags powerRequestFlag = 0;
3402 IOPMPowerFlags editedDesire;
3403
3404 ASSERT_GATED();
3405
3406 if (kIOLogPMRootDomain & gIOKitDebug)
3407 {
3408 IOService * powerChild =
3409 (IOService *) whichChild->getChildEntry(gIOPowerPlane);
3410 DLOG("child %p, flags %lx, spec %lx - %s\n",
3411 powerChild, desiredFlags, specification,
3412 powerChild ? powerChild->getName() : "?");
3413 }
3414
3415 // Force the child's input power requirements to 0 unless the prevent
3416 // idle-sleep flag is set. No input power flags map to our state 0.
3417 // Our power clamp (deviceDesire) keeps the minimum power state at 2.
3418
3419 if (desiredFlags & kIOPMPreventIdleSleep)
3420 editedDesire = kIOPMPreventIdleSleep | kIOPMPowerOn;
3421 else
3422 editedDesire = 0;
3423
3424 // Recompute sleep supported flag (doze if not supported)
3425 sleepIsSupported = true;
3426
3427 iter = getChildIterator(gIOPowerPlane);
3428 if ( iter )
3429 {
3430 while ( (next = iter->getNextObject()) )
3431 {
3432 if ( (connection = OSDynamicCast(IOPowerConnection, next)) )
3433 {
3434 // Ignore child that are in the process of joining.
3435 if (connection->getReadyFlag() == false)
3436 continue;
3437
3438 // Is this connection attached to the child that called
3439 // requestPowerDomainState()?
3440
3441 if (connection == whichChild)
3442 {
3443 // OR in the child's input power requirements.
3444 powerRequestFlag |= editedDesire;
3445
3446 if ( desiredFlags & kIOPMPreventSystemSleep )
3447 sleepIsSupported = false;
3448 }
3449 else
3450 {
3451 if (kIOLogPMRootDomain & gIOKitDebug)
3452 {
3453 IOService * powerChild =
3454 (IOService *) connection->getChildEntry(gIOPowerPlane);
3455 DLOG("child %p, state %ld, noIdle %d, noSleep %d - %s\n",
3456 powerChild,
3457 connection->getDesiredDomainState(),
3458 connection->getPreventIdleSleepFlag(),
3459 connection->getPreventSystemSleepFlag(),
3460 powerChild ? powerChild->getName() : "?");
3461 }
3462
3463 // OR in the child's desired power state (0 or ON_STATE).
3464 powerRequestFlag |= connection->getDesiredDomainState();
3465
3466 if ( connection->getPreventSystemSleepFlag() )
3467 sleepIsSupported = false;
3468 }
3469 }
3470 }
3471 iter->release();
3472 }
3473
3474 DLOG("childPowerFlags 0x%lx, extraSleepDelay %ld\n",
3475 powerRequestFlag, extraSleepDelay);
3476
3477 if ( !powerRequestFlag && !systemBooting )
3478 {
3479 if (!wrangler)
3480 {
3481 sleepASAP = false;
3482 changePowerStateToPriv(ON_STATE);
3483 if (idleSeconds)
3484 {
3485 // stay awake for at least idleSeconds
3486 startIdleSleepTimer(idleSeconds);
3487 }
3488 }
3489 else if (!extraSleepDelay && !idleSleepTimerPending)
3490 {
3491 sleepASAP = true;
3492 }
3493 }
3494
3495 // Drop our power clamp to SLEEP_STATE when all children became idle,
3496 // and the system sleep and display sleep values are equal.
3497
3498 adjustPowerState();
3499
3500 // If our power clamp has already dropped to SLEEP_STATE, and no child
3501 // is keeping us at ON_STATE, then this will trigger idle sleep.
3502
3503 editedDesire |= (desiredFlags & kIOPMPreventSystemSleep);
3504
3505 return super::requestPowerDomainState(
3506 editedDesire, whichChild, specification);
3507 }
3508
3509
3510 //******************************************************************************
3511 // handlePlatformHaltRestart
3512 //
3513 //******************************************************************************
3514
3515 struct HaltRestartApplierContext {
3516 IOPMrootDomain * RootDomain;
3517 unsigned long PowerState;
3518 IOPMPowerFlags PowerFlags;
3519 UInt32 MessageType;
3520 UInt32 Counter;
3521 };
3522
3523 static void
3524 platformHaltRestartApplier( OSObject * object, void * context )
3525 {
3526 IOPowerStateChangeNotification notify;
3527 HaltRestartApplierContext * ctx;
3528 AbsoluteTime startTime;
3529 UInt32 deltaTime;
3530
3531 ctx = (HaltRestartApplierContext *) context;
3532
3533 memset(&notify, 0, sizeof(notify));
3534 notify.powerRef = (void *)ctx->Counter;
3535 notify.returnValue = 0;
3536 notify.stateNumber = ctx->PowerState;
3537 notify.stateFlags = ctx->PowerFlags;
3538
3539 clock_get_uptime(&startTime);
3540 ctx->RootDomain->messageClient( ctx->MessageType, object, (void *)&notify );
3541 deltaTime = computeDeltaTimeMS(&startTime);
3542
3543 if ((deltaTime > kPMHaltTimeoutMS) || (gIOKitDebug & kIOLogDebugPower))
3544 {
3545 _IOServiceInterestNotifier * notifier;
3546 notifier = OSDynamicCast(_IOServiceInterestNotifier, object);
3547
3548 // IOService children of IOPMrootDomain are not instrumented.
3549 // Only IORootParent currently falls under that group.
3550
3551 if (notifier)
3552 {
3553 KLOG("%s handler %p took %u ms\n",
3554 (ctx->MessageType == kIOMessageSystemWillPowerOff) ?
3555 "PowerOff" : "Restart",
3556 notifier->handler, (uint32_t) deltaTime );
3557 }
3558 }
3559
3560 ctx->Counter++;
3561 }
3562
3563 void IOPMrootDomain::handlePlatformHaltRestart( UInt32 pe_type )
3564 {
3565 HaltRestartApplierContext ctx;
3566 AbsoluteTime startTime;
3567 UInt32 deltaTime;
3568
3569 memset(&ctx, 0, sizeof(ctx));
3570 ctx.RootDomain = this;
3571
3572 clock_get_uptime(&startTime);
3573 switch (pe_type)
3574 {
3575 case kPEHaltCPU:
3576 case kPEUPSDelayHaltCPU:
3577 ctx.PowerState = OFF_STATE;
3578 ctx.MessageType = kIOMessageSystemWillPowerOff;
3579 break;
3580
3581 case kPERestartCPU:
3582 ctx.PowerState = RESTART_STATE;
3583 ctx.MessageType = kIOMessageSystemWillRestart;
3584 break;
3585
3586 default:
3587 return;
3588 }
3589
3590 // Notify legacy clients
3591 applyToInterested(gIOPriorityPowerStateInterest, platformHaltRestartApplier, &ctx);
3592
3593 // For normal shutdown, turn off File Server Mode.
3594 if (kPEHaltCPU == pe_type)
3595 {
3596 const OSSymbol * setting = OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey);
3597 OSNumber * num = OSNumber::withNumber((unsigned long long) 0, 32);
3598 if (setting && num)
3599 {
3600 setPMSetting(setting, num);
3601 setting->release();
3602 num->release();
3603 }
3604 }
3605
3606 // Notify in power tree order
3607 notifySystemShutdown(this, ctx.MessageType);
3608
3609 deltaTime = computeDeltaTimeMS(&startTime);
3610 KLOG("%s all drivers took %u ms\n",
3611 (ctx.MessageType == kIOMessageSystemWillPowerOff) ?
3612 "PowerOff" : "Restart",
3613 (uint32_t) deltaTime );
3614 }
3615
3616
3617 //******************************************************************************
3618 // registerInterest
3619 //
3620 //******************************************************************************
3621
3622 IONotifier * IOPMrootDomain::registerInterest(
3623 const OSSymbol * typeOfInterest,
3624 IOServiceInterestHandler handler,
3625 void * target, void * ref )
3626 {
3627 IONotifier * notifier;
3628 bool isConfigd;
3629
3630 isConfigd = typeOfInterest &&
3631 typeOfInterest->isEqualTo(kIOPMPrivilegedPowerInterest);
3632
3633 if (isConfigd)
3634 typeOfInterest = gIOAppPowerStateInterest;
3635
3636 notifier = super::registerInterest(typeOfInterest, handler, target, ref);
3637
3638 #if ROOT_DOMAIN_RUN_STATES
3639 if (isConfigd && notifier && pmPowerStateQueue)
3640 {
3641 notifier->retain();
3642 if (pmPowerStateQueue->submitPowerEvent(
3643 kPowerEventConfigdRegisteredInterest, notifier) == false)
3644 notifier->release();
3645 }
3646 #endif
3647
3648 return notifier;
3649 }
3650
3651 static bool clientMessageFilter( OSObject * object, void * arg )
3652 {
3653 #if ROOT_DOMAIN_RUN_STATES
3654 #if LOG_INTEREST_CLIENTS
3655 IOPMInterestContext * context = (IOPMInterestContext *) arg;
3656 #endif
3657 bool allow = false;
3658
3659 switch (gMessageClientType)
3660 {
3661 case kMessageClientNone:
3662 allow = false;
3663 break;
3664
3665 case kMessageClientAll:
3666 allow = true;
3667 break;
3668
3669 case kMessageClientConfigd:
3670 allow = ((object == (OSObject *) gConfigdNotifier) ||
3671 (object == (OSObject *) gSysPowerDownNotifier));
3672 break;
3673 }
3674
3675 #if LOG_INTEREST_CLIENTS
3676 if (allow)
3677 DLOG("system message %x to %p\n",
3678 context->msgType, object);
3679 #endif
3680
3681 return allow;
3682 #else
3683 return true;
3684 #endif
3685 }
3686
3687
3688 //******************************************************************************
3689 // tellChangeDown
3690 //
3691 // We override the superclass implementation so we can send a different message
3692 // type to the client or application being notified.
3693 //******************************************************************************
3694
3695 bool IOPMrootDomain::tellChangeDown( unsigned long stateNum )
3696 {
3697 bool done;
3698
3699 DLOG("tellChangeDown %u->%u, R-state %u\n",
3700 (uint32_t) getPowerState(), (uint32_t) stateNum, runStateIndex);
3701
3702 switch ( stateNum ) {
3703 case DOZE_STATE:
3704 case SLEEP_STATE:
3705
3706 if (!ignoreChangeDown)
3707 {
3708 userActivityAtSleep = userActivityCount;
3709 hibernateAborted = false;
3710 DLOG("tellChangeDown::userActivityAtSleep %d\n", userActivityAtSleep);
3711
3712 // Direct callout into OSKext so it can disable kext unloads
3713 // during sleep/wake to prevent deadlocks.
3714 OSKextSystemSleepOrWake( kIOMessageSystemWillSleep );
3715
3716 if ( (SLEEP_STATE == stateNum) && sleepSupportedPEFunction )
3717 {
3718 // Reset PCI prevent sleep flag before calling platform driver.
3719 OSBitAndAtomic(~kPCICantSleep, &platformSleepSupport);
3720
3721 // Skip PCI check for maintenance sleep.
3722 if ((runStateFlags & kRStateFlagSuppressPCICheck) == 0)
3723 {
3724 // Determine if the machine supports sleep, or must doze.
3725 getPlatform()->callPlatformFunction(
3726 sleepSupportedPEFunction, false,
3727 NULL, NULL, NULL, NULL);
3728 }
3729
3730 // If the machine only supports doze, the callPlatformFunction call
3731 // boils down to IOPMrootDomain::setSleepSupported(kPCICantSleep),
3732 // otherwise nothing.
3733 }
3734
3735 // Notify platform that sleep has begun
3736 getPlatform()->callPlatformFunction(
3737 sleepMessagePEFunction, false,
3738 (void *)(uintptr_t) kIOMessageSystemWillSleep,
3739 NULL, NULL, NULL);
3740
3741 // Update canSleep and kIOSleepSupportedKey property so drivers
3742 // can tell if platform is going to sleep versus doze.
3743
3744 #if CONFIG_SLEEP
3745 canSleep = true;
3746 #else
3747 canSleep = false;
3748 #endif
3749 if (!sleepIsSupported)
3750 canSleep = false;
3751 if (platformSleepSupport & kPCICantSleep)
3752 canSleep = false;
3753 setProperty(kIOSleepSupportedKey, canSleep);
3754 DLOG("canSleep %d\n", canSleep);
3755
3756 // Publish the new sleep-wake UUID
3757 publishSleepWakeUUID(true);
3758
3759 // Two change downs are sent by IOServicePM. Ignore the 2nd.
3760 ignoreChangeDown = true;
3761
3762 tracePoint( kIOPMTracePointSystemSleepAppsPhase);
3763 }
3764
3765 DLOG("kIOMessageSystemWillSleep (%d)\n", gMessageClientType);
3766 done = super::tellClientsWithResponse(
3767 kIOMessageSystemWillSleep, clientMessageFilter);
3768 break;
3769
3770 default:
3771 done = super::tellChangeDown(stateNum);
3772 break;
3773 }
3774 return done;
3775 }
3776
3777
3778 //******************************************************************************
3779 // askChangeDown
3780 //
3781 // We override the superclass implementation so we can send a different message
3782 // type to the client or application being notified.
3783 //
3784 // This must be idle sleep since we don't ask during any other power change.
3785 //******************************************************************************
3786
3787 bool IOPMrootDomain::askChangeDown( unsigned long stateNum )
3788 {
3789 DLOG("askChangeDown %u->%u, R-state %u\n",
3790 (uint32_t) getPowerState(), (uint32_t) stateNum, runStateIndex);
3791 DLOG("kIOMessageCanSystemSleep (%d)\n", gMessageClientType);
3792
3793 return super::tellClientsWithResponse(
3794 kIOMessageCanSystemSleep,
3795 clientMessageFilter);
3796 }
3797
3798
3799 //******************************************************************************
3800 // tellNoChangeDown
3801 //
3802 // Notify registered applications and kernel clients that we are not dropping
3803 // power.
3804 //
3805 // We override the superclass implementation so we can send a different message
3806 // type to the client or application being notified.
3807 //
3808 // This must be a vetoed idle sleep, since no other power change can be vetoed.
3809 //******************************************************************************
3810
3811 void IOPMrootDomain::tellNoChangeDown( unsigned long stateNum )
3812 {
3813 DLOG("tellNoChangeDown %u->%u, R-state %u\n",
3814 (uint32_t) getPowerState(), (uint32_t) stateNum, runStateIndex);
3815
3816 // Sleep canceled, clear the sleep trace point.
3817 tracePoint(kIOPMTracePointSystemUp);
3818
3819 if (idleSeconds && !wrangler)
3820 {
3821 // stay awake for at least idleSeconds
3822 sleepASAP = false;
3823 startIdleSleepTimer(idleSeconds);
3824 }
3825 DLOG("kIOMessageSystemWillNotSleep (%d)\n", gMessageClientType);
3826 return tellClients(kIOMessageSystemWillNotSleep, clientMessageFilter);
3827 }
3828
3829
3830 //******************************************************************************
3831 // tellChangeUp
3832 //
3833 // Notify registered applications and kernel clients that we are raising power.
3834 //
3835 // We override the superclass implementation so we can send a different message
3836 // type to the client or application being notified.
3837 //******************************************************************************
3838
3839 void IOPMrootDomain::tellChangeUp( unsigned long stateNum )
3840 {
3841 OSData *publishPMStats = NULL;
3842
3843 DLOG("tellChangeUp %u->%u, R-state %u\n",
3844 (uint32_t) getPowerState(), (uint32_t) stateNum, runStateIndex);
3845
3846 ignoreChangeDown = false;
3847
3848 if ( stateNum == ON_STATE )
3849 {
3850 // Direct callout into OSKext so it can disable kext unloads
3851 // during sleep/wake to prevent deadlocks.
3852 OSKextSystemSleepOrWake( kIOMessageSystemHasPoweredOn );
3853
3854 // Notify platform that sleep was cancelled or resumed.
3855 getPlatform()->callPlatformFunction(
3856 sleepMessagePEFunction, false,
3857 (void *)(uintptr_t) kIOMessageSystemHasPoweredOn,
3858 NULL, NULL, NULL);
3859
3860 if (getPowerState() == ON_STATE)
3861 {
3862 // this is a quick wake from aborted sleep
3863 if (idleSeconds && !wrangler)
3864 {
3865 // stay awake for at least idleSeconds
3866 sleepASAP = false;
3867 startIdleSleepTimer(idleSeconds);
3868 }
3869 DLOG("kIOMessageSystemWillPowerOn (%d)\n", gMessageClientType);
3870 tellClients(kIOMessageSystemWillPowerOn, clientMessageFilter);
3871 }
3872 #if HIBERNATION
3873 else
3874 {
3875 IOHibernateSystemPostWake();
3876 }
3877 #endif
3878
3879 tracePoint(kIOPMTracePointSystemWakeAppsPhase);
3880 publishPMStats = OSData::withBytes(&pmStats, sizeof(pmStats));
3881 setProperty(kIOPMSleepStatisticsKey, publishPMStats);
3882 publishPMStats->release();
3883 bzero(&pmStats, sizeof(pmStats));
3884
3885 if (pmStatsAppResponses)
3886 {
3887 setProperty(kIOPMSleepStatisticsAppsKey, pmStatsAppResponses);
3888 pmStatsAppResponses->release();
3889 pmStatsAppResponses = OSArray::withCapacity(5);
3890 }
3891
3892 DLOG("kIOMessageSystemHasPoweredOn (%d)\n", gMessageClientType);
3893 tellClients(kIOMessageSystemHasPoweredOn, clientMessageFilter);
3894
3895 tracePoint(kIOPMTracePointSystemUp);
3896 }
3897 }
3898
3899
3900 //******************************************************************************
3901 // reportUserInput
3902 //
3903 //******************************************************************************
3904
3905 void IOPMrootDomain::reportUserInput( void )
3906 {
3907 #if !NO_KERNEL_HID
3908 OSIterator * iter;
3909
3910 if(!wrangler)
3911 {
3912 iter = getMatchingServices(serviceMatching("IODisplayWrangler"));
3913 if(iter)
3914 {
3915 wrangler = (IOService *) iter->getNextObject();
3916 iter->release();
3917 }
3918 }
3919
3920 if(wrangler)
3921 wrangler->activityTickle(0,0);
3922 #endif
3923 }
3924
3925
3926 //******************************************************************************
3927 // setQuickSpinDownTimeout
3928 //
3929 //******************************************************************************
3930
3931 void IOPMrootDomain::setQuickSpinDownTimeout( void )
3932 {
3933 ASSERT_GATED();
3934 setAggressiveness(
3935 kPMMinutesToSpinDown, 0, kAggressivesOptionQuickSpindownEnable );
3936 }
3937
3938
3939 //******************************************************************************
3940 // restoreUserSpinDownTimeout
3941 //
3942 //******************************************************************************
3943
3944 void IOPMrootDomain::restoreUserSpinDownTimeout( void )
3945 {
3946 ASSERT_GATED();
3947 setAggressiveness(
3948 kPMMinutesToSpinDown, 0, kAggressivesOptionQuickSpindownDisable );
3949 }
3950
3951
3952 //******************************************************************************
3953 // changePowerStateTo & changePowerStateToPriv
3954 //
3955 // Override of these methods for logging purposes.
3956 //******************************************************************************
3957
3958 IOReturn IOPMrootDomain::changePowerStateTo( unsigned long ordinal )
3959 {
3960 return kIOReturnUnsupported; // ignored
3961 }
3962
3963 IOReturn IOPMrootDomain::changePowerStateToPriv( unsigned long ordinal )
3964 {
3965 DLOG("changePowerStateToPriv(%lu)\n", ordinal);
3966
3967 if ( (getPowerState() == DOZE_STATE) && (ordinal != ON_STATE) )
3968 {
3969 return kIOReturnSuccess;
3970 }
3971
3972 if ( (userDisabledAllSleep || systemBooting || systemShutdown) &&
3973 (ordinal == SLEEP_STATE) )
3974 {
3975 DLOG("SLEEP rejected, forced to ON state (UD %d, SB %d, SS %d)\n",
3976 userDisabledAllSleep, systemBooting, systemShutdown);
3977
3978 super::changePowerStateToPriv(ON_STATE);
3979 }
3980
3981 return super::changePowerStateToPriv(ordinal);
3982 }
3983
3984 //******************************************************************************
3985 // activity detect
3986 //
3987 //******************************************************************************
3988
3989 bool IOPMrootDomain::activitySinceSleep(void)
3990 {
3991 return (userActivityCount != userActivityAtSleep);
3992 }
3993
3994 bool IOPMrootDomain::abortHibernation(void)
3995 {
3996 bool ret = activitySinceSleep();
3997
3998 if (ret && !hibernateAborted)
3999 {
4000 DLOG("activitySinceSleep ABORT [%d, %d]\n", userActivityCount, userActivityAtSleep);
4001 hibernateAborted = true;
4002 }
4003 return (ret);
4004 }
4005
4006 extern "C" int
4007 hibernate_should_abort(void)
4008 {
4009 if (gRootDomain)
4010 return (gRootDomain->abortHibernation());
4011 else
4012 return (0);
4013 }
4014
4015 //******************************************************************************
4016 // updateRunState
4017 //
4018 //******************************************************************************
4019
4020 void IOPMrootDomain::updateRunState( uint32_t inRunState )
4021 {
4022 #if ROOT_DOMAIN_RUN_STATES
4023 if (inRunState < kRStateCount)
4024 {
4025 runStateIndex = nextRunStateIndex = inRunState;
4026 runStateFlags = gRStateFlags[inRunState];
4027
4028 setProperty(
4029 kIOPMRootDomainRunStateKey,
4030 (unsigned long long) inRunState, 32);
4031 }
4032 #endif
4033 }
4034
4035
4036 #if ROOT_DOMAIN_RUN_STATES
4037 //******************************************************************************
4038 // tagPowerPlaneService
4039 //
4040 // Running on PM work loop thread.
4041 //******************************************************************************
4042
4043 void IOPMrootDomain::tagPowerPlaneService(
4044 IOService * service,
4045 uint32_t * rdFlags )
4046 {
4047 *rdFlags = 0;
4048
4049 if (service->getProperty("IOPMStrictTreeOrder") ||
4050 service->metaCast("IODisplayWrangler") ||
4051 OSDynamicCast(OSNumber,
4052 service->getProperty("IOPMUnattendedWakePowerState")))
4053 {
4054 *rdFlags |= kServiceFlagGraphics;
4055 DLOG("tagged device %s %x\n", service->getName(), *rdFlags);
4056 }
4057
4058 // Locate the first PCI host bridge.
4059 if (!pciHostBridgeDevice && service->metaCast("IOPCIBridge"))
4060 {
4061 IOService * provider = service->getProvider();
4062 if (OSDynamicCast(IOPlatformDevice, provider) &&
4063 provider->inPlane(gIODTPlane))
4064 {
4065 pciHostBridgeDevice = provider;
4066 DLOG("PMTrace found PCI host bridge %s->%s\n",
4067 provider->getName(), service->getName());
4068 }
4069 }
4070
4071 // Tag top-level PCI devices. The order of PMinit() call does not
4072 // change across boots and is used as the PCI bit number.
4073 if (pciHostBridgeDevice && service->metaCast("IOPCIDevice"))
4074 {
4075 // Would prefer to check built-in property, but tagPowerPlaneService()
4076 // is called before pciDevice->registerService().
4077 IORegistryEntry * parent = service->getParentEntry(gIODTPlane);
4078 if ((parent == pciHostBridgeDevice) && service->getProperty("acpi-device"))
4079 {
4080 int bit = pmTracer->recordTopLevelPCIDevice( service );
4081 if (bit >= 0)
4082 {
4083 // Save the assigned bit for fast lookup.
4084 bit &= 0xff;
4085 *rdFlags |= (kServiceFlagTopLevelPCI | (bit << 8));
4086 }
4087 }
4088 }
4089 }
4090
4091
4092 //******************************************************************************
4093 // handleActivityTickleForService
4094 //
4095 // Called by IOService::activityTickle() for a tickle that is requesting the
4096 // service to raise power state. Called from driver thread.
4097 //******************************************************************************
4098
4099 void IOPMrootDomain::handleActivityTickleForService( IOService * service,
4100 unsigned long type,
4101 unsigned long currentPowerState,
4102 uint32_t activityTickleCount )
4103 {
4104 if ((service == wrangler)
4105 )
4106 {
4107 bool aborting = ((lastSleepReason == kIOPMSleepReasonIdle)
4108 || (lastSleepReason == kIOPMSleepReasonMaintenance));
4109 if (aborting) userActivityCount++;
4110 DLOG("display wrangler tickled1 %d lastSleepReason %d\n", userActivityCount, lastSleepReason);
4111 }
4112
4113 // Tickle directed to IODisplayWrangler while graphics is disabled.
4114 // Bring graphics online.
4115
4116 if ((!currentPowerState) &&
4117 (service == wrangler) &&
4118 (runStateIndex > kRStateNormal) &&
4119 (false == wranglerTickled) &&
4120 (false == lowBatteryCondition))
4121 {
4122 DLOG("display wrangler tickled\n");
4123 if (kIOLogPMRootDomain & gIOKitDebug)
4124 OSReportWithBacktrace("Display Tickle");
4125 wranglerTickled = true;
4126 synchronizePowerTree();
4127 }
4128 }
4129
4130 //******************************************************************************
4131 // handlePowerChangeStartForService
4132 //
4133 // Running on PM work loop thread.
4134 //******************************************************************************
4135
4136 void IOPMrootDomain::handlePowerChangeStartForService(
4137 IOService * service,
4138 uint32_t * rdFlags,
4139 uint32_t newPowerState,
4140 uint32_t changeFlags )
4141 {
4142 if (service == this)
4143 {
4144 uint32_t currentPowerState = (uint32_t) getPowerState();
4145 uint32_t nextRunStateFlags;
4146
4147 assert(nextRunStateIndex < kRStateCount);
4148 nextRunStateFlags = gRStateFlags[nextRunStateIndex];
4149
4150 gMessageClientType = kMessageClientNone;
4151
4152 // Transition towards or away from ON power state.
4153
4154 if ((currentPowerState != newPowerState) &&
4155 ((ON_STATE == newPowerState) || (ON_STATE == currentPowerState)))
4156 {
4157 if ((runStateFlags & kRStateFlagSuppressMessages) == 0)
4158 gMessageClientType = kMessageClientAll;
4159 else
4160 gMessageClientType = kMessageClientConfigd;
4161 }
4162
4163 // Transition caused by deassertion of system notification suppression.
4164
4165 if ((ON_STATE == newPowerState) &&
4166 (ON_STATE == currentPowerState) &&
4167 ((runStateFlags ^ nextRunStateFlags) & kRStateFlagSuppressMessages))
4168 {
4169 gMessageClientType = kMessageClientAll;
4170 }
4171
4172 if (ON_STATE == newPowerState)
4173 {
4174 DLOG("kIOMessageSystemWillPowerOn (%d)\n",
4175 gMessageClientType);
4176 tellClients(kIOMessageSystemWillPowerOn, clientMessageFilter);
4177 }
4178
4179 if (SLEEP_STATE == newPowerState)
4180 {
4181 tracePoint(kIOPMTracePointSleepStarted);
4182 }
4183 }
4184
4185 if (*rdFlags & kServiceFlagTopLevelPCI)
4186 {
4187 pmTracer->tracePCIPowerChange(
4188 PMTraceWorker::kPowerChangeStart,
4189 service, changeFlags,
4190 (*rdFlags >> 8) & 0xff);
4191 }
4192 }
4193
4194
4195 //******************************************************************************
4196 // handlePowerChangeDoneForService
4197 //
4198 // Running on PM work loop thread.
4199 //******************************************************************************
4200
4201 void IOPMrootDomain::handlePowerChangeDoneForService(
4202 IOService * service,
4203 uint32_t * rdFlags,
4204 uint32_t newPowerState,
4205 uint32_t changeFlags )
4206 {
4207 if (*rdFlags & kServiceFlagTopLevelPCI)
4208 {
4209 pmTracer->tracePCIPowerChange(
4210 PMTraceWorker::kPowerChangeCompleted,
4211 service, changeFlags,
4212 (*rdFlags >> 8) & 0xff);
4213 }
4214 }
4215
4216
4217 //******************************************************************************
4218 // overridePowerStateForService
4219 //
4220 // Runs on PM work loop thread.
4221 //******************************************************************************
4222
4223 void IOPMrootDomain::overridePowerStateForService(
4224 IOService * service,
4225 uint32_t * rdFlags,
4226 unsigned long * powerState,
4227 uint32_t changeFlags )
4228 {
4229 uint32_t inPowerState = (uint32_t) *powerState;
4230
4231 if ((service == this) && (inPowerState == ON_STATE) &&
4232 (changeFlags & kIOPMSynchronize))
4233 {
4234 DLOG("sync root domain %u->%u\n",
4235 (uint32_t) getPowerState(), inPowerState);
4236
4237 // Root Domain is in a reduced R-state, and a HID tickle has
4238 // requested a PM tree sync. Begin R-state transition.
4239
4240 if (runStateIndex != kRStateNormal)
4241 {
4242 sleepTimerMaintenance = false;
4243 hibernateNoDefeat = false;
4244 nextRunStateIndex = kRStateNormal;
4245 setProperty(
4246 kIOPMRootDomainRunStateKey,
4247 (unsigned long long) kRStateNormal, 32);
4248 }
4249 }
4250
4251 if (*rdFlags & kServiceFlagGraphics)
4252 {
4253 DLOG("graphics device %s %u->%u (flags 0x%x)\n",
4254 service->getName(), (uint32_t) service->getPowerState(),
4255 inPowerState, changeFlags);
4256
4257 if (inPowerState == 0)
4258 {
4259 // Graphics device is powering down, apply limit preventing
4260 // device from powering back up later unless we consent.
4261
4262 if ((*rdFlags & kServiceFlagNoPowerUp) == 0)
4263 {
4264 *rdFlags |= kServiceFlagNoPowerUp;
4265 DLOG("asserted power limit for %s\n",
4266 service->getName());
4267 }
4268 }
4269 else
4270 {
4271 uint32_t nextRunStateFlags;
4272
4273 assert(nextRunStateIndex < kRStateCount);
4274 nextRunStateFlags = gRStateFlags[nextRunStateIndex];
4275
4276 // Graphics device is powering up. Release power limit at the
4277 // did-change machine state.
4278
4279 if (changeFlags & kIOPMSynchronize)
4280 {
4281 if ((runStateFlags & kRStateFlagSuppressGraphics) &&
4282 ((nextRunStateFlags & kRStateFlagSuppressGraphics) == 0) &&
4283 (changeFlags & kIOPMDomainDidChange))
4284 {
4285 // Woke up without graphics power, but
4286 // HID event has tickled display wrangler.
4287 *rdFlags &= ~kServiceFlagNoPowerUp;
4288 DLOG("removed power limit for %s\n",
4289 service->getName());
4290 }
4291 }
4292 else if ((runStateFlags & kRStateFlagSuppressGraphics) == 0)
4293 {
4294 *rdFlags &= ~kServiceFlagNoPowerUp;
4295 }
4296
4297 if (*rdFlags & kServiceFlagNoPowerUp)
4298 {
4299 DLOG("limited %s to power state 0\n",
4300 service->getName());
4301 *powerState = 0;
4302 }
4303 }
4304 }
4305 }
4306
4307
4308 //******************************************************************************
4309 // setMaintenanceWakeCalendar
4310 //
4311 //******************************************************************************
4312
4313 IOReturn IOPMrootDomain::setMaintenanceWakeCalendar(
4314 const IOPMCalendarStruct * calendar )
4315 {
4316 OSData * data;
4317 IOReturn ret;
4318
4319 if (!calendar)
4320 return kIOReturnBadArgument;
4321
4322 data = OSData::withBytesNoCopy((void *) calendar, sizeof(*calendar));
4323 if (!data)
4324 return kIOReturnNoMemory;
4325
4326 ret = setPMSetting(gIOPMSettingMaintenanceWakeCalendarKey, data);
4327
4328 data->release();
4329 return ret;
4330 }
4331 #endif /* ROOT_DOMAIN_RUN_STATES */
4332
4333
4334 //******************************************************************************
4335 // sysPowerDownHandler
4336 //
4337 // Receives a notification when the RootDomain changes state.
4338 //
4339 // Allows us to take action on system sleep, power down, and restart after
4340 // applications have received their power change notifications and replied,
4341 // but before drivers have powered down. We perform a vfs sync on power down.
4342 //******************************************************************************
4343
4344 IOReturn IOPMrootDomain::sysPowerDownHandler( void * target, void * refCon,
4345 UInt32 messageType, IOService * service,
4346 void * messageArgument, vm_size_t argSize )
4347 {
4348 IOReturn ret;
4349 IOPowerStateChangeNotification *params = (IOPowerStateChangeNotification *) messageArgument;
4350 IOPMrootDomain *rootDomain = OSDynamicCast(IOPMrootDomain, service);
4351
4352 DLOG("sysPowerDownHandler message %x\n", (uint32_t) messageType);
4353
4354 if(!rootDomain)
4355 return kIOReturnUnsupported;
4356
4357 switch (messageType) {
4358 case kIOMessageSystemWillSleep:
4359 // Interested applications have been notified of an impending power
4360 // change and have acked (when applicable).
4361 // This is our chance to save whatever state we can before powering
4362 // down.
4363 // We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c,
4364 // via callout
4365 #if HIBERNATION
4366 rootDomain->evaluateSystemSleepPolicyEarly();
4367 if (rootDomain->hibernateMode && !rootDomain->hibernateDisabled)
4368 {
4369 // We will ack within 240 seconds
4370 params->returnValue = 240 * 1000 * 1000;
4371 }
4372 else
4373 #endif
4374 // We will ack within 20 seconds
4375 params->returnValue = 20 * 1000 * 1000;
4376 DLOG("sysPowerDownHandler timeout %d s\n", (int) (params->returnValue / 1000 / 1000));
4377 if ( ! OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending ) )
4378 {
4379 // Purposely delay the ack and hope that shutdown occurs quickly.
4380 // Another option is not to schedule the thread and wait for
4381 // ack timeout...
4382 AbsoluteTime deadline;
4383 clock_interval_to_deadline( 30, kSecondScale, &deadline );
4384 thread_call_enter1_delayed( rootDomain->diskSyncCalloutEntry,
4385 (thread_call_param_t)params->powerRef,
4386 deadline );
4387 }
4388 else
4389 thread_call_enter1(rootDomain->diskSyncCalloutEntry, (thread_call_param_t)params->powerRef);
4390 ret = kIOReturnSuccess;
4391 break;
4392
4393 case kIOMessageSystemWillPowerOff:
4394 case kIOMessageSystemWillRestart:
4395 ret = kIOReturnUnsupported;
4396 break;
4397
4398 default:
4399 ret = kIOReturnUnsupported;
4400 break;
4401 }
4402 return ret;
4403 }
4404
4405 //******************************************************************************
4406 // publishSleepWakeUUID
4407 //
4408 //
4409 //******************************************************************************
4410 void IOPMrootDomain::publishSleepWakeUUID( bool shouldPublish )
4411 {
4412 if (shouldPublish)
4413 {
4414 if (queuedSleepWakeUUIDString)
4415 {
4416 if (OSCompareAndSwap(/*old*/ true, /*new*/ false, &gSleepWakeUUIDIsSet))
4417 {
4418 // Upon wake, it takes some time for userland to invalidate the
4419 // UUID. If another sleep is initiated during that period, force
4420 // a CLEAR message to balance the upcoming SET message.
4421
4422 messageClients( kIOPMMessageSleepWakeUUIDChange,
4423 kIOPMMessageSleepWakeUUIDCleared );
4424
4425 DLOG("SleepWake UUID forced clear\n");
4426 }
4427
4428 setProperty(kIOPMSleepWakeUUIDKey, queuedSleepWakeUUIDString);
4429 DLOG("SleepWake UUID published: %s\n", queuedSleepWakeUUIDString->getCStringNoCopy());
4430 queuedSleepWakeUUIDString->release();
4431 queuedSleepWakeUUIDString = NULL;
4432 messageClients(kIOPMMessageSleepWakeUUIDChange,
4433 kIOPMMessageSleepWakeUUIDSet);
4434 }
4435 } else {
4436 if (OSCompareAndSwap(/*old*/ true, /*new*/ false, &gSleepWakeUUIDIsSet))
4437 {
4438 DLOG("SleepWake UUID cleared\n");
4439 removeProperty(kIOPMSleepWakeUUIDKey);
4440 messageClients(kIOPMMessageSleepWakeUUIDChange,
4441 kIOPMMessageSleepWakeUUIDCleared);
4442 }
4443 }
4444 }
4445
4446
4447 //******************************************************************************
4448 // displayWranglerNotification
4449 //
4450 // Receives a notification when the IODisplayWrangler changes state.
4451 //
4452 // Allows us to take action on display dim/undim.
4453 //
4454 // When the display sleeps we:
4455 // - Start the idle sleep timer
4456 // - set the quick spin down timeout
4457 //
4458 // On wake from display sleep:
4459 // - Cancel the idle sleep timer
4460 // - restore the user's chosen spindown timer from the "quick" spin down value
4461 //******************************************************************************
4462
4463 IOReturn IOPMrootDomain::displayWranglerNotification(
4464 void * target, void * refCon,
4465 UInt32 messageType, IOService * service,
4466 void * messageArgument, vm_size_t argSize )
4467 {
4468 #if !NO_KERNEL_HID
4469 int displayPowerState;
4470 IOPowerStateChangeNotification * params =
4471 (IOPowerStateChangeNotification *) messageArgument;
4472
4473 if ((messageType != kIOMessageDeviceWillPowerOff) &&
4474 (messageType != kIOMessageDeviceHasPoweredOn))
4475 return kIOReturnUnsupported;
4476
4477 ASSERT_GATED();
4478 if (!gRootDomain)
4479 return kIOReturnUnsupported;
4480
4481 displayPowerState = params->stateNumber;
4482 DLOG("DisplayWrangler message 0x%x, new power state %d\n",
4483 (uint32_t) messageType, displayPowerState);
4484
4485 switch (messageType) {
4486 case kIOMessageDeviceWillPowerOff:
4487
4488 // The display wrangler has dropped power because of idle display sleep
4489 // or force system sleep.
4490 //
4491 // 4 Display ON
4492 // 3 Display Dim
4493 // 2 Display Sleep
4494 // 1 Not visible to user
4495 // 0 Not visible to user
4496
4497 if (gRootDomain->wranglerAsleep || (displayPowerState > 2))
4498 break;
4499
4500 // Record the time the display wrangler went to sleep.
4501
4502 gRootDomain->wranglerAsleep = true;
4503 clock_get_uptime(&gRootDomain->wranglerSleepTime);
4504
4505 // We start a timer here if the System Sleep timer is greater than the
4506 // Display Sleep timer. We kick off this timer when the display sleeps.
4507 //
4508 // Note that, although Display Dim timings may change adaptively accordingly
4509 // to the user's activity patterns, Display Sleep _always_ occurs at the
4510 // specified interval since last user activity.
4511
4512 if ( gRootDomain->extraSleepDelay )
4513 {
4514 gRootDomain->startIdleSleepTimer(gRootDomain->extraSleepDelay * 60);
4515 }
4516 else if ( gRootDomain->sleepSlider )
4517 {
4518 // Accelerate disk spindown if system sleep and display sleep
4519 // sliders are set to the same value (e.g. both set to 5 min),
4520 // and display is about to go dark. Check that spin down timer
4521 // is non-zero (zero = never spin down) and system sleep is
4522 // not set to never sleep.
4523
4524 gRootDomain->setQuickSpinDownTimeout();
4525 }
4526
4527 break;
4528
4529 case kIOMessageDeviceHasPoweredOn:
4530
4531 // The display wrangler has powered on either because of user activity
4532 // or wake from sleep/doze.
4533
4534 if ( 4 != displayPowerState )
4535 break;
4536
4537 gRootDomain->wranglerAsleep = false;
4538 gRootDomain->adjustPowerState();
4539 gRootDomain->cancelIdleSleepTimer();
4540
4541 // Change the spindown value back to the user's selection from our
4542 // accelerated setting.
4543 gRootDomain->restoreUserSpinDownTimeout();
4544
4545 break;
4546
4547 default:
4548 break;
4549 }
4550 #endif
4551 return kIOReturnUnsupported;
4552 }
4553
4554
4555 //******************************************************************************
4556 // displayWranglerPublished
4557 //
4558 // Receives a notification when the IODisplayWrangler is published.
4559 // When it's published we install a power state change handler.
4560 //******************************************************************************
4561
4562 bool IOPMrootDomain::displayWranglerPublished(
4563 void * target,
4564 void * refCon,
4565 IOService * newService)
4566 {
4567 #if !NO_KERNEL_HID
4568 if(!gRootDomain)
4569 return false;
4570
4571 gRootDomain->wrangler = newService;
4572
4573 // we found the display wrangler, now install a handler
4574 if( !gRootDomain->wrangler->registerInterest( gIOGeneralInterest,
4575 &displayWranglerNotification, target, 0) )
4576 {
4577 return false;
4578 }
4579 #endif
4580 return true;
4581 }
4582
4583
4584 //******************************************************************************
4585 // batteryPublished
4586 //
4587 // Notification on battery class IOPowerSource appearance
4588 //******************************************************************************
4589
4590 bool IOPMrootDomain::batteryPublished(
4591 void * target,
4592 void * root_domain,
4593 IOService * resourceService )
4594 {
4595 // rdar://2936060&4435589
4596 // All laptops have dimmable LCD displays
4597 // All laptops have batteries
4598 // So if this machine has a battery, publish the fact that the backlight
4599 // supports dimming.
4600 ((IOPMrootDomain *)root_domain)->publishFeature("DisplayDims");
4601
4602 return (true);
4603 }
4604
4605
4606 //******************************************************************************
4607 // adjustPowerState
4608 //
4609 // Some condition that affects our wake/sleep/doze decision has changed.
4610 //
4611 // If the sleep slider is in the off position, we cannot sleep or doze.
4612 // If the enclosure is open, we cannot sleep or doze.
4613 // If the system is still booting, we cannot sleep or doze.
4614 //
4615 // In those circumstances, we prevent sleep and doze by holding power on with
4616 // changePowerStateToPriv(ON).
4617 //
4618 // If the above conditions do not exist, and also the sleep timer has expired,
4619 // we allow sleep or doze to occur with either changePowerStateToPriv(SLEEP) or
4620 // changePowerStateToPriv(DOZE) depending on whether or not we already know the
4621 // platform cannot sleep.
4622 //
4623 // In this case, sleep or doze will either occur immediately or at the next time
4624 // that no children are holding the system out of idle sleep via the
4625 // kIOPMPreventIdleSleep flag in their power state arrays.
4626 //******************************************************************************
4627
4628 void IOPMrootDomain::adjustPowerState( void )
4629 {
4630 DLOG("adjustPowerState "
4631 "PS %u, ASAP %d, SL %ld, AS %d, SB %d, SS %d, UD %d\n",
4632 (uint32_t) getPowerState(), sleepASAP, sleepSlider,
4633 allowSleep, systemBooting, systemShutdown, userDisabledAllSleep);
4634
4635 ASSERT_GATED();
4636
4637 if ( (sleepSlider == 0)
4638 || !allowSleep
4639 || systemBooting
4640 || systemShutdown
4641 || userDisabledAllSleep
4642 || (runStateFlags & kRStateFlagDisableIdleSleep) )
4643 {
4644 changePowerStateToPriv(ON_STATE);
4645 } else {
4646 if ( sleepASAP )
4647 {
4648 /* Convenient place to run any code at idle sleep time
4649 * IOPMrootDomain initiates an idle sleep here
4650 *
4651 * Set last sleep cause accordingly.
4652 */
4653 lastSleepReason = kIOPMSleepReasonIdle;
4654 setProperty(kRootDomainSleepReasonKey, kIOPMIdleSleepKey);
4655
4656 sleepASAP = false;
4657 changePowerStateToPriv(SLEEP_STATE);
4658 }
4659 }
4660 }
4661
4662 void IOPMrootDomain::pmStatsRecordEvent(
4663 int eventIndex,
4664 AbsoluteTime timestamp)
4665 {
4666 bool starting = eventIndex & kIOPMStatsEventStartFlag ? true:false;
4667 bool stopping = eventIndex & kIOPMStatsEventStopFlag ? true:false;
4668 uint64_t delta;
4669 uint64_t nsec;
4670
4671 eventIndex &= ~(kIOPMStatsEventStartFlag | kIOPMStatsEventStopFlag);
4672
4673 absolutetime_to_nanoseconds(timestamp, &nsec);
4674
4675 switch (eventIndex) {
4676 case kIOPMStatsHibernateImageWrite:
4677 if (starting)
4678 pmStats.hibWrite.start = nsec;
4679 else if (stopping)
4680 pmStats.hibWrite.stop = nsec;
4681
4682 if (stopping) {
4683 delta = pmStats.hibWrite.stop - pmStats.hibWrite.start;
4684 IOLog("PMStats: Hibernate write took %qd ms\n", delta/1000000ULL);
4685 }
4686 break;
4687 case kIOPMStatsHibernateImageRead:
4688 if (starting)
4689 pmStats.hibRead.start = nsec;
4690 else if (stopping)
4691 pmStats.hibRead.stop = nsec;
4692
4693 if (stopping) {
4694 delta = pmStats.hibRead.stop - pmStats.hibRead.start;
4695 IOLog("PMStats: Hibernate read took %qd ms\n", delta/1000000ULL);
4696 }
4697 break;
4698 }
4699 }
4700
4701 /*
4702 * Appends a record of the application response to
4703 * IOPMrootDomain::pmStatsAppResponses
4704 */
4705 void IOPMrootDomain::pmStatsRecordApplicationResponse(
4706 const OSSymbol *response,
4707 const char *name,
4708 int messageType,
4709 uint32_t delay_ms,
4710 int app_pid)
4711 {
4712 OSDictionary *responseDescription = NULL;
4713 OSNumber *delayNum = NULL;
4714 OSNumber *pidNum = NULL;
4715 OSNumber *msgNum = NULL;
4716 const OSSymbol *appname;
4717 const OSSymbol *entryName;
4718 OSObject *entryType;
4719 int i;
4720
4721 if (!pmStatsAppResponses || pmStatsAppResponses->getCount() > 50)
4722 return;
4723
4724 i = 0;
4725 while ((responseDescription = (OSDictionary *) pmStatsAppResponses->getObject(i++)))
4726 {
4727 entryType = responseDescription->getObject(_statsResponseTypeKey);
4728 entryName = (OSSymbol *) responseDescription->getObject(_statsNameKey);
4729 if (entryName && (entryType == response) && entryName->isEqualTo(name))
4730 {
4731 OSNumber * entryValue;
4732 entryValue = (OSNumber *) responseDescription->getObject(_statsTimeMSKey);
4733 if (entryValue && (entryValue->unsigned32BitValue() < delay_ms))
4734 entryValue->setValue(delay_ms);
4735 return;
4736 }
4737 }
4738
4739 responseDescription = OSDictionary::withCapacity(5);
4740 if (responseDescription)
4741 {
4742 if (response) {
4743 responseDescription->setObject(_statsResponseTypeKey, response);
4744 }
4745
4746 if (messageType != 0) {
4747 msgNum = OSNumber::withNumber(messageType, 32);
4748 if (msgNum) {
4749 responseDescription->setObject(_statsMessageTypeKey, msgNum);
4750 msgNum->release();
4751 }
4752 }
4753
4754 if (name && (strlen(name) > 0))
4755 {
4756 appname = OSSymbol::withCString(name);
4757 if (appname) {
4758 responseDescription->setObject(_statsNameKey, appname);
4759 appname->release();
4760 }
4761 }
4762
4763 if (app_pid != -1) {
4764 pidNum = OSNumber::withNumber(app_pid, 32);
4765 if (pidNum) {
4766 responseDescription->setObject(_statsPIDKey, pidNum);
4767 pidNum->release();
4768 }
4769 }
4770
4771 delayNum = OSNumber::withNumber(delay_ms, 32);
4772 if (delayNum) {
4773 responseDescription->setObject(_statsTimeMSKey, delayNum);
4774 delayNum->release();
4775 }
4776
4777 if (pmStatsAppResponses) {
4778 pmStatsAppResponses->setObject(responseDescription);
4779 }
4780
4781 responseDescription->release();
4782 }
4783 return;
4784 }
4785
4786
4787 //******************************************************************************
4788 // TracePoint support
4789 //
4790 //******************************************************************************
4791
4792 #define kIOPMRegisterNVRAMTracePointHandlerKey \
4793 "IOPMRegisterNVRAMTracePointHandler"
4794
4795 IOReturn IOPMrootDomain::callPlatformFunction(
4796 const OSSymbol * functionName,
4797 bool waitForFunction,
4798 void * param1, void * param2,
4799 void * param3, void * param4 )
4800 {
4801 if (pmTracer && functionName &&
4802 functionName->isEqualTo(kIOPMRegisterNVRAMTracePointHandlerKey) &&
4803 !pmTracer->tracePointHandler && !pmTracer->tracePointTarget)
4804 {
4805 uint32_t tracePointPhases, tracePointPCI;
4806 uint64_t statusCode;
4807
4808 pmTracer->tracePointHandler = (IOPMTracePointHandler) param1;
4809 pmTracer->tracePointTarget = (void *) param2;
4810 tracePointPCI = (uint32_t)(uintptr_t) param3;
4811 tracePointPhases = (uint32_t)(uintptr_t) param4;
4812 statusCode = (((uint64_t)tracePointPCI) << 32) | tracePointPhases;
4813 if ((tracePointPhases >> 24) != kIOPMTracePointSystemUp)
4814 {
4815 LOG("Sleep failure code 0x%08x 0x%08x\n",
4816 tracePointPCI, tracePointPhases);
4817 }
4818 setProperty(kIOPMSleepWakeFailureCodeKey, statusCode, 64);
4819 pmTracer->tracePointHandler( pmTracer->tracePointTarget, 0, 0 );
4820
4821 return kIOReturnSuccess;
4822 }
4823
4824 return super::callPlatformFunction(
4825 functionName, waitForFunction, param1, param2, param3, param4);
4826 }
4827
4828 void IOPMrootDomain::tracePoint( uint8_t point )
4829 {
4830 pmTracer->tracePoint(point);
4831 }
4832
4833 //******************************************************************************
4834 // PMTraceWorker Class
4835 //
4836 //******************************************************************************
4837
4838 #undef super
4839 #define super OSObject
4840 OSDefineMetaClassAndStructors(PMTraceWorker, OSObject)
4841
4842 #define kPMBestGuessPCIDevicesCount 25
4843 #define kPMMaxRTCBitfieldSize 32
4844
4845 PMTraceWorker *PMTraceWorker::tracer(IOPMrootDomain *owner)
4846 {
4847 PMTraceWorker *me;
4848
4849 me = OSTypeAlloc( PMTraceWorker );
4850 if (!me || !me->init())
4851 {
4852 return NULL;
4853 }
4854
4855 DLOG("PMTraceWorker %p\n", me);
4856
4857 // Note that we cannot instantiate the PCI device -> bit mappings here, since
4858 // the IODeviceTree has not yet been created by IOPlatformExpert. We create
4859 // this dictionary lazily.
4860 me->owner = owner;
4861 me->pciDeviceBitMappings = NULL;
4862 me->pciMappingLock = IOLockAlloc();
4863 me->tracePhase = kIOPMTracePointSystemUp;
4864 me->loginWindowPhase = 0;
4865 me->pciBusyBitMask = 0;
4866 return me;
4867 }
4868
4869 void PMTraceWorker::RTC_TRACE(void)
4870 {
4871 if (tracePointHandler && tracePointTarget)
4872 {
4873 uint32_t wordA;
4874
4875 wordA = tracePhase; // destined for bits 24-31
4876 wordA <<= 8;
4877 wordA |= loginWindowPhase; // destined for bits 16-23
4878 wordA <<= 16;
4879
4880 tracePointHandler( tracePointTarget, pciBusyBitMask, wordA );
4881 DLOG("RTC_TRACE wrote 0x%08x 0x%08x\n", pciBusyBitMask, wordA);
4882 }
4883 }
4884
4885 int PMTraceWorker::recordTopLevelPCIDevice(IOService * pciDevice)
4886 {
4887 const OSSymbol * deviceName;
4888 int index = -1;
4889
4890 IOLockLock(pciMappingLock);
4891
4892 if (!pciDeviceBitMappings)
4893 {
4894 pciDeviceBitMappings = OSArray::withCapacity(kPMBestGuessPCIDevicesCount);
4895 if (!pciDeviceBitMappings)
4896 goto exit;
4897 }
4898
4899 // Check for bitmask overflow.
4900 if (pciDeviceBitMappings->getCount() >= kPMMaxRTCBitfieldSize)
4901 goto exit;
4902
4903 if ((deviceName = pciDevice->copyName()) &&
4904 (pciDeviceBitMappings->getNextIndexOfObject(deviceName, 0) == (unsigned int)-1) &&
4905 pciDeviceBitMappings->setObject(deviceName))
4906 {
4907 index = pciDeviceBitMappings->getCount() - 1;
4908 DLOG("PMTrace PCI array: set object %s => %d\n",
4909 deviceName->getCStringNoCopy(), index);
4910 }
4911 if (deviceName)
4912 deviceName->release();
4913 if (!addedToRegistry && (index >= 0))
4914 addedToRegistry = owner->setProperty("PCITopLevel", this);
4915
4916 exit:
4917 IOLockUnlock(pciMappingLock);
4918 return index;
4919 }
4920
4921 bool PMTraceWorker::serialize(OSSerialize *s) const
4922 {
4923 bool ok = false;
4924 if (pciDeviceBitMappings)
4925 {
4926 IOLockLock(pciMappingLock);
4927 ok = pciDeviceBitMappings->serialize(s);
4928 IOLockUnlock(pciMappingLock);
4929 }
4930 return ok;
4931 }
4932
4933 void PMTraceWorker::tracePoint(uint8_t phase)
4934 {
4935 tracePhase = phase;
4936
4937 DLOG("IOPMrootDomain: trace point 0x%02x\n", tracePhase);
4938 RTC_TRACE();
4939 }
4940
4941 void PMTraceWorker::traceLoginWindowPhase(uint8_t phase)
4942 {
4943 loginWindowPhase = phase;
4944
4945 DLOG("IOPMrootDomain: loginwindow tracepoint 0x%02x\n", loginWindowPhase);
4946 RTC_TRACE();
4947 }
4948
4949 void PMTraceWorker::tracePCIPowerChange(
4950 change_t type, IOService *service, uint32_t changeFlags, uint32_t bitNum)
4951 {
4952 uint32_t bitMask;
4953 uint32_t expectedFlag;
4954
4955 // Ignore PCI changes outside of system sleep/wake.
4956 if ((kIOPMTracePointSystemSleepDriversPhase != tracePhase) &&
4957 (kIOPMTracePointSystemWakeDriversPhase != tracePhase))
4958 return;
4959
4960 // Only record the WillChange transition when going to sleep,
4961 // and the DidChange on the way up.
4962 changeFlags &= (kIOPMDomainWillChange | kIOPMDomainDidChange);
4963 expectedFlag = (kIOPMTracePointSystemSleepDriversPhase == tracePhase) ?
4964 kIOPMDomainWillChange : kIOPMDomainDidChange;
4965 if (changeFlags != expectedFlag)
4966 return;
4967
4968 // Mark this device off in our bitfield
4969 if (bitNum < kPMMaxRTCBitfieldSize)
4970 {
4971 bitMask = (1 << bitNum);
4972
4973 if (kPowerChangeStart == type)
4974 {
4975 pciBusyBitMask |= bitMask;
4976 DLOG("PMTrace: Device %s started - bit %2d mask 0x%08x => 0x%08x\n",
4977 service->getName(), bitNum, bitMask, pciBusyBitMask);
4978 }
4979 else
4980 {
4981 pciBusyBitMask &= ~bitMask;
4982 DLOG("PMTrace: Device %s finished - bit %2d mask 0x%08x => 0x%08x\n",
4983 service->getName(), bitNum, bitMask, pciBusyBitMask);
4984 }
4985
4986 RTC_TRACE();
4987 }
4988 }
4989
4990
4991 //******************************************************************************
4992 // PMHaltWorker Class
4993 //
4994 //******************************************************************************
4995
4996 static unsigned int gPMHaltBusyCount;
4997 static unsigned int gPMHaltIdleCount;
4998 static int gPMHaltDepth;
4999 static unsigned long gPMHaltEvent;
5000 static IOLock * gPMHaltLock = 0;
5001 static OSArray * gPMHaltArray = 0;
5002 static const OSSymbol * gPMHaltClientAcknowledgeKey = 0;
5003
5004 PMHaltWorker * PMHaltWorker::worker( void )
5005 {
5006 PMHaltWorker * me;
5007 IOThread thread;
5008
5009 do {
5010 me = OSTypeAlloc( PMHaltWorker );
5011 if (!me || !me->init())
5012 break;
5013
5014 me->lock = IOLockAlloc();
5015 if (!me->lock)
5016 break;
5017
5018 DLOG("PMHaltWorker %p\n", me);
5019 me->retain(); // thread holds extra retain
5020 if (KERN_SUCCESS != kernel_thread_start(&PMHaltWorker::main, (void *) me, &thread))
5021 {
5022 me->release();
5023 break;
5024 }
5025 thread_deallocate(thread);
5026 return me;
5027
5028 } while (false);
5029
5030 if (me) me->release();
5031 return 0;
5032 }
5033
5034 void PMHaltWorker::free( void )
5035 {
5036 DLOG("PMHaltWorker free %p\n", this);
5037 if (lock)
5038 {
5039 IOLockFree(lock);
5040 lock = 0;
5041 }
5042 return OSObject::free();
5043 }
5044
5045 void PMHaltWorker::main( void * arg, wait_result_t waitResult )
5046 {
5047 PMHaltWorker * me = (PMHaltWorker *) arg;
5048
5049 IOLockLock( gPMHaltLock );
5050 gPMHaltBusyCount++;
5051 me->depth = gPMHaltDepth;
5052 IOLockUnlock( gPMHaltLock );
5053
5054 while (me->depth >= 0)
5055 {
5056 PMHaltWorker::work( me );
5057
5058 IOLockLock( gPMHaltLock );
5059 if (++gPMHaltIdleCount >= gPMHaltBusyCount)
5060 {
5061 // This is the last thread to finish work on this level,
5062 // inform everyone to start working on next lower level.
5063 gPMHaltDepth--;
5064 me->depth = gPMHaltDepth;
5065 gPMHaltIdleCount = 0;
5066 thread_wakeup((event_t) &gPMHaltIdleCount);
5067 }
5068 else
5069 {
5070 // One or more threads are still working on this level,
5071 // this thread must wait.
5072 me->depth = gPMHaltDepth - 1;
5073 do {
5074 IOLockSleep(gPMHaltLock, &gPMHaltIdleCount, THREAD_UNINT);
5075 } while (me->depth != gPMHaltDepth);
5076 }
5077 IOLockUnlock( gPMHaltLock );
5078 }
5079
5080 // No more work to do, terminate thread
5081 DLOG("All done for worker: %p (visits = %u)\n", me, me->visits);
5082 thread_wakeup( &gPMHaltDepth );
5083 me->release();
5084 }
5085
5086 void PMHaltWorker::work( PMHaltWorker * me )
5087 {
5088 IOService * service;
5089 OSSet * inner;
5090 AbsoluteTime startTime;
5091 UInt32 deltaTime;
5092 bool timeout;
5093
5094 while (true)
5095 {
5096 service = 0;
5097 timeout = false;
5098
5099 // Claim an unit of work from the shared pool
5100 IOLockLock( gPMHaltLock );
5101 inner = (OSSet *)gPMHaltArray->getObject(me->depth);
5102 if (inner)
5103 {
5104 service = (IOService *)inner->getAnyObject();
5105 if (service)
5106 {
5107 service->retain();
5108 inner->removeObject(service);
5109 }
5110 }
5111 IOLockUnlock( gPMHaltLock );
5112 if (!service)
5113 break; // no more work at this depth
5114
5115 clock_get_uptime(&startTime);
5116
5117 if (!service->isInactive() &&
5118 service->setProperty(gPMHaltClientAcknowledgeKey, me))
5119 {
5120 IOLockLock(me->lock);
5121 me->startTime = startTime;
5122 me->service = service;
5123 me->timeout = false;
5124 IOLockUnlock(me->lock);
5125
5126 service->systemWillShutdown( gPMHaltEvent );
5127
5128 // Wait for driver acknowledgement
5129 IOLockLock(me->lock);
5130 while (service->getProperty(gPMHaltClientAcknowledgeKey))
5131 {
5132 IOLockSleep(me->lock, me, THREAD_UNINT);
5133 }
5134 me->service = 0;
5135 timeout = me->timeout;
5136 IOLockUnlock(me->lock);
5137 }
5138
5139 deltaTime = computeDeltaTimeMS(&startTime);
5140 if ((deltaTime > kPMHaltTimeoutMS) || timeout ||
5141 (gIOKitDebug & (kIOLogDebugPower | kIOLogPMRootDomain)))
5142 {
5143 KLOG("%s driver %s (%p) took %u ms\n",
5144 (gPMHaltEvent == kIOMessageSystemWillPowerOff) ?
5145 "PowerOff" : "Restart",
5146 service->getName(), service,
5147 (uint32_t) deltaTime );
5148 }
5149
5150 service->release();
5151 me->visits++;
5152 }
5153 }
5154
5155 void PMHaltWorker::checkTimeout( PMHaltWorker * me, AbsoluteTime * now )
5156 {
5157 UInt64 nano;
5158 AbsoluteTime startTime;
5159 AbsoluteTime endTime;
5160
5161 endTime = *now;
5162
5163 IOLockLock(me->lock);
5164 if (me->service && !me->timeout)
5165 {
5166 startTime = me->startTime;
5167 nano = 0;
5168 if (CMP_ABSOLUTETIME(&endTime, &startTime) > 0)
5169 {
5170 SUB_ABSOLUTETIME(&endTime, &startTime);
5171 absolutetime_to_nanoseconds(endTime, &nano);
5172 }
5173 if (nano > 3000000000ULL)
5174 {
5175 me->timeout = true;
5176 LOG("%s still waiting on %s\n",
5177 (gPMHaltEvent == kIOMessageSystemWillPowerOff) ?
5178 "PowerOff" : "Restart",
5179 me->service->getName());
5180 }
5181 }
5182 IOLockUnlock(me->lock);
5183 }
5184
5185
5186 //******************************************************************************
5187 // acknowledgeSystemWillShutdown
5188 //
5189 // Acknowledgement from drivers that they have prepared for shutdown/restart.
5190 //******************************************************************************
5191
5192 void IOPMrootDomain::acknowledgeSystemWillShutdown( IOService * from )
5193 {
5194 PMHaltWorker * worker;
5195 OSObject * prop;
5196
5197 if (!from)
5198 return;
5199
5200 //DLOG("%s acknowledged\n", from->getName());
5201 prop = from->copyProperty( gPMHaltClientAcknowledgeKey );
5202 if (prop)
5203 {
5204 worker = (PMHaltWorker *) prop;
5205 IOLockLock(worker->lock);
5206 from->removeProperty( gPMHaltClientAcknowledgeKey );
5207 thread_wakeup((event_t) worker);
5208 IOLockUnlock(worker->lock);
5209 worker->release();
5210 }
5211 else
5212 {
5213 DLOG("%s acknowledged without worker property\n",
5214 from->getName());
5215 }
5216 }
5217
5218
5219 //******************************************************************************
5220 // notifySystemShutdown
5221 //
5222 // Notify all objects in PM tree that system will shutdown or restart
5223 //******************************************************************************
5224
5225 static void
5226 notifySystemShutdown( IOService * root, unsigned long event )
5227 {
5228 #define PLACEHOLDER ((OSSet *)gPMHaltArray)
5229 IORegistryIterator * iter;
5230 IORegistryEntry * entry;
5231 IOService * node;
5232 OSSet * inner;
5233 PMHaltWorker * workers[kPMHaltMaxWorkers];
5234 AbsoluteTime deadline;
5235 unsigned int totalNodes = 0;
5236 unsigned int depth;
5237 unsigned int rootDepth;
5238 unsigned int numWorkers;
5239 unsigned int count;
5240 int waitResult;
5241 void * baseFunc;
5242 bool ok;
5243
5244 DLOG("%s event = %lx\n", __FUNCTION__, event);
5245
5246 baseFunc = OSMemberFunctionCast(void *, root, &IOService::systemWillShutdown);
5247
5248 // Iterate the entire PM tree starting from root
5249
5250 rootDepth = root->getDepth( gIOPowerPlane );
5251 if (!rootDepth) goto done;
5252
5253 // debug - for repeated test runs
5254 while (PMHaltWorker::metaClass->getInstanceCount())
5255 IOSleep(1);
5256
5257 if (!gPMHaltArray)
5258 {
5259 gPMHaltArray = OSArray::withCapacity(40);
5260 if (!gPMHaltArray) goto done;
5261 }
5262 else // debug
5263 gPMHaltArray->flushCollection();
5264
5265 if (!gPMHaltLock)
5266 {
5267 gPMHaltLock = IOLockAlloc();
5268 if (!gPMHaltLock) goto done;
5269 }
5270
5271 if (!gPMHaltClientAcknowledgeKey)
5272 {
5273 gPMHaltClientAcknowledgeKey =
5274 OSSymbol::withCStringNoCopy("PMShutdown");
5275 if (!gPMHaltClientAcknowledgeKey) goto done;
5276 }
5277
5278 gPMHaltEvent = event;
5279
5280 // Depth-first walk of PM plane
5281
5282 iter = IORegistryIterator::iterateOver(
5283 root, gIOPowerPlane, kIORegistryIterateRecursively);
5284
5285 if (iter)
5286 {
5287 while ((entry = iter->getNextObject()))
5288 {
5289 node = OSDynamicCast(IOService, entry);
5290 if (!node)
5291 continue;
5292
5293 if (baseFunc ==
5294 OSMemberFunctionCast(void *, node, &IOService::systemWillShutdown))
5295 continue;
5296
5297 depth = node->getDepth( gIOPowerPlane );
5298 if (depth <= rootDepth)
5299 continue;
5300
5301 ok = false;
5302
5303 // adjust to zero based depth
5304 depth -= (rootDepth + 1);
5305
5306 // gPMHaltArray is an array of containers, each container
5307 // refers to nodes with the same depth.
5308
5309 count = gPMHaltArray->getCount();
5310 while (depth >= count)
5311 {
5312 // expand array and insert placeholders
5313 gPMHaltArray->setObject(PLACEHOLDER);
5314 count++;
5315 }
5316 count = gPMHaltArray->getCount();
5317 if (depth < count)
5318 {
5319 inner = (OSSet *)gPMHaltArray->getObject(depth);
5320 if (inner == PLACEHOLDER)
5321 {
5322 inner = OSSet::withCapacity(40);
5323 if (inner)
5324 {
5325 gPMHaltArray->replaceObject(depth, inner);
5326 inner->release();
5327 }
5328 }
5329
5330 // PM nodes that appear more than once in the tree will have
5331 // the same depth, OSSet will refuse to add the node twice.
5332 if (inner)
5333 ok = inner->setObject(node);
5334 }
5335 if (!ok)
5336 DLOG("Skipped PM node %s\n", node->getName());
5337 }
5338 iter->release();
5339 }
5340
5341 // debug only
5342 for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i)); i++)
5343 {
5344 count = 0;
5345 if (inner != PLACEHOLDER)
5346 count = inner->getCount();
5347 DLOG("Nodes at depth %u = %u\n", i, count);
5348 }
5349
5350 // strip placeholders (not all depths are populated)
5351 numWorkers = 0;
5352 for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i)); )
5353 {
5354 if (inner == PLACEHOLDER)
5355 {
5356 gPMHaltArray->removeObject(i);
5357 continue;
5358 }
5359 count = inner->getCount();
5360 if (count > numWorkers)
5361 numWorkers = count;
5362 totalNodes += count;
5363 i++;
5364 }
5365
5366 if (gPMHaltArray->getCount() == 0 || !numWorkers)
5367 goto done;
5368
5369 gPMHaltBusyCount = 0;
5370 gPMHaltIdleCount = 0;
5371 gPMHaltDepth = gPMHaltArray->getCount() - 1;
5372
5373 // Create multiple workers (and threads)
5374
5375 if (numWorkers > kPMHaltMaxWorkers)
5376 numWorkers = kPMHaltMaxWorkers;
5377
5378 DLOG("PM nodes = %u, maxDepth = %u, workers = %u\n",
5379 totalNodes, gPMHaltArray->getCount(), numWorkers);
5380
5381 for (unsigned int i = 0; i < numWorkers; i++)
5382 workers[i] = PMHaltWorker::worker();
5383
5384 // Wait for workers to exhaust all available work
5385
5386 IOLockLock(gPMHaltLock);
5387 while (gPMHaltDepth >= 0)
5388 {
5389 clock_interval_to_deadline(1000, kMillisecondScale, &deadline);
5390
5391 waitResult = IOLockSleepDeadline(
5392 gPMHaltLock, &gPMHaltDepth, deadline, THREAD_UNINT);
5393 if (THREAD_TIMED_OUT == waitResult)
5394 {
5395 AbsoluteTime now;
5396 clock_get_uptime(&now);
5397
5398 IOLockUnlock(gPMHaltLock);
5399 for (unsigned int i = 0 ; i < numWorkers; i++)
5400 {
5401 if (workers[i])
5402 PMHaltWorker::checkTimeout(workers[i], &now);
5403 }
5404 IOLockLock(gPMHaltLock);
5405 }
5406 }
5407 IOLockUnlock(gPMHaltLock);
5408
5409 // Release all workers
5410
5411 for (unsigned int i = 0; i < numWorkers; i++)
5412 {
5413 if (workers[i])
5414 workers[i]->release();
5415 // worker also retained by it's own thread
5416 }
5417
5418 done:
5419 DLOG("%s done\n", __FUNCTION__);
5420 return;
5421 }
5422
5423 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
5424
5425 IOPMDriverAssertionID IOPMrootDomain::createPMAssertion(
5426 IOPMDriverAssertionType whichAssertionBits,
5427 IOPMDriverAssertionLevel assertionLevel,
5428 IOService *ownerService,
5429 const char *ownerDescription)
5430 {
5431 IOReturn ret;
5432 IOPMDriverAssertionID newAssertion;
5433
5434 if (!pmAssertions)
5435 return 0;
5436
5437 ret = pmAssertions->createAssertion(whichAssertionBits, assertionLevel, ownerService, ownerDescription, &newAssertion);
5438
5439 if (kIOReturnSuccess == ret)
5440 return newAssertion;
5441 else
5442 return 0;
5443 }
5444
5445 IOReturn IOPMrootDomain::releasePMAssertion(IOPMDriverAssertionID releaseAssertion)
5446 {
5447 if (!pmAssertions)
5448 return kIOReturnInternalError;
5449
5450 return pmAssertions->releaseAssertion(releaseAssertion);
5451 }
5452
5453 IOReturn IOPMrootDomain::setPMAssertionLevel(
5454 IOPMDriverAssertionID assertionID,
5455 IOPMDriverAssertionLevel assertionLevel)
5456 {
5457 return pmAssertions->setAssertionLevel(assertionID, assertionLevel);
5458 }
5459
5460 IOPMDriverAssertionLevel IOPMrootDomain::getPMAssertionLevel(IOPMDriverAssertionType whichAssertion)
5461 {
5462 IOPMDriverAssertionType sysLevels;
5463
5464 if (!pmAssertions || whichAssertion == 0)
5465 return kIOPMDriverAssertionLevelOff;
5466
5467 sysLevels = pmAssertions->getActivatedAssertions();
5468
5469 // Check that every bit set in argument 'whichAssertion' is asserted
5470 // in the aggregate bits.
5471 if ((sysLevels & whichAssertion) == whichAssertion)
5472 return kIOPMDriverAssertionLevelOn;
5473 else
5474 return kIOPMDriverAssertionLevelOff;
5475 }
5476
5477 IOReturn IOPMrootDomain::setPMAssertionUserLevels(IOPMDriverAssertionType inLevels)
5478 {
5479 if (!pmAssertions)
5480 return kIOReturnNotFound;
5481
5482 return pmAssertions->setUserAssertionLevels(inLevels);
5483 }
5484
5485 bool IOPMrootDomain::serializeProperties( OSSerialize * s ) const
5486 {
5487 if (pmAssertions)
5488 {
5489 pmAssertions->publishProperties();
5490 }
5491 return( IOService::serializeProperties(s) );
5492 }
5493
5494 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
5495
5496
5497 #undef super
5498 #define super OSObject
5499 OSDefineMetaClassAndFinalStructors(PMSettingObject, OSObject)
5500
5501 void PMSettingObject::setPMSetting(const OSSymbol *type, OSObject *obj)
5502 {
5503 (*func)(target, type, obj, refcon);
5504 }
5505
5506 /*
5507 * Static constructor/initializer for PMSettingObject
5508 */
5509 PMSettingObject *PMSettingObject::pmSettingObject(
5510 IOPMrootDomain *parent_arg,
5511 IOPMSettingControllerCallback handler_arg,
5512 OSObject *target_arg,
5513 uintptr_t refcon_arg,
5514 uint32_t supportedPowerSources,
5515 const OSSymbol * settings[])
5516 {
5517 uint32_t objCount = 0;
5518 PMSettingObject *pmso;
5519
5520 if( !parent_arg || !handler_arg || !settings ) return NULL;
5521
5522 // count OSSymbol entries in NULL terminated settings array
5523 while( settings[objCount] ) {
5524 objCount++;
5525 }
5526 if(0 == objCount) return NULL;
5527
5528 pmso = new PMSettingObject;
5529 if(!pmso || !pmso->init()) return NULL;
5530
5531 pmso->parent = parent_arg;
5532 pmso->func = handler_arg;
5533 pmso->target = target_arg;
5534 pmso->refcon = refcon_arg;
5535 pmso->releaseAtCount = objCount + 1; // release when it has count+1 retains
5536
5537 pmso->publishedFeatureID = (uint32_t *)IOMalloc(sizeof(uint32_t)*objCount);
5538 if(pmso->publishedFeatureID) {
5539 for(unsigned int i=0; i<objCount; i++) {
5540 // Since there is now at least one listener to this setting, publish
5541 // PM root domain support for it.
5542 parent_arg->publishFeature( settings[i]->getCStringNoCopy(),
5543 supportedPowerSources, &pmso->publishedFeatureID[i] );
5544 }
5545 }
5546
5547 return pmso;
5548 }
5549
5550 void PMSettingObject::free(void)
5551 {
5552 OSCollectionIterator *settings_iter;
5553 OSSymbol *sym;
5554 OSArray *arr;
5555 int arr_idx;
5556 int i;
5557 int objCount = releaseAtCount - 1;
5558
5559 if(publishedFeatureID) {
5560 for(i=0; i<objCount; i++) {
5561 if(0 != publishedFeatureID[i]) {
5562 parent->removePublishedFeature( publishedFeatureID[i] );
5563 }
5564 }
5565
5566 IOFree(publishedFeatureID, sizeof(uint32_t) * objCount);
5567 }
5568
5569 IORecursiveLockLock(parent->settingsCtrlLock);
5570
5571 // Search each PM settings array in the kernel.
5572 settings_iter = OSCollectionIterator::withCollection(parent->settingsCallbacks);
5573 if(settings_iter)
5574 {
5575 while(( sym = OSDynamicCast(OSSymbol, settings_iter->getNextObject()) ))
5576 {
5577 arr = (OSArray *)parent->settingsCallbacks->getObject(sym);
5578 arr_idx = arr->getNextIndexOfObject(this, 0);
5579 if(-1 != arr_idx) {
5580 // 'this' was found in the array; remove it
5581 arr->removeObject(arr_idx);
5582 }
5583 }
5584
5585 settings_iter->release();
5586 }
5587
5588 IORecursiveLockUnlock(parent->settingsCtrlLock);
5589
5590 super::free();
5591 }
5592
5593 void PMSettingObject::taggedRelease(const void *tag, const int when) const
5594 {
5595 // We have n+1 retains - 1 per array that this PMSettingObject is a member
5596 // of, and 1 retain to ourself. When we get a release with n+1 retains
5597 // remaining, we go ahead and free ourselves, cleaning up array pointers
5598 // in free();
5599
5600 super::taggedRelease(tag, releaseAtCount);
5601 }
5602
5603 // MARK: -
5604 // MARK: PMAssertionsTracker
5605
5606 //*********************************************************************************
5607 //*********************************************************************************
5608 //*********************************************************************************
5609 // class PMAssertionsTracker Implementation
5610
5611 #define kAssertUniqueIDStart 500
5612
5613 PMAssertionsTracker *PMAssertionsTracker::pmAssertionsTracker( IOPMrootDomain *rootDomain )
5614 {
5615 PMAssertionsTracker *myself;
5616
5617 myself = new PMAssertionsTracker;
5618
5619 if (myself) {
5620 myself->init();
5621 myself->owner = rootDomain;
5622 myself->issuingUniqueID = kAssertUniqueIDStart;
5623 myself->assertionsArray = OSArray::withCapacity(5);
5624 myself->assertionsKernel = 0;
5625 myself->assertionsUser = 0;
5626 myself->assertionsCombined = 0;
5627 myself->assertionsArrayLock = IOLockAlloc();
5628 myself->tabulateProducerCount = myself->tabulateConsumerCount = 0;
5629
5630 if (!myself->assertionsArray || !myself->assertionsArrayLock)
5631 myself = NULL;
5632 }
5633
5634 return myself;
5635 }
5636
5637 /* tabulate
5638 * - Update assertionsKernel to reflect the state of all
5639 * assertions in the kernel.
5640 * - Update assertionsCombined to reflect both kernel & user space.
5641 */
5642 void PMAssertionsTracker::tabulate(void)
5643 {
5644 int i;
5645 int count;
5646 PMAssertStruct *_a = NULL;
5647 OSData *_d = NULL;
5648
5649 IOPMDriverAssertionType oldKernel = assertionsKernel;
5650 IOPMDriverAssertionType oldCombined = assertionsCombined;
5651
5652 ASSERT_GATED();
5653
5654 assertionsKernel = 0;
5655 assertionsCombined = 0;
5656
5657 if (!assertionsArray)
5658 return;
5659
5660 if ((count = assertionsArray->getCount()))
5661 {
5662 for (i=0; i<count; i++)
5663 {
5664 _d = OSDynamicCast(OSData, assertionsArray->getObject(i));
5665 if (_d)
5666 {
5667 _a = (PMAssertStruct *)_d->getBytesNoCopy();
5668 if (_a && (kIOPMDriverAssertionLevelOn == _a->level))
5669 assertionsKernel |= _a->assertionBits;
5670 }
5671 }
5672 }
5673
5674 tabulateProducerCount++;
5675 assertionsCombined = assertionsKernel | assertionsUser;
5676
5677 if ((assertionsKernel != oldKernel) ||
5678 (assertionsCombined != oldCombined))
5679 {
5680 owner->messageClients(kIOPMMessageDriverAssertionsChanged);
5681 }
5682 }
5683
5684 void PMAssertionsTracker::publishProperties( void )
5685 {
5686 OSArray *assertionsSummary = NULL;
5687
5688 if (tabulateConsumerCount != tabulateProducerCount)
5689 {
5690 IOLockLock(assertionsArrayLock);
5691
5692 tabulateConsumerCount = tabulateProducerCount;
5693
5694 /* Publish the IOPMrootDomain property "DriverPMAssertionsDetailed"
5695 */
5696 assertionsSummary = copyAssertionsArray();
5697 if (assertionsSummary)
5698 {
5699 owner->setProperty(kIOPMAssertionsDriverDetailedKey, assertionsSummary);
5700 assertionsSummary->release();
5701 }
5702 else
5703 {
5704 owner->removeProperty(kIOPMAssertionsDriverDetailedKey);
5705 }
5706
5707 /* Publish the IOPMrootDomain property "DriverPMAssertions"
5708 */
5709 owner->setProperty(kIOPMAssertionsDriverKey, assertionsKernel, 64);
5710
5711 IOLockUnlock(assertionsArrayLock);
5712 }
5713 }
5714
5715 PMAssertionsTracker::PMAssertStruct *PMAssertionsTracker::detailsForID(IOPMDriverAssertionID _id, int *index)
5716 {
5717 PMAssertStruct *_a = NULL;
5718 OSData *_d = NULL;
5719 int found = -1;
5720 int count = 0;
5721 int i = 0;
5722
5723 if (assertionsArray
5724 && (count = assertionsArray->getCount()))
5725 {
5726 for (i=0; i<count; i++)
5727 {
5728 _d = OSDynamicCast(OSData, assertionsArray->getObject(i));
5729 if (_d)
5730 {
5731 _a = (PMAssertStruct *)_d->getBytesNoCopy();
5732 if (_a && (_id == _a->id)) {
5733 found = i;
5734 break;
5735 }
5736 }
5737 }
5738 }
5739
5740 if (-1 == found) {
5741 return NULL;
5742 } else {
5743 if (index)
5744 *index = found;
5745 return _a;
5746 }
5747 }
5748
5749 /* PMAssertionsTracker::handleCreateAssertion
5750 * Perform assertion work on the PM workloop. Do not call directly.
5751 */
5752 IOReturn PMAssertionsTracker::handleCreateAssertion(OSData *newAssertion)
5753 {
5754 ASSERT_GATED();
5755
5756 if (newAssertion)
5757 {
5758 IOLockLock(assertionsArrayLock);
5759 assertionsArray->setObject(newAssertion);
5760 IOLockUnlock(assertionsArrayLock);
5761 newAssertion->release();
5762
5763 tabulate();
5764 }
5765 return kIOReturnSuccess;
5766 }
5767
5768 /* PMAssertionsTracker::createAssertion
5769 * createAssertion allocates memory for a new PM assertion, and affects system behavior, if
5770 * appropiate.
5771 */
5772 IOReturn PMAssertionsTracker::createAssertion(
5773 IOPMDriverAssertionType which,
5774 IOPMDriverAssertionLevel level,
5775 IOService *serviceID,
5776 const char *whoItIs,
5777 IOPMDriverAssertionID *outID)
5778 {
5779 OSData *dataStore = NULL;
5780 PMAssertStruct track;
5781
5782 // Warning: trillions and trillions of created assertions may overflow the unique ID.
5783 #ifdef __ppc__
5784 track.id = issuingUniqueID++; // FIXME: need OSIncrementAtomic64() for ppc
5785 #else
5786 track.id = OSIncrementAtomic64((SInt64*) &issuingUniqueID);
5787 #endif
5788 track.level = level;
5789 track.assertionBits = which;
5790 track.ownerString = whoItIs ? OSSymbol::withCString(whoItIs) : 0;
5791 track.ownerService = serviceID;
5792 track.modifiedTime = 0;
5793 pmEventTimeStamp(&track.createdTime);
5794
5795 dataStore = OSData::withBytes(&track, sizeof(PMAssertStruct));
5796 if (!dataStore)
5797 {
5798 if (track.ownerString)
5799 track.ownerString->release();
5800 return kIOReturnNoMemory;
5801 }
5802
5803 *outID = track.id;
5804
5805 if (owner && owner->pmPowerStateQueue) {
5806 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionCreate, (void *)dataStore);
5807 }
5808
5809 return kIOReturnSuccess;
5810 }
5811
5812 /* PMAssertionsTracker::handleReleaseAssertion
5813 * Runs in PM workloop. Do not call directly.
5814 */
5815 IOReturn PMAssertionsTracker::handleReleaseAssertion(
5816 IOPMDriverAssertionID _id)
5817 {
5818 ASSERT_GATED();
5819
5820 int index;
5821 PMAssertStruct *assertStruct = detailsForID(_id, &index);
5822
5823 if (!assertStruct)
5824 return kIOReturnNotFound;
5825
5826 IOLockLock(assertionsArrayLock);
5827 if (assertStruct->ownerString)
5828 assertStruct->ownerString->release();
5829
5830 assertionsArray->removeObject(index);
5831 IOLockUnlock(assertionsArrayLock);
5832
5833 tabulate();
5834 return kIOReturnSuccess;
5835 }
5836
5837 /* PMAssertionsTracker::releaseAssertion
5838 * Releases an assertion and affects system behavior if appropiate.
5839 * Actual work happens on PM workloop.
5840 */
5841 IOReturn PMAssertionsTracker::releaseAssertion(
5842 IOPMDriverAssertionID _id)
5843 {
5844 if (owner && owner->pmPowerStateQueue) {
5845 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionRelease, 0, _id);
5846 }
5847 return kIOReturnSuccess;
5848 }
5849
5850 /* PMAssertionsTracker::handleSetAssertionLevel
5851 * Runs in PM workloop. Do not call directly.
5852 */
5853 IOReturn PMAssertionsTracker::handleSetAssertionLevel(
5854 IOPMDriverAssertionID _id,
5855 IOPMDriverAssertionLevel _level)
5856 {
5857 PMAssertStruct *assertStruct = detailsForID(_id, NULL);
5858
5859 ASSERT_GATED();
5860
5861 if (!assertStruct) {
5862 return kIOReturnNotFound;
5863 }
5864
5865 IOLockLock(assertionsArrayLock);
5866 pmEventTimeStamp(&assertStruct->modifiedTime);
5867 assertStruct->level = _level;
5868 IOLockUnlock(assertionsArrayLock);
5869
5870 tabulate();
5871 return kIOReturnSuccess;
5872 }
5873
5874 /* PMAssertionsTracker::setAssertionLevel
5875 */
5876 IOReturn PMAssertionsTracker::setAssertionLevel(
5877 IOPMDriverAssertionID _id,
5878 IOPMDriverAssertionLevel _level)
5879 {
5880 if (owner && owner->pmPowerStateQueue) {
5881 owner->pmPowerStateQueue->submitPowerEvent(kPowerEventAssertionSetLevel,
5882 (void *)_level, _id);
5883 }
5884
5885 return kIOReturnSuccess;
5886 }
5887
5888 IOReturn PMAssertionsTracker::handleSetUserAssertionLevels(void * arg0)
5889 {
5890 IOPMDriverAssertionType new_user_levels = *(IOPMDriverAssertionType *) arg0;
5891
5892 ASSERT_GATED();
5893
5894 if (new_user_levels != assertionsUser)
5895 {
5896 assertionsUser = new_user_levels;
5897 DLOG("assertionsUser 0x%llx\n", assertionsUser);
5898 }
5899
5900 tabulate();
5901 return kIOReturnSuccess;
5902 }
5903
5904 IOReturn PMAssertionsTracker::setUserAssertionLevels(
5905 IOPMDriverAssertionType new_user_levels)
5906 {
5907 if (gIOPMWorkLoop) {
5908 gIOPMWorkLoop->runAction(
5909 OSMemberFunctionCast(
5910 IOWorkLoop::Action,
5911 this,
5912 &PMAssertionsTracker::handleSetUserAssertionLevels),
5913 this,
5914 (void *) &new_user_levels, 0, 0, 0);
5915 }
5916
5917 return kIOReturnSuccess;
5918 }
5919
5920
5921 OSArray *PMAssertionsTracker::copyAssertionsArray(void)
5922 {
5923 int count;
5924 int i;
5925 OSArray *outArray = NULL;
5926
5927 if (!assertionsArray ||
5928 (0 == (count = assertionsArray->getCount())) ||
5929 (NULL == (outArray = OSArray::withCapacity(count))))
5930 {
5931 goto exit;
5932 }
5933
5934 for (i=0; i<count; i++)
5935 {
5936 PMAssertStruct *_a = NULL;
5937 OSData *_d = NULL;
5938 OSDictionary *details = NULL;
5939
5940 _d = OSDynamicCast(OSData, assertionsArray->getObject(i));
5941 if (_d && (_a = (PMAssertStruct *)_d->getBytesNoCopy()))
5942 {
5943 OSNumber *_n = NULL;
5944
5945 details = OSDictionary::withCapacity(7);
5946 if (!details)
5947 continue;
5948
5949 outArray->setObject(details);
5950 details->release();
5951
5952 _n = OSNumber::withNumber(_a->id, 64);
5953 if (_n) {
5954 details->setObject(kIOPMDriverAssertionIDKey, _n);
5955 _n->release();
5956 }
5957 _n = OSNumber::withNumber(_a->createdTime, 64);
5958 if (_n) {
5959 details->setObject(kIOPMDriverAssertionCreatedTimeKey, _n);
5960 _n->release();
5961 }
5962 _n = OSNumber::withNumber(_a->modifiedTime, 64);
5963 if (_n) {
5964 details->setObject(kIOPMDriverAssertionModifiedTimeKey, _n);
5965 _n->release();
5966 }
5967 _n = OSNumber::withNumber((uintptr_t)_a->ownerService, 64);
5968 if (_n) {
5969 details->setObject(kIOPMDriverAssertionOwnerServiceKey, _n);
5970 _n->release();
5971 }
5972 _n = OSNumber::withNumber(_a->level, 64);
5973 if (_n) {
5974 details->setObject(kIOPMDriverAssertionLevelKey, _n);
5975 _n->release();
5976 }
5977 _n = OSNumber::withNumber(_a->assertionBits, 64);
5978 if (_n) {
5979 details->setObject(kIOPMDriverAssertionAssertedKey, _n);
5980 _n->release();
5981 }
5982
5983 if (_a->ownerString) {
5984 details->setObject(kIOPMDriverAssertionOwnerStringKey, _a->ownerString);
5985 }
5986 }
5987 }
5988
5989 exit:
5990 return outArray;
5991 }
5992
5993 IOPMDriverAssertionType PMAssertionsTracker::getActivatedAssertions(void)
5994 {
5995 return assertionsCombined;
5996 }
5997
5998 IOPMDriverAssertionLevel PMAssertionsTracker::getAssertionLevel(
5999 IOPMDriverAssertionType type)
6000 {
6001 if (type && ((type & assertionsKernel) == assertionsKernel))
6002 {
6003 return kIOPMDriverAssertionLevelOn;
6004 } else {
6005 return kIOPMDriverAssertionLevelOff;
6006 }
6007 }
6008
6009 //*********************************************************************************
6010 //*********************************************************************************
6011 //*********************************************************************************
6012
6013 static void pmEventTimeStamp(uint64_t *recordTS)
6014 {
6015 clock_sec_t tsec;
6016 clock_usec_t tusec;
6017
6018 if (!recordTS)
6019 return;
6020
6021 // We assume tsec fits into 32 bits; 32 bits holds enough
6022 // seconds for 136 years since the epoch in 1970.
6023 clock_get_calendar_microtime(&tsec, &tusec);
6024
6025
6026 // Pack the sec & microsec calendar time into a uint64_t, for fun.
6027 *recordTS = 0;
6028 *recordTS |= (uint32_t)tusec;
6029 *recordTS |= ((uint64_t)tsec << 32);
6030
6031 return;
6032 }
6033
6034 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
6035
6036 #undef super
6037 #define super IOService
6038
6039 OSDefineMetaClassAndFinalStructors(IORootParent, IOService)
6040
6041 // This array exactly parallels the state array for the root domain.
6042 // Power state changes initiated by a device can be vetoed by a client of the device, and
6043 // power state changes initiated by the parent of a device cannot be vetoed by a client of the device,
6044 // so when the root domain wants a power state change that cannot be vetoed (e.g. demand sleep), it asks
6045 // its parent to make the change. That is the reason for this complexity.
6046
6047 static IOPMPowerState patriarchPowerStates[NUM_POWER_STATES] =
6048 {
6049 {1,0,0,0,0,0,0,0,0,0,0,0}, // off (not used)
6050 {1,0,RESTART_POWER,0,0,0,0,0,0,0,0,0}, // reset (not used)
6051 {1,0,SLEEP_POWER,0,0,0,0,0,0,0,0,0}, // sleep
6052 {1,0,DOZE_POWER,0,0,0,0,0,0,0,0,0}, // doze
6053 {1,0,ON_POWER,0,0,0,0,0,0,0,0,0}, // running
6054 };
6055
6056 bool IORootParent::start( IOService * nub )
6057 {
6058 mostRecentChange = ON_STATE;
6059 super::start(nub);
6060 attachToParent( getRegistryRoot(), gIOPowerPlane );
6061 PMinit();
6062 registerPowerDriver(this, patriarchPowerStates, NUM_POWER_STATES);
6063 wakeSystem();
6064 powerOverrideOnPriv();
6065 return true;
6066 }
6067
6068 void IORootParent::shutDownSystem( void )
6069 {
6070 }
6071
6072 void IORootParent::restartSystem( void )
6073 {
6074 }
6075
6076 void IORootParent::sleepSystem( void )
6077 {
6078 mostRecentChange = SLEEP_STATE;
6079 changePowerStateToPriv(SLEEP_STATE);
6080 }
6081
6082 void IORootParent::dozeSystem( void )
6083 {
6084 mostRecentChange = DOZE_STATE;
6085 changePowerStateToPriv(DOZE_STATE);
6086 }
6087
6088 // Called in demand sleep when sleep discovered to be impossible after actually attaining that state.
6089 // This brings the parent to doze, which allows the root to step up from sleep to doze.
6090
6091 // In idle sleep, do nothing because the parent is still on and the root can freely change state.
6092
6093 void IORootParent::sleepToDoze( void )
6094 {
6095 if ( mostRecentChange == SLEEP_STATE ) {
6096 changePowerStateToPriv(DOZE_STATE);
6097 }
6098 }
6099
6100 void IORootParent::wakeSystem( void )
6101 {
6102 mostRecentChange = ON_STATE;
6103 changePowerStateToPriv(ON_STATE);
6104 }