]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOPMrootDomain.cpp
xnu-1228.tar.gz
[apple/xnu.git] / iokit / Kernel / IOPMrootDomain.cpp
1 /*
2 * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 #include <IOKit/IOWorkLoop.h>
29 #include <IOKit/IOCommandGate.h>
30 #include <IOKit/IOTimerEventSource.h>
31 #include <IOKit/IOPlatformExpert.h>
32 #include <IOKit/IOKitDebug.h>
33 #include <IOKit/IOTimeStamp.h>
34 #include <IOKit/pwr_mgt/RootDomain.h>
35 #include <IOKit/pwr_mgt/IOPMPrivate.h>
36 #include <IOKit/IODeviceTreeSupport.h>
37 #include <IOKit/IOMessage.h>
38 #include <IOKit/IOReturn.h>
39 #include "RootDomainUserClient.h"
40 #include "IOKit/pwr_mgt/IOPowerConnection.h"
41 #include "IOPMPowerStateQueue.h"
42 #include <IOKit/IOCatalogue.h>
43 #if HIBERNATION
44 #include <IOKit/IOHibernatePrivate.h>
45 #endif
46 #include <sys/syslog.h>
47 #include <sys/sysctl.h>
48 #include <sys/time.h>
49 #include "IOServicePrivate.h" // _IOServiceInterestNotifier
50
51
52 #if __i386__
53 __BEGIN_DECLS
54 #include "IOPMrootDomainInternal.h"
55 __END_DECLS
56 #endif
57
58
59 //#define DEBUG 1
60 #if DEBUG
61 #define DEBUG_LOG(x...) do { kprintf(x); } while (0)
62 #else
63 #define DEBUG_LOG(x...)
64 #endif
65 #define HaltRestartLog(x...) do { kprintf(x); } while (0)
66
67 extern "C" {
68 IOReturn OSMetaClassSystemSleepOrWake( UInt32 );
69 }
70
71 extern const IORegistryPlane * gIOPowerPlane;
72
73 IOReturn broadcast_aggressiveness ( OSObject *, void *, void *, void *, void * );
74 static void sleepTimerExpired(thread_call_param_t);
75 static void wakeupClamshellTimerExpired ( thread_call_param_t us);
76 static void notifySystemShutdown( IOService * root, unsigned long event );
77
78 // "IOPMSetSleepSupported" callPlatformFunction name
79 static const OSSymbol *sleepSupportedPEFunction = NULL;
80
81 #define kIOSleepSupportedKey "IOSleepSupported"
82
83 #define kRD_AllPowerSources (kIOPMSupportedOnAC \
84 | kIOPMSupportedOnBatt \
85 | kIOPMSupportedOnUPS)
86
87 #define number_of_power_states 5
88 #define OFF_STATE 0
89 #define RESTART_STATE 1
90 #define SLEEP_STATE 2
91 #define DOZE_STATE 3
92 #define ON_STATE 4
93
94 #define ON_POWER kIOPMPowerOn
95 #define RESTART_POWER kIOPMRestart
96 #define SLEEP_POWER kIOPMAuxPowerOn
97 #define DOZE_POWER kIOPMDoze
98
99 enum
100 {
101 // not idle around autowake time, secs
102 kAutoWakePreWindow = 45,
103 kAutoWakePostWindow = 15
104 };
105
106
107 #define kLocalEvalClamshellCommand (1 << 15)
108
109 static IOPMPowerState ourPowerStates[number_of_power_states] = {
110 // state 0, off
111 {1,0, 0, 0,0,0,0,0,0,0,0,0},
112 // state 1, restart
113 {1,kIOPMRestartCapability, kIOPMRestart, RESTART_POWER,0,0,0,0,0,0,0,0},
114 // state 2, sleep
115 {1,kIOPMSleepCapability, kIOPMSleep, SLEEP_POWER,0,0,0,0,0,0,0,0},
116 // state 3, doze
117 {1,kIOPMDoze, kIOPMDoze, DOZE_POWER,0,0,0,0,0,0,0,0},
118 // state 4, on
119 {1,kIOPMPowerOn, kIOPMPowerOn, ON_POWER,0,0,0,0,0,0,0,0},
120 };
121
122 static IOPMrootDomain * gRootDomain;
123 static UInt32 gSleepOrShutdownPending = 0;
124
125 struct timeval gIOLastSleepTime;
126 struct timeval gIOLastWakeTime;
127
128 // Constants used as arguments to IOPMrootDomain::informCPUStateChange
129 #define kCPUUnknownIndex 9999999
130 enum {
131 kInformAC = 0,
132 kInformLid = 1,
133 kInformableCount = 2
134 };
135
136 class PMSettingObject : public OSObject
137 {
138 OSDeclareDefaultStructors(PMSettingObject)
139 private:
140 IOPMrootDomain *parent;
141 IOPMSettingControllerCallback func;
142 OSObject *target;
143 uintptr_t refcon;
144 uint32_t *publishedFeatureID;
145 int releaseAtCount;
146 public:
147 static PMSettingObject *pmSettingObject(
148 IOPMrootDomain *parent_arg,
149 IOPMSettingControllerCallback handler_arg,
150 OSObject *target_arg,
151 uintptr_t refcon_arg,
152 uint32_t supportedPowerSources,
153 const OSSymbol *settings[]);
154
155 void setPMSetting(const OSSymbol *type, OSObject *obj);
156
157 void taggedRelease(const void *tag, const int when) const;
158 void free(void);
159 };
160
161 /*
162 * Internal helper object for Shutdown/Restart notifications.
163 */
164 #define kPMHaltMaxWorkers 8
165 #define kPMHaltTimeoutMS 100
166
167 class PMHaltWorker : public OSObject
168 {
169 OSDeclareDefaultStructors( PMHaltWorker )
170
171 public:
172 IOService * service; // service being worked on
173 AbsoluteTime startTime; // time when work started
174 int depth; // work on nubs at this PM-tree depth
175 int visits; // number of nodes visited (debug)
176 IOLock * lock;
177 bool timeout; // service took too long
178
179 static PMHaltWorker * worker( void );
180 static void main( void * arg );
181 static void work( PMHaltWorker * me );
182 static void checkTimeout( PMHaltWorker * me, AbsoluteTime * now );
183 virtual void free( void );
184 };
185
186 OSDefineMetaClassAndStructors( PMHaltWorker, OSObject )
187
188
189 #define super IOService
190 OSDefineMetaClassAndStructors(IOPMrootDomain,IOService)
191
192 extern "C"
193 {
194 IONotifier * registerSleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref)
195 {
196 return gRootDomain->registerInterest( gIOGeneralInterest, handler, self, ref );
197 }
198
199 IONotifier * registerPrioritySleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref)
200 {
201 return gRootDomain->registerInterest( gIOPriorityPowerStateInterest, handler, self, ref );
202 }
203
204 IOReturn acknowledgeSleepWakeNotification(void * PMrefcon)
205 {
206 return gRootDomain->allowPowerChange ( (unsigned long)PMrefcon );
207 }
208
209 IOReturn vetoSleepWakeNotification(void * PMrefcon)
210 {
211 return gRootDomain->cancelPowerChange ( (unsigned long)PMrefcon );
212 }
213
214 IOReturn rootDomainRestart ( void )
215 {
216 return gRootDomain->restartSystem();
217 }
218
219 IOReturn rootDomainShutdown ( void )
220 {
221 return gRootDomain->shutdownSystem();
222 }
223
224 void IOSystemShutdownNotification ( void )
225 {
226 IOCatalogue::disableExternalLinker();
227 for ( int i = 0; i < 100; i++ )
228 {
229 if ( OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending ) ) break;
230 IOSleep( 100 );
231 }
232 }
233
234 int sync_internal(void);
235 }
236
237 /*
238 A device is always in the highest power state which satisfies its driver, its policy-maker, and any power domain
239 children it has, but within the constraint of the power state provided by its parent. The driver expresses its desire by
240 calling changePowerStateTo(), the policy-maker expresses its desire by calling changePowerStateToPriv(), and the children
241 express their desires by calling requestPowerDomainState().
242
243 The Root Power Domain owns the policy for idle and demand sleep and doze for the system. It is a power-managed IOService just
244 like the others in the system. It implements several power states which correspond to what we see as Sleep, Doze, etc.
245
246 The sleep/doze policy is as follows:
247 Sleep and Doze are prevented if the case is open so that nobody will think the machine is off and plug/unplug cards.
248 Sleep and Doze are prevented if the sleep timeout slider in the preferences panel is at zero.
249 The system cannot Sleep, but can Doze if some object in the tree is in a power state marked kIOPMPreventSystemSleep.
250
251 These three conditions are enforced using the "driver clamp" by calling changePowerStateTo(). For example, if the case is
252 opened, changePowerStateTo(ON_STATE) is called to hold the system on regardless of the desires of the children of the root or
253 the state of the other clamp.
254
255 Demand Sleep/Doze is initiated by pressing the front panel power button, closing the clamshell, or selecting the menu item.
256 In this case the root's parent actually initiates the power state change so that the root has no choice and does not give
257 applications the opportunity to veto the change.
258
259 Idle Sleep/Doze occurs if no objects in the tree are in a state marked kIOPMPreventIdleSleep. When this is true, the root's
260 children are not holding the root on, so it sets the "policy-maker clamp" by calling changePowerStateToPriv(ON_STATE)
261 to hold itself on until the sleep timer expires. This timer is set for the difference between the sleep timeout slider and
262 the larger of the display dim timeout slider and the disk spindown timeout slider in the Preferences panel. For example, if
263 the system is set to sleep after thirty idle minutes, and the display and disk are set to sleep after five idle minutes,
264 when there is no longer an object in the tree holding the system out of Idle Sleep (via kIOPMPreventIdleSleep), the root
265 sets its timer for 25 minutes (30 - 5). When the timer expires, it releases its clamp and now nothing is holding it awake,
266 so it falls asleep.
267
268 Demand sleep is prevented when the system is booting. When preferences are transmitted by the loginwindow at the end of
269 boot, a flag is cleared, and this allows subsequent Demand Sleep.
270
271 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
272 a clamp, but sets a flag which is noticed before actually sleeping the kernel. If the flag is set, the root steps up
273 one power state from Sleep to Doze, and any objects in the tree for which this is relevent will act appropriately (USB and
274 ADB will turn on again so that they can wake the system out of Doze (keyboard/mouse activity will cause the Display Wrangler
275 to be tickled)).
276 */
277
278 // **********************************************************************************
279
280 IOPMrootDomain * IOPMrootDomain::construct( void )
281 {
282 IOPMrootDomain *root;
283
284 root = new IOPMrootDomain;
285 if( root)
286 root->init();
287
288 return( root );
289 }
290
291 // **********************************************************************************
292
293 static void disk_sync_callout(thread_call_param_t p0, thread_call_param_t p1)
294 {
295 IOService *rootDomain = (IOService *) p0;
296 unsigned long pmRef = (unsigned long) p1;
297
298 DEBUG_LOG("disk_sync_callout: start\n");
299
300 #if HIBERNATION
301 IOHibernateSystemSleep();
302 #endif
303 sync_internal();
304 rootDomain->allowPowerChange(pmRef);
305 DEBUG_LOG("disk_sync_callout: finish\n");
306 }
307
308 // **********************************************************************************
309
310 static UInt32 computeDeltaTimeMS( const AbsoluteTime * startTime )
311 {
312 AbsoluteTime endTime;
313 UInt64 nano = 0;
314
315 clock_get_uptime(&endTime);
316 if (CMP_ABSOLUTETIME(&endTime, startTime) > 0)
317 {
318 SUB_ABSOLUTETIME(&endTime, startTime);
319 absolutetime_to_nanoseconds(endTime, &nano);
320 }
321
322 return (UInt32)(nano / 1000000ULL);
323 }
324
325 // **********************************************************************************
326 // start
327 //
328 // We don't do much here. The real initialization occurs when the platform
329 // expert informs us we are the root.
330 // **********************************************************************************
331
332 #define kRootDomainSettingsCount 14
333
334 static SYSCTL_STRUCT(_kern, OID_AUTO, sleeptime,
335 CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN,
336 &gIOLastSleepTime, timeval, "");
337
338 static SYSCTL_STRUCT(_kern, OID_AUTO, waketime,
339 CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN,
340 &gIOLastWakeTime, timeval, "");
341
342 static const OSSymbol * gIOPMSettingAutoWakeSecondsKey;
343
344 bool IOPMrootDomain::start ( IOService * nub )
345 {
346 OSIterator *psIterator;
347 OSDictionary *tmpDict;
348
349 gIOPMSettingAutoWakeSecondsKey = OSSymbol::withCString(kIOPMSettingAutoWakeSecondsKey);
350
351 const OSSymbol *settingsArr[kRootDomainSettingsCount] =
352 {
353 OSSymbol::withCString(kIOPMSettingSleepOnPowerButtonKey),
354 gIOPMSettingAutoWakeSecondsKey,
355 OSSymbol::withCString(kIOPMSettingAutoPowerSecondsKey),
356 OSSymbol::withCString(kIOPMSettingAutoWakeCalendarKey),
357 OSSymbol::withCString(kIOPMSettingAutoPowerCalendarKey),
358 OSSymbol::withCString(kIOPMSettingDebugWakeRelativeKey),
359 OSSymbol::withCString(kIOPMSettingDebugPowerRelativeKey),
360 OSSymbol::withCString(kIOPMSettingWakeOnRingKey),
361 OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey),
362 OSSymbol::withCString(kIOPMSettingWakeOnClamshellKey),
363 OSSymbol::withCString(kIOPMSettingWakeOnACChangeKey),
364 OSSymbol::withCString(kIOPMSettingTimeZoneOffsetKey),
365 OSSymbol::withCString(kIOPMSettingDisplaySleepUsesDimKey),
366 OSSymbol::withCString(kIOPMSettingMobileMotionModuleKey)
367 };
368
369
370 pmPowerStateQueue = 0;
371
372 _reserved = (ExpansionData *)IOMalloc(sizeof(ExpansionData));
373 if(!_reserved) return false;
374
375 super::start(nub);
376
377 gRootDomain = this;
378
379 PMinit();
380
381 sleepSupportedPEFunction = OSSymbol::withCString("IOPMSetSleepSupported");
382 canSleep = true;
383 setProperty(kIOSleepSupportedKey,true);
384
385 userDisabledAllSleep = false;
386 allowSleep = true;
387 sleepIsSupported = true;
388 systemBooting = true;
389 sleepSlider = 0;
390 idleSleepPending = false;
391 wrangler = NULL;
392 sleepASAP = false;
393 clamshellIsClosed = false;
394 clamshellExists = false;
395 ignoringClamshell = true;
396 ignoringClamshellDuringWakeup = false;
397 acAdaptorConnect = true;
398
399 idxPMCPUClamshell = kCPUUnknownIndex;
400 idxPMCPULimitedPower = kCPUUnknownIndex;
401
402 tmpDict = OSDictionary::withCapacity(1);
403 setProperty(kRootDomainSupportedFeatures, tmpDict);
404 tmpDict->release();
405
406 settingsCallbacks = OSDictionary::withCapacity(1);
407
408 // Create a list of the valid PM settings that we'll relay to
409 // interested clients in setProperties() => setPMSetting()
410 allowedPMSettings = OSArray::withObjects(
411 (const OSObject **)settingsArr,
412 kRootDomainSettingsCount,
413 0);
414
415 fPMSettingsDict = OSDictionary::withCapacity(5);
416
417 pmPowerStateQueue = IOPMPowerStateQueue::PMPowerStateQueue(this);
418 getPMworkloop()->addEventSource(pmPowerStateQueue);
419
420 featuresDictLock = IOLockAlloc();
421 settingsCtrlLock = IORecursiveLockAlloc();
422
423 extraSleepTimer = thread_call_allocate(
424 (thread_call_func_t)sleepTimerExpired,
425 (thread_call_param_t) this);
426 clamshellWakeupIgnore = thread_call_allocate(
427 (thread_call_func_t)wakeupClamshellTimerExpired,
428 (thread_call_param_t) this);
429 diskSyncCalloutEntry = thread_call_allocate(
430 &disk_sync_callout,
431 (thread_call_param_t) this);
432
433 // create our parent
434 patriarch = new IORootParent;
435 patriarch->init();
436 patriarch->attach(this);
437 patriarch->start(this);
438 patriarch->addPowerChild(this);
439
440 registerPowerDriver(this,ourPowerStates,number_of_power_states);
441
442 setPMRootDomain(this);
443 // set a clamp until we sleep
444 changePowerStateToPriv(ON_STATE);
445
446 // install power change handler
447 registerPrioritySleepWakeInterest( &sysPowerDownHandler, this, 0);
448
449 #if !NO_KERNEL_HID
450 // Register for a notification when IODisplayWrangler is published
451 _displayWranglerNotifier = addNotification(
452 gIOPublishNotification, serviceMatching("IODisplayWrangler"),
453 &displayWranglerPublished, this, 0);
454 #endif
455
456 // Battery location published - ApplePMU support only
457 _batteryPublishNotifier = addNotification(
458 gIOPublishNotification, serviceMatching("IOPMPowerSource"),
459 &batteryPublished, this, this);
460
461
462 const OSSymbol *ucClassName = OSSymbol::withCStringNoCopy("RootDomainUserClient");
463 setProperty(gIOUserClientClassKey, (OSObject *) ucClassName);
464 ucClassName->release();
465
466 // IOBacklightDisplay can take a long time to load at boot, or it may
467 // not load at all if you're booting with clamshell closed. We publish
468 // 'DisplayDims' here redundantly to get it published early and at all.
469 psIterator = getMatchingServices( serviceMatching("IOPMPowerSource") );
470 if( psIterator && psIterator->getNextObject() )
471 {
472 // There's at least one battery on the system, so we publish
473 // 'DisplayDims' support for the LCD.
474 publishFeature("DisplayDims");
475 }
476 if(psIterator) {
477 psIterator->release();
478 }
479
480
481 sysctl_register_oid(&sysctl__kern_sleeptime);
482 sysctl_register_oid(&sysctl__kern_waketime);
483
484 #if HIBERNATION
485 IOHibernateSystemInit(this);
486 #endif
487
488 registerService(); // let clients find us
489
490 return true;
491 }
492
493 // **********************************************************************************
494 // setProperties
495 //
496 // Receive a setProperty call
497 // The "System Boot" property means the system is completely booted.
498 // **********************************************************************************
499 IOReturn IOPMrootDomain::setProperties ( OSObject *props_obj)
500 {
501 IOReturn return_value = kIOReturnSuccess;
502 OSDictionary *dict = OSDynamicCast(OSDictionary, props_obj);
503 OSBoolean *b;
504 OSNumber *n;
505 OSString *str;
506 OSSymbol *type;
507 OSObject *obj;
508 unsigned int i;
509
510 const OSSymbol *boot_complete_string =
511 OSSymbol::withCString("System Boot Complete");
512 const OSSymbol *sys_shutdown_string =
513 OSSymbol::withCString("System Shutdown");
514 const OSSymbol *stall_halt_string =
515 OSSymbol::withCString("StallSystemAtHalt");
516 const OSSymbol *battery_warning_disabled_string =
517 OSSymbol::withCString("BatteryWarningsDisabled");
518 const OSSymbol *idle_seconds_string =
519 OSSymbol::withCString("System Idle Seconds");
520 #if HIBERNATION
521 const OSSymbol *hibernatemode_string =
522 OSSymbol::withCString(kIOHibernateModeKey);
523 const OSSymbol *hibernatefile_string =
524 OSSymbol::withCString(kIOHibernateFileKey);
525 const OSSymbol *hibernatefreeratio_string =
526 OSSymbol::withCString(kIOHibernateFreeRatioKey);
527 const OSSymbol *hibernatefreetime_string =
528 OSSymbol::withCString(kIOHibernateFreeTimeKey);
529 #endif
530 const OSSymbol *sleepdisabled_string =
531 OSSymbol::withCString("SleepDisabled");
532
533 if(!dict)
534 {
535 return_value = kIOReturnBadArgument;
536 goto exit;
537 }
538
539 if ((n = OSDynamicCast(OSNumber, dict->getObject(idle_seconds_string))))
540 {
541 setProperty(idle_seconds_string, n);
542 idleSeconds = n->unsigned32BitValue();
543 }
544
545 if( systemBooting
546 && boot_complete_string
547 && dict->getObject(boot_complete_string))
548 {
549 systemBooting = false;
550 adjustPowerState();
551
552 // If lid is closed, re-send lid closed notification
553 // now that booting is complete.
554 if( clamshellIsClosed )
555 {
556 this->receivePowerNotification(kLocalEvalClamshellCommand);
557 }
558 }
559
560 if( battery_warning_disabled_string
561 && dict->getObject(battery_warning_disabled_string))
562 {
563 setProperty( battery_warning_disabled_string,
564 dict->getObject(battery_warning_disabled_string));
565 }
566
567 if( sys_shutdown_string
568 && (b = OSDynamicCast(OSBoolean, dict->getObject(sys_shutdown_string))))
569 {
570
571 if(kOSBooleanTrue == b)
572 {
573 /* We set systemShutdown = true during shutdown
574 to prevent sleep at unexpected times while loginwindow is trying
575 to shutdown apps and while the OS is trying to transition to
576 complete power of.
577
578 Set to true during shutdown, as soon as loginwindow shows
579 the "shutdown countdown dialog", through individual app
580 termination, and through black screen kernel shutdown.
581 */
582 kprintf("systemShutdown true\n");
583 systemShutdown = true;
584 } else {
585 /*
586 A shutdown was initiated, but then the shutdown
587 was cancelled, clearing systemShutdown to false here.
588 */
589 kprintf("systemShutdown false\n");
590 systemShutdown = false;
591 }
592 }
593
594 if( stall_halt_string
595 && (b = OSDynamicCast(OSBoolean, dict->getObject(stall_halt_string))) )
596 {
597 setProperty(stall_halt_string, b);
598 }
599
600 #if HIBERNATION
601 if ( hibernatemode_string
602 && (n = OSDynamicCast(OSNumber, dict->getObject(hibernatemode_string))))
603 {
604 setProperty(hibernatemode_string, n);
605 }
606 if ( hibernatefreeratio_string
607 && (n = OSDynamicCast(OSNumber, dict->getObject(hibernatefreeratio_string))))
608 {
609 setProperty(hibernatefreeratio_string, n);
610 }
611 if ( hibernatefreetime_string
612 && (n = OSDynamicCast(OSNumber, dict->getObject(hibernatefreetime_string))))
613 {
614 setProperty(hibernatefreetime_string, n);
615 }
616 if ( hibernatefile_string
617 && (str = OSDynamicCast(OSString, dict->getObject(hibernatefile_string))))
618 {
619 setProperty(hibernatefile_string, str);
620 }
621 #endif
622
623 if( sleepdisabled_string
624 && (b = OSDynamicCast(OSBoolean, dict->getObject(sleepdisabled_string))) )
625 {
626 setProperty(sleepdisabled_string, b);
627
628 userDisabledAllSleep = (kOSBooleanTrue == b);
629 }
630
631 // Relay our allowed PM settings onto our registered PM clients
632 for(i = 0; i < allowedPMSettings->getCount(); i++) {
633
634 type = (OSSymbol *)allowedPMSettings->getObject(i);
635 if(!type) continue;
636
637 obj = dict->getObject(type);
638 if(!obj) continue;
639
640 if ((gIOPMSettingAutoWakeSecondsKey == type) && ((n = OSDynamicCast(OSNumber, obj))))
641 {
642 UInt32 rsecs = n->unsigned32BitValue();
643 if (!rsecs)
644 autoWakeStart = autoWakeEnd = 0;
645 else
646 {
647 AbsoluteTime deadline;
648 clock_interval_to_deadline(rsecs + kAutoWakePostWindow, kSecondScale, &deadline);
649 autoWakeEnd = AbsoluteTime_to_scalar(&deadline);
650 if (rsecs > kAutoWakePreWindow)
651 rsecs -= kAutoWakePreWindow;
652 else
653 rsecs = 0;
654 clock_interval_to_deadline(rsecs, kSecondScale, &deadline);
655 autoWakeStart = AbsoluteTime_to_scalar(&deadline);
656 }
657 }
658
659 return_value = setPMSetting(type, obj);
660
661 if(kIOReturnSuccess != return_value) goto exit;
662 }
663
664 exit:
665 if(sleepdisabled_string) sleepdisabled_string->release();
666 if(boot_complete_string) boot_complete_string->release();
667 if(stall_halt_string) stall_halt_string->release();
668 if(idle_seconds_string) idle_seconds_string->release();
669 return return_value;
670 }
671
672
673 //*********************************************************************************
674 // youAreRoot
675 //
676 // Power Managment is informing us that we are the root power domain.
677 // We know we are not the root however, since we have just instantiated a parent
678 // for ourselves and made it the root. We override this method so it will have
679 // no effect
680 //*********************************************************************************
681 IOReturn IOPMrootDomain::youAreRoot ( void )
682 {
683 return IOPMNoErr;
684 }
685
686 // **********************************************************************************
687 // command_received
688 //
689 // No longer used
690 // **********************************************************************************
691 void IOPMrootDomain::command_received ( void * w, void * x, void * y, void * z )
692 {
693 super::command_received(w,x,y,z);
694 }
695
696
697 // **********************************************************************************
698 // broadcast_aggressiveness
699 //
700 // **********************************************************************************
701 IOReturn broadcast_aggressiveness ( OSObject * root, void * x, void * y, void *, void * )
702 {
703 ((IOPMrootDomain *)root)->broadcast_it((unsigned long)x,(unsigned long)y);
704 return IOPMNoErr;
705 }
706
707
708 // **********************************************************************************
709 // broadcast_it
710 //
711 // We are behind the command gate to broadcast an aggressiveness factor. We let the
712 // superclass do it, but we need to snoop on factors that affect idle sleep.
713 // **********************************************************************************
714 void IOPMrootDomain::broadcast_it (unsigned long type, unsigned long value)
715 {
716 super::setAggressiveness(type,value);
717
718 // Save user's spin down timer to restore after we replace it for idle sleep
719 if( type == kPMMinutesToSpinDown ) user_spindown = value;
720
721 // Use longestNonSleepSlider to calculate dimming adjust idle sleep timer
722 if (getAggressiveness(kPMMinutesToDim, (unsigned long *)&longestNonSleepSlider)
723 != kIOReturnSuccess)
724 longestNonSleepSlider = 0;
725
726 if ( type == kPMMinutesToSleep ) {
727 DEBUG_LOG("PM idle time -> %ld secs (ena %d)\n", idleSeconds, (value != 0));
728 if (0x7fffffff == value)
729 value = idleSeconds;
730
731 if ( (sleepSlider == 0) && (value != 0) ) {
732 if (!wrangler)
733 {
734 sleepASAP = false;
735 changePowerStateToPriv(ON_STATE);
736 if (idleSeconds)
737 {
738 AbsoluteTime deadline;
739 // stay awake for at least idleSeconds
740 clock_interval_to_deadline(idleSeconds, kSecondScale, &deadline);
741 thread_call_enter_delayed(extraSleepTimer, deadline);
742 // this gets turned off when we sleep again
743 idleSleepPending = true;
744 }
745 }
746 else
747 {
748 // If sleepASAP is already set, then calling adjustPowerState() here
749 // will put the system to sleep immediately which is bad. Note that
750 // this aggressiveness change can occur without waking up the display
751 // by (dis)connecting the AC adapter. To get around this, the power
752 // clamp is restore to ON state then dropped after waiting for the
753 // sleep timer to expire.
754
755 if (sleepASAP)
756 {
757 AbsoluteTime deadline;
758 // stay awake for at least sleepSlider minutes
759 clock_interval_to_deadline(value * 60, kSecondScale, &deadline);
760 thread_call_enter_delayed(extraSleepTimer, deadline);
761 // this gets turned off when we sleep again
762 idleSleepPending = true;
763 sleepASAP = false;
764 }
765 }
766 }
767 sleepSlider = value;
768 if ( sleepSlider == 0 ) {
769 // idle sleep is now disabled
770 adjustPowerState();
771 // make sure we're powered
772 patriarch->wakeSystem();
773 }
774 }
775 if ( sleepSlider > longestNonSleepSlider ) {
776 extraSleepDelay = sleepSlider - longestNonSleepSlider ;
777 }
778 else {
779 extraSleepDelay = 0;
780 }
781 }
782
783
784 // **********************************************************************************
785 // sleepTimerExpired
786 //
787 // **********************************************************************************
788 static void sleepTimerExpired ( thread_call_param_t us)
789 {
790 ((IOPMrootDomain *)us)->handleSleepTimerExpiration();
791 }
792
793
794 static void wakeupClamshellTimerExpired ( thread_call_param_t us)
795 {
796 ((IOPMrootDomain *)us)->stopIgnoringClamshellEventsDuringWakeup();
797 }
798
799
800 // **********************************************************************************
801 // handleSleepTimerExpiration
802 //
803 // The time between the sleep idle timeout and the next longest one has elapsed.
804 // It's time to sleep. Start that by removing the clamp that's holding us awake.
805 // **********************************************************************************
806 void IOPMrootDomain::handleSleepTimerExpiration ( void )
807 {
808 DEBUG_LOG("SleepTimerExpired\n");
809
810 AbsoluteTime time;
811
812 clock_get_uptime(&time);
813 if ((AbsoluteTime_to_scalar(&time) > autoWakeStart) && (AbsoluteTime_to_scalar(&time) < autoWakeEnd))
814 {
815 thread_call_enter_delayed(extraSleepTimer, *((AbsoluteTime *) &autoWakeEnd));
816 return;
817 }
818
819 // accelerate disk spin down if spin down timer is non-zero (zero = never spin down)
820 if(0 != user_spindown)
821 setQuickSpinDownTimeout();
822
823 sleepASAP = true;
824 adjustPowerState();
825 }
826
827
828 void IOPMrootDomain::stopIgnoringClamshellEventsDuringWakeup(void)
829 {
830 // Allow clamshell-induced sleep now
831 ignoringClamshellDuringWakeup = false;
832
833 // Re-send clamshell event, in case it causes a sleep
834 if(clamshellIsClosed)
835 this->receivePowerNotification( kLocalEvalClamshellCommand );
836 }
837
838 //*********************************************************************************
839 // setAggressiveness
840 //
841 // Some aggressiveness factor has changed. We broadcast it to the hierarchy while on
842 // the Power Mangement workloop thread. This enables objects in the
843 // hierarchy to successfully alter their idle timers, which are all on the
844 // same thread.
845 //*********************************************************************************
846
847 IOReturn IOPMrootDomain::setAggressiveness ( unsigned long type, unsigned long newLevel )
848 {
849 IOWorkLoop * pmWorkLoop = getPMworkloop();
850 if (pmWorkLoop)
851 pmWorkLoop->runAction(broadcast_aggressiveness,this,(void *)type,(void *)newLevel);
852
853 return kIOReturnSuccess;
854 }
855
856
857 // **********************************************************************************
858 // sleepSystem
859 //
860 // **********************************************************************************
861 /* public */
862 IOReturn IOPMrootDomain::sleepSystem ( void )
863 {
864 return sleepSystemOptions (NULL);
865 }
866
867 /* private */
868 IOReturn IOPMrootDomain::sleepSystemOptions ( OSDictionary *options )
869 {
870 /* sleepSystem is a public function, and may be called by any kernel driver.
871 * And that's bad - drivers should sleep the system by calling
872 * receivePowerNotification() instead. Drivers should not use sleepSystem.
873 *
874 * Note that user space app calls to IOPMSleepSystem() will also travel
875 * this code path and thus be correctly identified as software sleeps.
876 */
877
878 if (options && options->getObject("OSSwitch"))
879 {
880
881 // Log specific sleep cause for OS Switch hibernation
882 return privateSleepSystem( kIOPMOSSwitchHibernationKey) ;
883
884 } else {
885
886 return privateSleepSystem( kIOPMSoftwareSleepKey);
887
888 }
889 }
890
891 /* private */
892 IOReturn IOPMrootDomain::privateSleepSystem ( const char *sleepReason )
893 {
894 // Record sleep cause in IORegistry
895 if (sleepReason) {
896 setProperty(kRootDomainSleepReasonKey, sleepReason);
897 }
898
899 if(systemShutdown) {
900 kprintf("Preventing system sleep on grounds of systemShutdown.\n");
901 }
902
903 if( userDisabledAllSleep )
904 {
905 /* Prevent sleep of all kinds if directed to by user space */
906 return kIOReturnNotPermitted;
907 }
908
909 if ( !systemBooting
910 && !systemShutdown
911 && allowSleep)
912 {
913 if ( !sleepIsSupported ) {
914 setSleepSupported( kPCICantSleep );
915 kprintf("Sleep prevented by kIOPMPreventSystemSleep flag\n");
916 }
917 patriarch->sleepSystem();
918 return kIOReturnSuccess;
919 } else {
920 // Unable to sleep because system is in the process of booting or shutting down,
921 // or sleep has otherwise been disallowed.
922 return kIOReturnError;
923 }
924 }
925
926
927 // **********************************************************************************
928 // shutdownSystem
929 //
930 // **********************************************************************************
931 IOReturn IOPMrootDomain::shutdownSystem ( void )
932 {
933 //patriarch->shutDownSystem();
934 return kIOReturnUnsupported;
935 }
936
937
938 // **********************************************************************************
939 // restartSystem
940 //
941 // **********************************************************************************
942 IOReturn IOPMrootDomain::restartSystem ( void )
943 {
944 //patriarch->restartSystem();
945 return kIOReturnUnsupported;
946 }
947
948
949 // **********************************************************************************
950 // powerChangeDone
951 //
952 // This overrides powerChangeDone in IOService.
953 //
954 // Finder sleep and idle sleep move us from the ON state to the SLEEP_STATE.
955 // In this case:
956 // If we just finished going to the SLEEP_STATE, and the platform is capable of true sleep,
957 // sleep the kernel. Otherwise switch up to the DOZE_STATE which will keep almost
958 // everything as off as it can get.
959 //
960 // **********************************************************************************
961 void IOPMrootDomain::powerChangeDone ( unsigned long previousState )
962 {
963 OSNumber * propertyPtr;
964 unsigned short theProperty;
965 AbsoluteTime deadline;
966
967 DEBUG_LOG("PowerChangeDone: %ld -> %ld\n", previousState, getPowerState());
968
969 switch ( getPowerState() ) {
970 case SLEEP_STATE:
971 if ( previousState != ON_STATE )
972 break;
973
974 if ( canSleep && sleepIsSupported )
975 {
976 // re-enable this timer for next sleep
977 idleSleepPending = false;
978
979 uint32_t secs, microsecs;
980 clock_get_calendar_microtime(&secs, &microsecs);
981 logtime(secs);
982 gIOLastSleepTime.tv_sec = secs;
983 gIOLastSleepTime.tv_usec = microsecs;
984
985 #if HIBERNATION
986 IOLog("System %sSleep\n", gIOHibernateState ? "Safe" : "");
987
988 IOHibernateSystemHasSlept();
989 #else
990 IOLog("System Sleep\n");
991 #endif
992
993 getPlatform()->sleepKernel();
994
995 // The CPU(s) are off at this point. When they're awakened by CPU interrupt,
996 // code will resume execution here.
997
998 // Now we're waking...
999 #if HIBERNATION
1000 IOHibernateSystemWake();
1001 #endif
1002
1003 // stay awake for at least 30 seconds
1004 clock_interval_to_deadline(30, kSecondScale, &deadline);
1005 thread_call_enter_delayed(extraSleepTimer, deadline);
1006 // this gets turned off when we sleep again
1007 idleSleepPending = true;
1008
1009 // Ignore closed clamshell during wakeup and for a few seconds
1010 // after wakeup is complete
1011 ignoringClamshellDuringWakeup = true;
1012
1013 // sleep transition complete
1014 gSleepOrShutdownPending = 0;
1015
1016 // trip the reset of the calendar clock
1017 clock_wakeup_calendar();
1018
1019 // get us some power
1020 patriarch->wakeSystem();
1021
1022 // early stage wake notification
1023 tellClients(kIOMessageSystemWillPowerOn);
1024
1025 // tell the tree we're waking
1026 #if HIBERNATION
1027 IOLog("System %sWake\n", gIOHibernateState ? "SafeSleep " : "");
1028 #endif
1029 systemWake();
1030
1031 // Allow drivers to request extra processing time before clamshell
1032 // sleep if kIOREMSleepEnabledKey is present.
1033 // Ignore clamshell events for at least 5 seconds
1034 if(getProperty(kIOREMSleepEnabledKey)) {
1035 // clamshellWakeupIgnore callout clears ignoreClamshellDuringWakeup bit
1036 clock_interval_to_deadline(5, kSecondScale, &deadline);
1037 if(clamshellWakeupIgnore) {
1038 thread_call_enter_delayed(clamshellWakeupIgnore, deadline);
1039 }
1040 } else ignoringClamshellDuringWakeup = false;
1041
1042 // Find out what woke us
1043 propertyPtr = OSDynamicCast(OSNumber,getProperty("WakeEvent"));
1044 if ( propertyPtr ) {
1045 theProperty = propertyPtr->unsigned16BitValue();
1046 IOLog("Wake event %04x\n",theProperty);
1047 if ( (theProperty & 0x0008) || //lid
1048 (theProperty & 0x0800) || // front panel button
1049 (theProperty & 0x0020) || // external keyboard
1050 (theProperty & 0x0001) ) { // internal keyboard
1051 // We've identified the wakeup event as UI driven
1052 reportUserInput();
1053 }
1054 } else {
1055 // Since we can't identify the wakeup event, treat it as UI activity
1056 reportUserInput();
1057 }
1058
1059 // Wake for thirty seconds
1060 changePowerStateToPriv(ON_STATE);
1061 } else {
1062 // allow us to step up a power state
1063 patriarch->sleepToDoze();
1064
1065 // ignore children's request for higher power during doze.
1066 powerOverrideOnPriv();
1067 changePowerStateToPriv(DOZE_STATE);
1068 }
1069 break;
1070
1071 case DOZE_STATE:
1072 if ( previousState != DOZE_STATE )
1073 {
1074 IOLog("System Doze\n");
1075 }
1076 // re-enable this timer for next sleep
1077 idleSleepPending = false;
1078 gSleepOrShutdownPending = 0;
1079 break;
1080
1081 case RESTART_STATE:
1082 IOLog("System Restart\n");
1083 PEHaltRestart(kPERestartCPU);
1084 break;
1085
1086 case OFF_STATE:
1087 IOLog("System Halt\n");
1088 PEHaltRestart(kPEHaltCPU);
1089 break;
1090 }
1091 }
1092
1093
1094 // **********************************************************************************
1095 // wakeFromDoze
1096 //
1097 // The Display Wrangler calls here when it switches to its highest state. If the
1098 // system is currently dozing, allow it to wake by making sure the parent is
1099 // providing power.
1100 // **********************************************************************************
1101 void IOPMrootDomain::wakeFromDoze( void )
1102 {
1103 if ( getPowerState() == DOZE_STATE )
1104 {
1105 // Reset sleep support till next sleep attempt.
1106 // A machine's support of sleep vs. doze can change over the course of
1107 // a running system, so we recalculate it before every sleep.
1108 setSleepSupported(0);
1109
1110 changePowerStateToPriv(ON_STATE);
1111 powerOverrideOffPriv();
1112
1113 // early wake notification
1114 tellClients(kIOMessageSystemWillPowerOn);
1115
1116 // allow us to wake if children so desire
1117 patriarch->wakeSystem();
1118 }
1119 }
1120
1121
1122 // *****************************************************************************
1123 // publishFeature
1124 //
1125 // Adds a new feature to the supported features dictionary
1126 //
1127 //
1128 // *****************************************************************************
1129 void IOPMrootDomain::publishFeature( const char * feature )
1130 {
1131 publishFeature(feature, kIOPMSupportedOnAC
1132 | kIOPMSupportedOnBatt
1133 | kIOPMSupportedOnUPS,
1134 NULL);
1135 return;
1136 }
1137
1138
1139 // *****************************************************************************
1140 // publishFeature (with supported power source specified)
1141 //
1142 // Adds a new feature to the supported features dictionary
1143 //
1144 //
1145 // *****************************************************************************
1146 void IOPMrootDomain::publishFeature(
1147 const char *feature,
1148 uint32_t supportedWhere,
1149 uint32_t *uniqueFeatureID)
1150 {
1151 static uint16_t next_feature_id = 500;
1152
1153 OSNumber *new_feature_data = NULL;
1154 OSNumber *existing_feature = NULL;
1155 OSArray *existing_feature_arr = NULL;
1156 OSObject *osObj = NULL;
1157 uint32_t feature_value = 0;
1158
1159 supportedWhere &= kRD_AllPowerSources; // mask off any craziness!
1160
1161 // kprintf("IOPMrootDomain::publishFeature [\"%s\":%0x01x]\n", feature, supportedWhere);
1162
1163 if(!supportedWhere) {
1164 // Feature isn't supported anywhere!
1165 return;
1166 }
1167
1168 if(next_feature_id > 5000) {
1169 // Far, far too many features!
1170 return;
1171 }
1172
1173 if(featuresDictLock) IOLockLock(featuresDictLock);
1174
1175 OSDictionary *features =
1176 (OSDictionary *) getProperty(kRootDomainSupportedFeatures);
1177
1178 // Create new features dict if necessary
1179 if ( features && OSDynamicCast(OSDictionary, features)) {
1180 features = OSDictionary::withDictionary(features);
1181 } else {
1182 features = OSDictionary::withCapacity(1);
1183 }
1184
1185 // Create OSNumber to track new feature
1186
1187 next_feature_id += 1;
1188 if( uniqueFeatureID ) {
1189 // We don't really mind if the calling kext didn't give us a place
1190 // to stash their unique id. Many kexts don't plan to unload, and thus
1191 // have no need to remove themselves later.
1192 *uniqueFeatureID = next_feature_id;
1193 }
1194
1195 feature_value = supportedWhere + (next_feature_id << 16);
1196 new_feature_data = OSNumber::withNumber(
1197 (unsigned long long)feature_value, 32);
1198
1199 // Does features object already exist?
1200 if( (osObj = features->getObject(feature)) )
1201 {
1202 if(( existing_feature = OSDynamicCast(OSNumber, osObj) ))
1203 {
1204 // We need to create an OSArray to hold the now 2 elements.
1205 existing_feature_arr = OSArray::withObjects(
1206 (const OSObject **)&existing_feature, 1, 2);
1207 existing_feature_arr->setObject(new_feature_data);
1208 features->setObject(feature, existing_feature_arr);
1209 } else if(( existing_feature_arr = OSDynamicCast(OSArray, osObj) ))
1210 {
1211 // Add object to existing array
1212 existing_feature_arr->setObject(new_feature_data);
1213 }
1214 } else {
1215 // The easy case: no previously existing features listed. We simply
1216 // set the OSNumber at key 'feature' and we're on our way.
1217 features->setObject(feature, new_feature_data);
1218 }
1219
1220 new_feature_data->release();
1221
1222 setProperty(kRootDomainSupportedFeatures, features);
1223
1224 features->release();
1225
1226 if(featuresDictLock) IOLockUnlock(featuresDictLock);
1227
1228 // Notify EnergySaver and all those in user space so they might
1229 // re-populate their feature specific UI
1230 if(pmPowerStateQueue) {
1231 pmPowerStateQueue->featureChangeOccurred(
1232 kIOPMMessageFeatureChange, this);
1233 }
1234 }
1235
1236 // *****************************************************************************
1237 // removePublishedFeature
1238 //
1239 // Removes previously published feature
1240 //
1241 //
1242 // *****************************************************************************
1243 IOReturn IOPMrootDomain::removePublishedFeature( uint32_t removeFeatureID )
1244 {
1245 IOReturn ret = kIOReturnError;
1246 uint32_t feature_value = 0;
1247 uint16_t feature_id = 0;
1248 bool madeAChange = false;
1249
1250 OSSymbol *dictKey = NULL;
1251 OSCollectionIterator *dictIterator = NULL;
1252 OSArray *arrayMember = NULL;
1253 OSNumber *numberMember = NULL;
1254 OSObject *osObj = NULL;
1255 OSNumber *osNum = NULL;
1256
1257 if(featuresDictLock) IOLockLock(featuresDictLock);
1258
1259 OSDictionary *features =
1260 (OSDictionary *) getProperty(kRootDomainSupportedFeatures);
1261
1262 if ( features && OSDynamicCast(OSDictionary, features) )
1263 {
1264 // Any modifications to the dictionary are made to the copy to prevent
1265 // races & crashes with userland clients. Dictionary updated
1266 // automically later.
1267 features = OSDictionary::withDictionary(features);
1268 } else {
1269 features = NULL;
1270 ret = kIOReturnNotFound;
1271 goto exit;
1272 }
1273
1274 // We iterate 'features' dictionary looking for an entry tagged
1275 // with 'removeFeatureID'. If found, we remove it from our tracking
1276 // structures and notify the OS via a general interest message.
1277
1278 dictIterator = OSCollectionIterator::withCollection(features);
1279 if(!dictIterator) {
1280 goto exit;
1281 }
1282
1283 while( (dictKey = OSDynamicCast(OSSymbol, dictIterator->getNextObject())) )
1284 {
1285 osObj = features->getObject(dictKey);
1286
1287 // Each Feature is either tracked by an OSNumber
1288 if( osObj && (numberMember = OSDynamicCast(OSNumber, osObj)) )
1289 {
1290 feature_value = numberMember->unsigned32BitValue();
1291 feature_id = (uint16_t)(feature_value >> 16);
1292
1293 if( feature_id == (uint16_t)removeFeatureID )
1294 {
1295 // Remove this node
1296 features->removeObject(dictKey);
1297 madeAChange = true;
1298 break;
1299 }
1300
1301 // Or tracked by an OSArray of OSNumbers
1302 } else if( osObj && (arrayMember = OSDynamicCast(OSArray, osObj)) )
1303 {
1304 unsigned int arrayCount = arrayMember->getCount();
1305
1306 for(unsigned int i=0; i<arrayCount; i++)
1307 {
1308 osNum = OSDynamicCast(OSNumber, arrayMember->getObject(i));
1309 if(!osNum) {
1310 continue;
1311 }
1312
1313 feature_value = osNum->unsigned32BitValue();
1314 feature_id = (uint16_t)(feature_value >> 16);
1315
1316 if( feature_id == (uint16_t)removeFeatureID )
1317 {
1318 // Remove this node
1319 if( 1 == arrayCount ) {
1320 // If the array only contains one element, remove
1321 // the whole thing.
1322 features->removeObject(dictKey);
1323 } else {
1324 // Otherwise just remove the element in question.
1325 arrayMember->removeObject(i);
1326 }
1327
1328 madeAChange = true;
1329 break;
1330 }
1331 }
1332 }
1333 }
1334
1335
1336 dictIterator->release();
1337
1338 if( madeAChange )
1339 {
1340 ret = kIOReturnSuccess;
1341
1342 setProperty(kRootDomainSupportedFeatures, features);
1343
1344 // Notify EnergySaver and all those in user space so they might
1345 // re-populate their feature specific UI
1346 if(pmPowerStateQueue) {
1347 pmPowerStateQueue->featureChangeOccurred(
1348 kIOPMMessageFeatureChange, this);
1349 }
1350 } else {
1351 ret = kIOReturnNotFound;
1352 }
1353
1354 exit:
1355 if(features) features->release();
1356 if(featuresDictLock) IOLockUnlock(featuresDictLock);
1357 return ret;
1358 }
1359
1360
1361 // **********************************************************************************
1362 // unIdleDevice
1363 //
1364 // Enqueues unidle event to be performed later in a serialized context.
1365 //
1366 // **********************************************************************************
1367 void IOPMrootDomain::unIdleDevice( IOService *theDevice, unsigned long theState )
1368 {
1369 if(pmPowerStateQueue)
1370 pmPowerStateQueue->unIdleOccurred(theDevice, theState);
1371 }
1372
1373 // **********************************************************************************
1374 // announcePowerSourceChange
1375 //
1376 // Notifies "interested parties" that the batteries have changed state
1377 //
1378 // **********************************************************************************
1379 void IOPMrootDomain::announcePowerSourceChange( void )
1380 {
1381 IORegistryEntry *_batteryRegEntry = (IORegistryEntry *) getProperty("BatteryEntry");
1382
1383 // (if possible) re-publish power source state under IOPMrootDomain;
1384 // only do so if the battery controller publishes an IOResource
1385 // defining battery location. Called from ApplePMU battery driver.
1386
1387 if(_batteryRegEntry)
1388 {
1389 OSArray *batt_info;
1390 batt_info = (OSArray *) _batteryRegEntry->getProperty(kIOBatteryInfoKey);
1391 if(batt_info)
1392 setProperty(kIOBatteryInfoKey, batt_info);
1393 }
1394
1395 }
1396
1397
1398 // *****************************************************************************
1399 // setPMSetting (private)
1400 //
1401 // Internal helper to relay PM settings changes from user space to individual
1402 // drivers. Should be called only by IOPMrootDomain::setProperties.
1403 //
1404 // *****************************************************************************
1405 IOReturn IOPMrootDomain::setPMSetting(
1406 const OSSymbol *type,
1407 OSObject *obj)
1408 {
1409 OSArray *arr = NULL;
1410 PMSettingObject *p_obj = NULL;
1411 int count;
1412 int i;
1413
1414 if(NULL == type) return kIOReturnBadArgument;
1415
1416 IORecursiveLockLock(settingsCtrlLock);
1417
1418 fPMSettingsDict->setObject(type, obj);
1419
1420 arr = (OSArray *)settingsCallbacks->getObject(type);
1421 if(NULL == arr) goto exit;
1422 count = arr->getCount();
1423 for(i=0; i<count; i++) {
1424 p_obj = (PMSettingObject *)OSDynamicCast(PMSettingObject, arr->getObject(i));
1425 if(p_obj) p_obj->setPMSetting(type, obj);
1426 }
1427
1428 exit:
1429 IORecursiveLockUnlock(settingsCtrlLock);
1430 return kIOReturnSuccess;
1431 }
1432
1433 // *****************************************************************************
1434 // copyPMSetting (public)
1435 //
1436 // Allows kexts to safely read setting values, without being subscribed to
1437 // notifications.
1438 //
1439 // *****************************************************************************
1440 OSObject * IOPMrootDomain::copyPMSetting(
1441 OSSymbol *whichSetting)
1442 {
1443 OSObject *obj = NULL;
1444
1445 if(!whichSetting) return NULL;
1446
1447 IORecursiveLockLock(settingsCtrlLock);
1448 obj = fPMSettingsDict->getObject(whichSetting);
1449 if(obj) {
1450 obj->retain();
1451 }
1452 IORecursiveLockUnlock(settingsCtrlLock);
1453
1454 return obj;
1455 }
1456
1457 // *****************************************************************************
1458 // registerPMSettingController (public)
1459 //
1460 // direct wrapper to registerPMSettingController with uint32_t power source arg
1461 // *****************************************************************************
1462 IOReturn IOPMrootDomain::registerPMSettingController(
1463 const OSSymbol * settings[],
1464 IOPMSettingControllerCallback func,
1465 OSObject *target,
1466 uintptr_t refcon,
1467 OSObject **handle)
1468 {
1469 return registerPMSettingController(
1470 settings,
1471 (kIOPMSupportedOnAC | kIOPMSupportedOnBatt | kIOPMSupportedOnUPS),
1472 func, target, refcon, handle);
1473 }
1474
1475 // *****************************************************************************
1476 // registerPMSettingController (public)
1477 //
1478 // Kexts may register for notifications when a particular setting is changed.
1479 // A list of settings is available in IOPM.h.
1480 // Arguments:
1481 // * settings - An OSArray containing OSSymbols. Caller should populate this
1482 // array with a list of settings caller wants notifications from.
1483 // * func - A C function callback of the type IOPMSettingControllerCallback
1484 // * target - caller may provide an OSObject *, which PM will pass as an
1485 // target to calls to "func"
1486 // * refcon - caller may provide an void *, which PM will pass as an
1487 // argument to calls to "func"
1488 // * handle - This is a return argument. We will populate this pointer upon
1489 // call success. Hold onto this and pass this argument to
1490 // IOPMrootDomain::deRegisterPMSettingCallback when unloading your kext
1491 // Returns:
1492 // kIOReturnSuccess on success
1493 // *****************************************************************************
1494 IOReturn IOPMrootDomain::registerPMSettingController(
1495 const OSSymbol * settings[],
1496 uint32_t supportedPowerSources,
1497 IOPMSettingControllerCallback func,
1498 OSObject *target,
1499 uintptr_t refcon,
1500 OSObject **handle)
1501 {
1502 PMSettingObject *pmso = NULL;
1503 OSArray *list = NULL;
1504 IOReturn ret = kIOReturnSuccess;
1505 int i;
1506
1507 if( NULL == settings ||
1508 NULL == func ||
1509 NULL == handle)
1510 {
1511 return kIOReturnBadArgument;
1512 }
1513
1514 pmso = PMSettingObject::pmSettingObject(
1515 (IOPMrootDomain *)this, func, target,
1516 refcon, supportedPowerSources, settings);
1517
1518 if(!pmso) {
1519 ret = kIOReturnInternalError;
1520 goto bail_no_unlock;
1521 }
1522
1523 IORecursiveLockLock(settingsCtrlLock);
1524 for(i=0; settings[i]; i++)
1525 {
1526 list = (OSArray *)settingsCallbacks->getObject(settings[i]);
1527 if(!list) {
1528 // New array of callbacks for this setting
1529 list = OSArray::withCapacity(1);
1530 settingsCallbacks->setObject(settings[i], list);
1531 list->release();
1532 }
1533
1534 // Add caller to the callback list
1535 list->setObject(pmso);
1536 }
1537
1538 IORecursiveLockUnlock(settingsCtrlLock);
1539
1540 ret = kIOReturnSuccess;
1541
1542 // Track this instance by its OSData ptr from now on
1543 *handle = pmso;
1544
1545 bail_no_unlock:
1546 if(kIOReturnSuccess != ret)
1547 {
1548 // Error return case
1549 if(pmso) pmso->release();
1550 if(handle) *handle = NULL;
1551 }
1552 return ret;
1553 }
1554
1555
1556 //******************************************************************************
1557 // sleepOnClamshellClosed
1558 //
1559 // contains the logic to determine if the system should sleep when the clamshell
1560 // is closed.
1561 //******************************************************************************
1562
1563 bool IOPMrootDomain::shouldSleepOnClamshellClosed ( void )
1564 {
1565 return ( !ignoringClamshell
1566 && !ignoringClamshellDuringWakeup
1567 && !(desktopMode && acAdaptorConnect) );
1568 }
1569
1570 void IOPMrootDomain::sendClientClamshellNotification ( void )
1571 {
1572 /* Only broadcast clamshell alert if clamshell exists. */
1573 if(!clamshellExists)
1574 return;
1575
1576 setProperty(kAppleClamshellStateKey,
1577 clamshellIsClosed ? kOSBooleanTrue : kOSBooleanFalse);
1578
1579 setProperty(kAppleClamshellCausesSleepKey,
1580 shouldSleepOnClamshellClosed() ? kOSBooleanTrue : kOSBooleanFalse);
1581
1582
1583 /* Argument to message is a bitfiel of
1584 * ( kClamshellStateBit | kClamshellSleepBit )
1585 */
1586 messageClients(kIOPMMessageClamshellStateChange,
1587 (void *) ( (clamshellIsClosed ? kClamshellStateBit : 0)
1588 | ( shouldSleepOnClamshellClosed() ? kClamshellSleepBit : 0)) );
1589 }
1590
1591 //******************************************************************************
1592 // informCPUStateChange
1593 //
1594 // Call into PM CPU code so that CPU power savings may dynamically adjust for
1595 // running on battery, with the lid closed, etc.
1596 //
1597 // informCPUStateChange is a no-op on non x86 systems
1598 // only x86 has explicit support in the IntelCPUPowerManagement kext
1599 //******************************************************************************
1600
1601 void IOPMrootDomain::informCPUStateChange(
1602 uint32_t type,
1603 uint32_t value )
1604 {
1605 #ifdef __i386__
1606
1607 pmioctlVariableInfo_t varInfoStruct;
1608 int pmCPUret = 0;
1609 const char *varNameStr = NULL;
1610 int32_t *varIndex = NULL;
1611
1612 if (kInformAC == type) {
1613 varNameStr = kIOPMRootDomainBatPowerCString;
1614 varIndex = &idxPMCPULimitedPower;
1615 } else if (kInformLid == type) {
1616 varNameStr = kIOPMRootDomainLidCloseCString;
1617 varIndex = &idxPMCPUClamshell;
1618 } else {
1619 return;
1620 }
1621
1622 // Set the new value!
1623 // pmCPUControl will assign us a new ID if one doesn't exist yet
1624 bzero(&varInfoStruct, sizeof(pmioctlVariableInfo_t));
1625 varInfoStruct.varID = *varIndex;
1626 varInfoStruct.varType = vBool;
1627 varInfoStruct.varInitValue = value;
1628 varInfoStruct.varCurValue = value;
1629 strncpy( (char *)varInfoStruct.varName,
1630 (const char *)varNameStr,
1631 strlen(varNameStr) + 1 );
1632
1633 // Set!
1634 pmCPUret = pmCPUControl( PMIOCSETVARINFO, (void *)&varInfoStruct );
1635
1636 // pmCPU only assigns numerical id's when a new varName is specified
1637 if ((0 == pmCPUret)
1638 && (*varIndex == kCPUUnknownIndex))
1639 {
1640 // pmCPUControl has assigned us a new variable ID.
1641 // Let's re-read the structure we just SET to learn that ID.
1642 pmCPUret = pmCPUControl( PMIOCGETVARNAMEINFO, (void *)&varInfoStruct );
1643
1644 if (0 == pmCPUret)
1645 {
1646 // Store it in idxPMCPUClamshell or idxPMCPULimitedPower
1647 *varIndex = varInfoStruct.varID;
1648 }
1649 }
1650
1651 return;
1652
1653 #endif __i386__
1654 }
1655
1656
1657 //******************************************************************************
1658 // receivePowerNotification
1659 //
1660 // The power controller is notifying us of a hardware-related power management
1661 // event that we must handle. This is a result of an 'environment' interrupt from
1662 // the power mgt micro.
1663 //******************************************************************************
1664
1665 IOReturn IOPMrootDomain::receivePowerNotification (UInt32 msg)
1666 {
1667 bool eval_clamshell = false;
1668
1669 /*
1670 * Local (IOPMrootDomain only) eval clamshell command
1671 */
1672 if (msg & kLocalEvalClamshellCommand)
1673 {
1674 eval_clamshell = true;
1675 }
1676
1677 /*
1678 * Overtemp
1679 */
1680 if (msg & kIOPMOverTemp)
1681 {
1682 IOLog("PowerManagement emergency overtemp signal. Going to sleep!");
1683
1684 privateSleepSystem (kIOPMThermalEmergencySleepKey);
1685 }
1686
1687 /*
1688 * PMU Processor Speed Change
1689 */
1690 if (msg & kIOPMProcessorSpeedChange)
1691 {
1692 IOService *pmu = waitForService(serviceMatching("ApplePMU"));
1693 pmu->callPlatformFunction("prepareForSleep", false, 0, 0, 0, 0);
1694 getPlatform()->sleepKernel();
1695 pmu->callPlatformFunction("recoverFromSleep", false, 0, 0, 0, 0);
1696 }
1697
1698 /*
1699 * Sleep Now!
1700 */
1701 if (msg & kIOPMSleepNow)
1702 {
1703 privateSleepSystem (kIOPMSoftwareSleepKey);
1704 }
1705
1706 /*
1707 * Power Emergency
1708 */
1709 if (msg & kIOPMPowerEmergency)
1710 {
1711 privateSleepSystem (kIOPMLowPowerSleepKey);
1712 }
1713
1714
1715 /*
1716 * Clamshell OPEN
1717 */
1718 if (msg & kIOPMClamshellOpened)
1719 {
1720 // Received clamshel open message from clamshell controlling driver
1721 // Update our internal state and tell general interest clients
1722 clamshellIsClosed = false;
1723 clamshellExists = true;
1724
1725 // Tell PMCPU
1726 informCPUStateChange(kInformLid, 0);
1727
1728 // Tell general interest clients
1729 sendClientClamshellNotification();
1730 }
1731
1732 /*
1733 * Clamshell CLOSED
1734 * Send the clamshell interest notification since the lid is closing.
1735 */
1736 if (msg & kIOPMClamshellClosed)
1737 {
1738 // Received clamshel open message from clamshell controlling driver
1739 // Update our internal state and tell general interest clients
1740 clamshellIsClosed = true;
1741 clamshellExists = true;
1742
1743 // Tell PMCPU
1744 informCPUStateChange(kInformLid, 1);
1745
1746 // Tell general interest clients
1747 sendClientClamshellNotification();
1748
1749 // And set eval_clamshell = so we can attempt
1750 eval_clamshell = true;
1751 }
1752
1753 /*
1754 * Set Desktop mode (sent from graphics)
1755 *
1756 * -> reevaluate lid state
1757 */
1758 if (msg & kIOPMSetDesktopMode)
1759 {
1760 desktopMode = (0 != (msg & kIOPMSetValue));
1761 msg &= ~(kIOPMSetDesktopMode | kIOPMSetValue);
1762
1763 sendClientClamshellNotification();
1764
1765 // Re-evaluate the lid state
1766 if( clamshellIsClosed )
1767 {
1768 eval_clamshell = true;
1769 }
1770 }
1771
1772 /*
1773 * AC Adaptor connected
1774 *
1775 * -> reevaluate lid state
1776 */
1777 if (msg & kIOPMSetACAdaptorConnected)
1778 {
1779 acAdaptorConnect = (0 != (msg & kIOPMSetValue));
1780 msg &= ~(kIOPMSetACAdaptorConnected | kIOPMSetValue);
1781
1782 // Tell PMCPU
1783 informCPUStateChange(kInformAC, !acAdaptorConnect);
1784
1785 sendClientClamshellNotification();
1786
1787 // Re-evaluate the lid state
1788 if( clamshellIsClosed )
1789 {
1790 eval_clamshell = true;
1791 }
1792
1793 }
1794
1795 /*
1796 * Enable Clamshell (external display disappear)
1797 *
1798 * -> reevaluate lid state
1799 */
1800 if (msg & kIOPMEnableClamshell)
1801 {
1802 // Re-evaluate the lid state
1803 // System should sleep on external display disappearance
1804 // in lid closed operation.
1805 if( clamshellIsClosed && (true == ignoringClamshell) )
1806 {
1807 eval_clamshell = true;
1808 }
1809
1810 ignoringClamshell = false;
1811
1812 sendClientClamshellNotification();
1813 }
1814
1815 /*
1816 * Disable Clamshell (external display appeared)
1817 * We don't bother re-evaluating clamshell state. If the system is awake,
1818 * the lid is probably open.
1819 */
1820 if (msg & kIOPMDisableClamshell)
1821 {
1822 ignoringClamshell = true;
1823
1824 sendClientClamshellNotification();
1825 }
1826
1827 /*
1828 * Evaluate clamshell and SLEEP if appropiate
1829 */
1830 if ( eval_clamshell && shouldSleepOnClamshellClosed() )
1831 {
1832
1833
1834 // SLEEP!
1835 privateSleepSystem (kIOPMClamshellSleepKey);
1836 }
1837
1838 /*
1839 * Power Button
1840 */
1841 if (msg & kIOPMPowerButton)
1842 {
1843 // toggle state of sleep/wake
1844 // are we dozing?
1845 if ( getPowerState() == DOZE_STATE )
1846 {
1847 // yes, tell the tree we're waking
1848 systemWake();
1849 // wake the Display Wrangler
1850 reportUserInput();
1851 }
1852 else {
1853 OSString *pbs = OSString::withCString("DisablePowerButtonSleep");
1854 // Check that power button sleep is enabled
1855 if( pbs ) {
1856 if( kOSBooleanTrue != getProperty(pbs))
1857 privateSleepSystem (kIOPMPowerButtonSleepKey);
1858 }
1859 }
1860 }
1861
1862 /*
1863 * Allow Sleep
1864 *
1865 */
1866 if ( (msg & kIOPMAllowSleep) && !allowSleep )
1867 {
1868 allowSleep = true;
1869 adjustPowerState();
1870 }
1871
1872 /*
1873 * Prevent Sleep
1874 *
1875 */
1876 if (msg & kIOPMPreventSleep) {
1877 allowSleep = false;
1878 // are we dozing?
1879 if ( getPowerState() == DOZE_STATE ) {
1880 // yes, tell the tree we're waking
1881 systemWake();
1882 adjustPowerState();
1883 // wake the Display Wrangler
1884 reportUserInput();
1885 } else {
1886 adjustPowerState();
1887 // make sure we have power to clamp
1888 patriarch->wakeSystem();
1889 }
1890 }
1891
1892 return 0;
1893 }
1894
1895
1896 //*********************************************************************************
1897 // sleepSupported
1898 //
1899 //*********************************************************************************
1900
1901 void IOPMrootDomain::setSleepSupported( IOOptionBits flags )
1902 {
1903 if ( flags & kPCICantSleep )
1904 {
1905 canSleep = false;
1906 } else {
1907 canSleep = true;
1908 platformSleepSupport = flags;
1909 }
1910
1911 setProperty(kIOSleepSupportedKey, canSleep);
1912
1913 }
1914
1915 //*********************************************************************************
1916 // requestPowerDomainState
1917 //
1918 // The root domain intercepts this call to the superclass.
1919 // Called on the PM work loop thread.
1920 //
1921 // If the clamp bit is not set in the desire, then the child doesn't need the power
1922 // state it's requesting; it just wants it. The root ignores desires but not needs.
1923 // If the clamp bit is not set, the root takes it that the child can tolerate no
1924 // power and interprets the request accordingly. If all children can thus tolerate
1925 // no power, we are on our way to idle sleep.
1926 //*********************************************************************************
1927
1928 IOReturn IOPMrootDomain::requestPowerDomainState (
1929 IOPMPowerFlags desiredState,
1930 IOPowerConnection * whichChild,
1931 unsigned long specification )
1932 {
1933 OSIterator *iter;
1934 OSObject *next;
1935 IOPowerConnection *connection;
1936 unsigned long powerRequestFlag = 0;
1937 IOPMPowerFlags editedDesire;
1938
1939 #if DEBUG
1940 IOService *powerChild;
1941 powerChild = (IOService *) whichChild->getChildEntry(gIOPowerPlane);
1942 #endif
1943
1944 DEBUG_LOG("RequestPowerDomainState: flags %lx, child %p [%s], spec %lx\n",
1945 desiredState, powerChild, powerChild ? powerChild->getName() : "?",
1946 specification);
1947
1948 // Force the child's input power requirements to 0 unless the prevent
1949 // idle-sleep flag is set. No input power flags map to our state 0.
1950 // Our power clamp (deviceDesire) keeps the minimum power state at 2.
1951
1952 if (desiredState & kIOPMPreventIdleSleep)
1953 editedDesire = desiredState;
1954 else
1955 editedDesire = 0;
1956
1957 // Recompute sleep supported flag (doze if not supported)
1958 sleepIsSupported = true;
1959
1960 iter = getChildIterator(gIOPowerPlane);
1961 if ( iter )
1962 {
1963 while ( (next = iter->getNextObject()) )
1964 {
1965 if ( (connection = OSDynamicCast(IOPowerConnection, next)) )
1966 {
1967 // Ignore child that are in the process of joining.
1968 if (connection->getReadyFlag() == false)
1969 continue;
1970
1971 // Is this connection attached to the child that called
1972 // requestPowerDomainState()?
1973
1974 if ( connection == whichChild )
1975 {
1976 // Yes, OR in the child's input power requirements.
1977 powerRequestFlag |= editedDesire;
1978
1979 if ( desiredState & kIOPMPreventSystemSleep )
1980 sleepIsSupported = false;
1981 }
1982 else
1983 {
1984 #if DEBUG
1985 powerChild = (IOService *) connection->getChildEntry(gIOPowerPlane);
1986 #endif
1987 DEBUG_LOG(" child %p, PState %ld, noIdle %d, noSleep %d, valid %d %s\n",
1988 powerChild,
1989 connection->getDesiredDomainState(),
1990 connection->getPreventIdleSleepFlag(),
1991 connection->getPreventSystemSleepFlag(),
1992 connection->getReadyFlag(),
1993 powerChild ? powerChild->getName() : "?");
1994
1995 // No, OR in the child's desired power domain state.
1996 // Which is our power state desired by this child.
1997 powerRequestFlag |= connection->getDesiredDomainState();
1998
1999 if ( connection->getPreventSystemSleepFlag() )
2000 sleepIsSupported = false;
2001 }
2002 }
2003 }
2004 iter->release();
2005 }
2006
2007 if ( !powerRequestFlag && !systemBooting )
2008 {
2009 if (!wrangler)
2010 {
2011 sleepASAP = false;
2012 changePowerStateToPriv(ON_STATE);
2013 if (idleSeconds)
2014 {
2015 AbsoluteTime deadline;
2016 // stay awake for at least idleSeconds
2017 clock_interval_to_deadline(idleSeconds, kSecondScale, &deadline);
2018 thread_call_enter_delayed(extraSleepTimer, deadline);
2019 // this gets turned off when we sleep again
2020 idleSleepPending = true;
2021 }
2022 }
2023 else if (extraSleepDelay == 0)
2024 {
2025 sleepASAP = true;
2026 }
2027 }
2028
2029 DEBUG_LOG(" sleepDelay %lx, mergedFlags %lx, sleepASAP %x, booting %x\n",
2030 extraSleepDelay, powerRequestFlag, sleepASAP, systemBooting);
2031
2032 // Drop our power clamp to SLEEP_STATE when all devices become idle.
2033 // Needed when the system sleep and display sleep timeouts are the same.
2034 // Otherwise, the extra sleep timer will also drop our power clamp.
2035
2036 adjustPowerState();
2037
2038 editedDesire |= (desiredState & kIOPMPreventSystemSleep);
2039
2040 // If our power clamp has already dropped to SLEEP_STATE, and no child
2041 // is keeping us at max power, then this will trigger idle sleep.
2042
2043 return super::requestPowerDomainState(editedDesire, whichChild, specification);
2044 }
2045
2046
2047 //*********************************************************************************
2048 // getSleepSupported
2049 //
2050 //*********************************************************************************
2051
2052 IOOptionBits IOPMrootDomain::getSleepSupported( void )
2053 {
2054 return( platformSleepSupport );
2055 }
2056
2057
2058 //*********************************************************************************
2059 // handlePlatformHaltRestart
2060 //
2061 //*********************************************************************************
2062
2063 struct HaltRestartApplierContext {
2064 IOPMrootDomain * RootDomain;
2065 unsigned long PowerState;
2066 IOPMPowerFlags PowerFlags;
2067 UInt32 MessageType;
2068 UInt32 Counter;
2069 };
2070
2071 static void
2072 platformHaltRestartApplier( OSObject * object, void * context )
2073 {
2074 IOPowerStateChangeNotification notify;
2075 HaltRestartApplierContext * ctx;
2076 AbsoluteTime startTime;
2077 UInt32 deltaTime;
2078
2079 ctx = (HaltRestartApplierContext *) context;
2080
2081 memset(&notify, 0, sizeof(notify));
2082 notify.powerRef = (void *)ctx->Counter;
2083 notify.returnValue = 0;
2084 notify.stateNumber = ctx->PowerState;
2085 notify.stateFlags = ctx->PowerFlags;
2086
2087 clock_get_uptime(&startTime);
2088 ctx->RootDomain->messageClient( ctx->MessageType, object, (void *)&notify );
2089 deltaTime = computeDeltaTimeMS(&startTime);
2090
2091 if ((deltaTime > kPMHaltTimeoutMS) || (gIOKitDebug & kIOLogDebugPower))
2092 {
2093 _IOServiceInterestNotifier * notifier;
2094 notifier = OSDynamicCast(_IOServiceInterestNotifier, object);
2095
2096 // IOService children of IOPMrootDomain are not instrumented.
2097 // Only IORootParent currently falls under that group.
2098
2099 if (notifier)
2100 {
2101 HaltRestartLog("%s handler %p took %lu ms\n",
2102 (ctx->MessageType == kIOMessageSystemWillPowerOff) ?
2103 "PowerOff" : "Restart",
2104 notifier->handler, deltaTime );
2105 }
2106 }
2107
2108 ctx->Counter++;
2109 }
2110
2111 void IOPMrootDomain::handlePlatformHaltRestart( UInt32 pe_type )
2112 {
2113 HaltRestartApplierContext ctx;
2114 AbsoluteTime startTime;
2115 UInt32 deltaTime;
2116
2117 memset(&ctx, 0, sizeof(ctx));
2118 ctx.RootDomain = this;
2119
2120 clock_get_uptime(&startTime);
2121 switch (pe_type)
2122 {
2123 case kPEHaltCPU:
2124 ctx.PowerState = OFF_STATE;
2125 ctx.MessageType = kIOMessageSystemWillPowerOff;
2126 break;
2127
2128 case kPERestartCPU:
2129 ctx.PowerState = RESTART_STATE;
2130 ctx.MessageType = kIOMessageSystemWillRestart;
2131 break;
2132
2133 default:
2134 return;
2135 }
2136
2137 // Notify legacy clients
2138 applyToInterested(gIOPriorityPowerStateInterest, platformHaltRestartApplier, &ctx);
2139
2140 // Notify in power tree order
2141 notifySystemShutdown(this, ctx.MessageType);
2142
2143 deltaTime = computeDeltaTimeMS(&startTime);
2144 HaltRestartLog("%s all drivers took %lu ms\n",
2145 (ctx.MessageType == kIOMessageSystemWillPowerOff) ?
2146 "PowerOff" : "Restart",
2147 deltaTime );
2148 }
2149
2150
2151 //*********************************************************************************
2152 // tellChangeDown
2153 //
2154 // We override the superclass implementation so we can send a different message
2155 // type to the client or application being notified.
2156 //*********************************************************************************
2157
2158 bool IOPMrootDomain::tellChangeDown ( unsigned long stateNum )
2159 {
2160 switch ( stateNum ) {
2161 case DOZE_STATE:
2162 case SLEEP_STATE:
2163
2164 // Direct callout into OSMetaClass so it can disable kmod unloads
2165 // during sleep/wake to prevent deadlocks.
2166 OSMetaClassSystemSleepOrWake( kIOMessageSystemWillSleep );
2167
2168 return super::tellClientsWithResponse(kIOMessageSystemWillSleep);
2169 }
2170 return super::tellChangeDown(stateNum);
2171 }
2172
2173
2174 //*********************************************************************************
2175 // askChangeDown
2176 //
2177 // We override the superclass implementation so we can send a different message
2178 // type to the client or application being notified.
2179 //
2180 // This must be idle sleep since we don't ask apps during any other power change.
2181 //*********************************************************************************
2182
2183 bool IOPMrootDomain::askChangeDown ( unsigned long )
2184 {
2185 return super::tellClientsWithResponse(kIOMessageCanSystemSleep);
2186 }
2187
2188
2189 //*********************************************************************************
2190 // tellNoChangeDown
2191 //
2192 // Notify registered applications and kernel clients that we are not
2193 // dropping power.
2194 //
2195 // We override the superclass implementation so we can send a different message
2196 // type to the client or application being notified.
2197 //
2198 // This must be a vetoed idle sleep, since no other power change can be vetoed.
2199 //*********************************************************************************
2200
2201 void IOPMrootDomain::tellNoChangeDown ( unsigned long )
2202 {
2203 if (idleSeconds && !wrangler)
2204 {
2205 AbsoluteTime deadline;
2206 sleepASAP = false;
2207 // stay awake for at least idleSeconds
2208 clock_interval_to_deadline(idleSeconds, kSecondScale, &deadline);
2209 thread_call_enter_delayed(extraSleepTimer, deadline);
2210 // this gets turned off when we sleep again
2211 idleSleepPending = true;
2212 }
2213 return tellClients(kIOMessageSystemWillNotSleep);
2214 }
2215
2216
2217 //*********************************************************************************
2218 // tellChangeUp
2219 //
2220 // Notify registered applications and kernel clients that we are raising power.
2221 //
2222 // We override the superclass implementation so we can send a different message
2223 // type to the client or application being notified.
2224 //*********************************************************************************
2225
2226 void IOPMrootDomain::tellChangeUp ( unsigned long stateNum)
2227 {
2228 if ( stateNum == ON_STATE )
2229 {
2230 #if HIBERNATION
2231 // Direct callout into OSMetaClass so it can disable kmod unloads
2232 // during sleep/wake to prevent deadlocks.
2233 OSMetaClassSystemSleepOrWake( kIOMessageSystemHasPoweredOn );
2234
2235 IOHibernateSystemPostWake();
2236 #endif
2237 return tellClients(kIOMessageSystemHasPoweredOn);
2238 }
2239 }
2240
2241 //*********************************************************************************
2242 // reportUserInput
2243 //
2244 //*********************************************************************************
2245
2246 void IOPMrootDomain::reportUserInput ( void )
2247 {
2248 #if !NO_KERNEL_HID
2249 OSIterator * iter;
2250
2251 if(!wrangler)
2252 {
2253 iter = getMatchingServices(serviceMatching("IODisplayWrangler"));
2254 if(iter)
2255 {
2256 wrangler = (IOService *) iter->getNextObject();
2257 iter->release();
2258 }
2259 }
2260
2261 if(wrangler)
2262 wrangler->activityTickle(0,0);
2263 #endif
2264 }
2265
2266 //*********************************************************************************
2267 // setQuickSpinDownTimeout
2268 //
2269 //*********************************************************************************
2270
2271 void IOPMrootDomain::setQuickSpinDownTimeout ( void )
2272 {
2273 super::setAggressiveness((unsigned long)kPMMinutesToSpinDown,(unsigned long)1);
2274 }
2275
2276 //*********************************************************************************
2277 // restoreUserSpinDownTimeout
2278 //
2279 //*********************************************************************************
2280
2281 void IOPMrootDomain::restoreUserSpinDownTimeout ( void )
2282 {
2283 super::setAggressiveness((unsigned long)kPMMinutesToSpinDown,(unsigned long)user_spindown);
2284 }
2285
2286 //*********************************************************************************
2287 // changePowerStateTo & changePowerStateToPriv
2288 //
2289 // Override of these methods for logging purposes.
2290 //*********************************************************************************
2291
2292 IOReturn IOPMrootDomain::changePowerStateTo ( unsigned long ordinal )
2293 {
2294 return super::changePowerStateTo(ordinal);
2295 }
2296
2297 IOReturn IOPMrootDomain::changePowerStateToPriv ( unsigned long ordinal )
2298 {
2299 IOReturn ret;
2300
2301 DEBUG_LOG("ChangePowerStateToPriv: power state %ld\n", ordinal);
2302
2303 if ( (getPowerState() == DOZE_STATE) && (ordinal != ON_STATE) )
2304 {
2305 return kIOReturnSuccess;
2306 }
2307
2308 if( (userDisabledAllSleep || systemBooting || systemShutdown)
2309 && (ordinal == SLEEP_STATE) )
2310 {
2311 DEBUG_LOG(" sleep denied: disableAllSleep %d, booting %d, shutdown %d\n",
2312 userDisabledAllSleep, systemBooting, systemShutdown);
2313 super::changePowerStateToPriv(ON_STATE);
2314 }
2315
2316 if( (SLEEP_STATE == ordinal) && sleepSupportedPEFunction )
2317 {
2318
2319 // Determine if the machine supports sleep, or must doze.
2320 ret = getPlatform()->callPlatformFunction(
2321 sleepSupportedPEFunction, false,
2322 NULL, NULL, NULL, NULL);
2323
2324 // If the machine only supports doze, the callPlatformFunction call
2325 // boils down to IOPMrootDomain::setSleepSupported(kPCICantSleep),
2326 // otherwise nothing.
2327 }
2328
2329 return super::changePowerStateToPriv(ordinal);
2330 }
2331
2332
2333 //*********************************************************************************
2334 // sysPowerDownHandler
2335 //
2336 // Receives a notification when the RootDomain changes state.
2337 //
2338 // Allows us to take action on system sleep, power down, and restart after
2339 // applications have received their power change notifications and replied,
2340 // but before drivers have powered down. We perform a vfs sync on power down.
2341 //*********************************************************************************
2342
2343 IOReturn IOPMrootDomain::sysPowerDownHandler( void * target, void * refCon,
2344 UInt32 messageType, IOService * service,
2345 void * messageArgument, vm_size_t argSize )
2346 {
2347 IOReturn ret;
2348 IOPowerStateChangeNotification *params = (IOPowerStateChangeNotification *) messageArgument;
2349 IOPMrootDomain *rootDomain = OSDynamicCast(IOPMrootDomain, service);
2350
2351 if(!rootDomain)
2352 return kIOReturnUnsupported;
2353
2354 switch (messageType) {
2355 case kIOMessageSystemWillSleep:
2356 DEBUG_LOG("SystemWillSleep\n");
2357
2358 // Interested applications have been notified of an impending power
2359 // change and have acked (when applicable).
2360 // This is our chance to save whatever state we can before powering
2361 // down.
2362 // We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c,
2363 // via callout
2364
2365 // We will ack within 20 seconds
2366 params->returnValue = 20 * 1000 * 1000;
2367 #if HIBERNATION
2368 if (gIOHibernateState)
2369 params->returnValue += gIOHibernateFreeTime * 1000; //add in time we could spend freeing pages
2370 #endif
2371
2372 if ( ! OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending ) )
2373 {
2374 // Purposely delay the ack and hope that shutdown occurs quickly.
2375 // Another option is not to schedule the thread and wait for
2376 // ack timeout...
2377 AbsoluteTime deadline;
2378 clock_interval_to_deadline( 30, kSecondScale, &deadline );
2379 thread_call_enter1_delayed( rootDomain->diskSyncCalloutEntry,
2380 (thread_call_param_t)params->powerRef,
2381 deadline );
2382 }
2383 else
2384 thread_call_enter1(rootDomain->diskSyncCalloutEntry, (thread_call_param_t)params->powerRef);
2385 ret = kIOReturnSuccess;
2386 break;
2387
2388 case kIOMessageSystemWillPowerOff:
2389 case kIOMessageSystemWillRestart:
2390 ret = kIOReturnUnsupported;
2391 break;
2392
2393 default:
2394 ret = kIOReturnUnsupported;
2395 break;
2396 }
2397 return ret;
2398 }
2399
2400 //*********************************************************************************
2401 // displayWranglerNotification
2402 //
2403 // Receives a notification when the IODisplayWrangler changes state.
2404 //
2405 // Allows us to take action on display dim/undim.
2406 //
2407 // When the display sleeps we:
2408 // - Start the idle sleep timer
2409 // - set the quick spin down timeout
2410 //
2411 // On wake from display sleep:
2412 // - Cancel the idle sleep timer
2413 // - restore the user's chosen spindown timer from the "quick" spin down value
2414 //*********************************************************************************
2415
2416 IOReturn IOPMrootDomain::displayWranglerNotification(
2417 void * target, void * refCon,
2418 UInt32 messageType, IOService * service,
2419 void * messageArgument, vm_size_t argSize )
2420 {
2421 #if !NO_KERNEL_HID
2422 IOPMrootDomain * rootDomain = OSDynamicCast(IOPMrootDomain, (IOService *)target);
2423 AbsoluteTime deadline;
2424 static int displayPowerState = 4;
2425
2426 if (!rootDomain)
2427 return kIOReturnUnsupported;
2428
2429 switch (messageType) {
2430 case kIOMessageDeviceWillPowerOff:
2431 DEBUG_LOG("DisplayWranglerWillPowerOff: new p-state %d\n",
2432 displayPowerState - 1);
2433
2434 // The display wrangler has dropped power because of idle display sleep
2435 // or force system sleep. We will receive 4 messages before the display
2436 // wrangler reaches its lowest state. Act only when going to state 2.
2437 //
2438 // 4->3 Display Dim
2439 // 3->2 Display Sleep
2440 // 2->1 Not visible to user
2441 // 1->0 Not visible to user
2442
2443 displayPowerState--;
2444 if ( 2 != displayPowerState )
2445 return kIOReturnUnsupported;
2446
2447 // We start a timer here if the System Sleep timer is greater than the
2448 // Display Sleep timer. We kick off this timer when the display sleeps.
2449 //
2450 // Note that, although Display Dim timings may change adaptively accordingly
2451 // to the user's activity patterns, Display Sleep _always_ occurs at the
2452 // specified interval since last user activity.
2453
2454 if ( rootDomain->extraSleepDelay )
2455 {
2456 clock_interval_to_deadline(rootDomain->extraSleepDelay*60, kSecondScale, &deadline);
2457 thread_call_enter_delayed(rootDomain->extraSleepTimer, deadline);
2458 rootDomain->idleSleepPending = true;
2459 DEBUG_LOG(" sleep timer set to expire in %ld min\n",
2460 rootDomain->extraSleepDelay);
2461 } else {
2462 // Accelerate disk spindown if system sleep and display sleep
2463 // sliders are set to the same value (e.g. both set to 5 min),
2464 // and display is about to go dark. Check that spin down timer
2465 // is non-zero (zero = never spin down) and system sleep is
2466 // not set to never sleep.
2467
2468 if ( (0 != rootDomain->user_spindown) && (0 != rootDomain->sleepSlider) )
2469 {
2470 DEBUG_LOG(" accelerate quick disk spindown, was %d min\n",
2471 rootDomain->user_spindown);
2472 rootDomain->setQuickSpinDownTimeout();
2473 }
2474 }
2475
2476 break;
2477
2478 case kIOMessageDeviceHasPoweredOn:
2479 DEBUG_LOG("DisplayWranglerHasPoweredOn: previous p-state %d\n",
2480 displayPowerState);
2481
2482 // The display wrangler has powered on either because of user activity
2483 // or wake from sleep/doze.
2484
2485 displayPowerState = 4;
2486 rootDomain->adjustPowerState();
2487
2488 // cancel any pending idle sleep timers
2489 if (rootDomain->idleSleepPending)
2490 {
2491 DEBUG_LOG(" extra-sleep timer stopped\n");
2492 thread_call_cancel(rootDomain->extraSleepTimer);
2493 rootDomain->idleSleepPending = false;
2494 }
2495
2496 // Change the spindown value back to the user's selection from our
2497 // accelerated setting.
2498 if (0 != rootDomain->user_spindown)
2499 {
2500 DEBUG_LOG(" restoring disk spindown to %d min\n",
2501 rootDomain->user_spindown);
2502 rootDomain->restoreUserSpinDownTimeout();
2503 }
2504
2505 break;
2506
2507 default:
2508 break;
2509 }
2510 #endif
2511 return kIOReturnUnsupported;
2512 }
2513
2514 //*********************************************************************************
2515 // displayWranglerPublished
2516 //
2517 // Receives a notification when the IODisplayWrangler is published.
2518 // When it's published we install a power state change handler.
2519 //
2520 //*********************************************************************************
2521
2522 bool IOPMrootDomain::displayWranglerPublished(
2523 void * target,
2524 void * refCon,
2525 IOService * newService)
2526 {
2527 #if !NO_KERNEL_HID
2528 IOPMrootDomain *rootDomain =
2529 OSDynamicCast(IOPMrootDomain, (IOService *)target);
2530
2531 if(!rootDomain)
2532 return false;
2533
2534 rootDomain->wrangler = newService;
2535
2536 // we found the display wrangler, now install a handler
2537 if( !rootDomain->wrangler->registerInterest( gIOGeneralInterest,
2538 &displayWranglerNotification, target, 0) )
2539 {
2540 return false;
2541 }
2542 #endif
2543 return true;
2544 }
2545
2546 //*********************************************************************************
2547 // batteryPublished
2548 //
2549 // Notification on battery class IOPowerSource appearance
2550 //
2551 //******************************************************************************
2552
2553 bool IOPMrootDomain::batteryPublished(
2554 void * target,
2555 void * root_domain,
2556 IOService * resourceService )
2557 {
2558 // rdar://2936060&4435589
2559 // All laptops have dimmable LCD displays
2560 // All laptops have batteries
2561 // So if this machine has a battery, publish the fact that the backlight
2562 // supports dimming.
2563 ((IOPMrootDomain *)root_domain)->publishFeature("DisplayDims");
2564
2565 return (true);
2566 }
2567
2568 //*********************************************************************************
2569 // adjustPowerState
2570 //
2571 // Some condition that affects our wake/sleep/doze decision has changed.
2572 //
2573 // If the sleep slider is in the off position, we cannot sleep or doze.
2574 // If the enclosure is open, we cannot sleep or doze.
2575 // If the system is still booting, we cannot sleep or doze.
2576 //
2577 // In those circumstances, we prevent sleep and doze by holding power on with
2578 // changePowerStateToPriv(ON).
2579 //
2580 // If the above conditions do not exist, and also the sleep timer has expired, we
2581 // allow sleep or doze to occur with either changePowerStateToPriv(SLEEP) or
2582 // changePowerStateToPriv(DOZE) depending on whether or not we already know the
2583 // platform cannot sleep.
2584 //
2585 // In this case, sleep or doze will either occur immediately or at the next time
2586 // that no children are holding the system out of idle sleep via the
2587 // kIOPMPreventIdleSleep flag in their power state arrays.
2588 //*********************************************************************************
2589
2590 void IOPMrootDomain::adjustPowerState( void )
2591 {
2592 if ( (sleepSlider == 0)
2593 || !allowSleep
2594 || systemBooting
2595 || systemShutdown
2596 || userDisabledAllSleep )
2597 {
2598 DEBUG_LOG("AdjustPowerState %ld -> ON: slider %ld, allowSleep %d, "
2599 "booting %d, shutdown %d, userDisabled %d\n",
2600 getPowerState(), sleepSlider, allowSleep, systemBooting,
2601 systemShutdown, userDisabledAllSleep);
2602
2603 changePowerStateToPriv(ON_STATE);
2604 } else {
2605 if ( sleepASAP )
2606 {
2607 DEBUG_LOG("AdjustPowerState SLEEP\n");
2608
2609 /* Convenient place to run any code at idle sleep time
2610 * IOPMrootDomain initiates an idle sleep here
2611 *
2612 * Set last sleep cause accordingly.
2613 */
2614 setProperty(kRootDomainSleepReasonKey, kIOPMIdleSleepKey);
2615
2616 sleepASAP = false;
2617 if ( !sleepIsSupported )
2618 {
2619 setSleepSupported( kPCICantSleep );
2620 kprintf("Sleep prevented by kIOPMPreventSystemSleep flag\n");
2621 }
2622 changePowerStateToPriv(SLEEP_STATE);
2623 }
2624 }
2625 }
2626
2627 //*********************************************************************************
2628 // PMHaltWorker Class
2629 //
2630 //*********************************************************************************
2631
2632 static unsigned int gPMHaltBusyCount;
2633 static unsigned int gPMHaltIdleCount;
2634 static int gPMHaltDepth;
2635 static unsigned long gPMHaltEvent;
2636 static IOLock * gPMHaltLock = 0;
2637 static OSArray * gPMHaltArray = 0;
2638 static const OSSymbol * gPMHaltClientAcknowledgeKey = 0;
2639
2640 PMHaltWorker * PMHaltWorker::worker( void )
2641 {
2642 PMHaltWorker * me;
2643 IOThread thread;
2644
2645 do {
2646 me = OSTypeAlloc( PMHaltWorker );
2647 if (!me || !me->init())
2648 break;
2649
2650 me->lock = IOLockAlloc();
2651 if (!me->lock)
2652 break;
2653
2654 DEBUG_LOG("PMHaltWorker %p\n", me);
2655 me->retain(); // thread holds extra retain
2656 thread = IOCreateThread( &PMHaltWorker::main, me );
2657 if (!thread)
2658 {
2659 me->release();
2660 break;
2661 }
2662 return me;
2663
2664 } while (false);
2665
2666 if (me) me->release();
2667 return 0;
2668 }
2669
2670 void PMHaltWorker::free( void )
2671 {
2672 DEBUG_LOG("PMHaltWorker free %p\n", this);
2673 if (lock)
2674 {
2675 IOLockFree(lock);
2676 lock = 0;
2677 }
2678 return OSObject::free();
2679 }
2680
2681 void PMHaltWorker::main( void * arg )
2682 {
2683 PMHaltWorker * me = (PMHaltWorker *) arg;
2684
2685 IOLockLock( gPMHaltLock );
2686 gPMHaltBusyCount++;
2687 me->depth = gPMHaltDepth;
2688 IOLockUnlock( gPMHaltLock );
2689
2690 while (me->depth >= 0)
2691 {
2692 PMHaltWorker::work( me );
2693
2694 IOLockLock( gPMHaltLock );
2695 if (++gPMHaltIdleCount >= gPMHaltBusyCount)
2696 {
2697 // This is the last thread to finish work on this level,
2698 // inform everyone to start working on next lower level.
2699 gPMHaltDepth--;
2700 me->depth = gPMHaltDepth;
2701 gPMHaltIdleCount = 0;
2702 thread_wakeup((event_t) &gPMHaltIdleCount);
2703 }
2704 else
2705 {
2706 // One or more threads are still working on this level,
2707 // this thread must wait.
2708 me->depth = gPMHaltDepth - 1;
2709 do {
2710 IOLockSleep(gPMHaltLock, &gPMHaltIdleCount, THREAD_UNINT);
2711 } while (me->depth != gPMHaltDepth);
2712 }
2713 IOLockUnlock( gPMHaltLock );
2714 }
2715
2716 // No more work to do, terminate thread
2717 DEBUG_LOG("All done for worker: %p (visits = %u)\n", me, me->visits);
2718 thread_wakeup( &gPMHaltDepth );
2719 me->release();
2720 }
2721
2722 void PMHaltWorker::work( PMHaltWorker * me )
2723 {
2724 IOService * service;
2725 OSSet * inner;
2726 AbsoluteTime startTime;
2727 UInt32 deltaTime;
2728 bool timeout;
2729
2730 while (true)
2731 {
2732 service = 0;
2733 timeout = false;
2734
2735 // Claim an unit of work from the shared pool
2736 IOLockLock( gPMHaltLock );
2737 inner = (OSSet *)gPMHaltArray->getObject(me->depth);
2738 if (inner)
2739 {
2740 service = (IOService *)inner->getAnyObject();
2741 if (service)
2742 {
2743 service->retain();
2744 inner->removeObject(service);
2745 }
2746 }
2747 IOLockUnlock( gPMHaltLock );
2748 if (!service)
2749 break; // no more work at this depth
2750
2751 clock_get_uptime(&startTime);
2752
2753 if (!service->isInactive() &&
2754 service->setProperty(gPMHaltClientAcknowledgeKey, me))
2755 {
2756 IOLockLock(me->lock);
2757 me->startTime = startTime;
2758 me->service = service;
2759 me->timeout = false;
2760 IOLockUnlock(me->lock);
2761
2762 service->systemWillShutdown( gPMHaltEvent );
2763
2764 // Wait for driver acknowledgement
2765 IOLockLock(me->lock);
2766 while (service->getProperty(gPMHaltClientAcknowledgeKey))
2767 {
2768 IOLockSleep(me->lock, me, THREAD_UNINT);
2769 }
2770 me->service = 0;
2771 timeout = me->timeout;
2772 IOLockUnlock(me->lock);
2773 }
2774
2775 deltaTime = computeDeltaTimeMS(&startTime);
2776 if ((deltaTime > kPMHaltTimeoutMS) || timeout ||
2777 (gIOKitDebug & kIOLogDebugPower))
2778 {
2779 HaltRestartLog("%s driver %s (%p) took %lu ms\n",
2780 (gPMHaltEvent == kIOMessageSystemWillPowerOff) ?
2781 "PowerOff" : "Restart",
2782 service->getName(), service,
2783 deltaTime );
2784 }
2785
2786 service->release();
2787 me->visits++;
2788 }
2789 }
2790
2791 void PMHaltWorker::checkTimeout( PMHaltWorker * me, AbsoluteTime * now )
2792 {
2793 UInt64 nano;
2794 AbsoluteTime startTime;
2795 AbsoluteTime endTime;
2796
2797 endTime = *now;
2798
2799 IOLockLock(me->lock);
2800 if (me->service && !me->timeout)
2801 {
2802 startTime = me->startTime;
2803 nano = 0;
2804 if (CMP_ABSOLUTETIME(&endTime, &startTime) > 0)
2805 {
2806 SUB_ABSOLUTETIME(&endTime, &startTime);
2807 absolutetime_to_nanoseconds(endTime, &nano);
2808 }
2809 if (nano > 3000000000ULL)
2810 {
2811 me->timeout = true;
2812 HaltRestartLog("%s still waiting on %s\n",
2813 (gPMHaltEvent == kIOMessageSystemWillPowerOff) ?
2814 "PowerOff" : "Restart",
2815 me->service->getName());
2816 }
2817 }
2818 IOLockUnlock(me->lock);
2819 }
2820
2821 //*********************************************************************************
2822 // acknowledgeSystemWillShutdown
2823 //
2824 // Acknowledgement from drivers that they have prepared for shutdown/restart.
2825 //*********************************************************************************
2826
2827 void IOPMrootDomain::acknowledgeSystemWillShutdown( IOService * from )
2828 {
2829 PMHaltWorker * worker;
2830 OSObject * prop;
2831
2832 if (!from)
2833 return;
2834
2835 //DEBUG_LOG("%s acknowledged\n", from->getName());
2836 prop = from->copyProperty( gPMHaltClientAcknowledgeKey );
2837 if (prop)
2838 {
2839 worker = (PMHaltWorker *) prop;
2840 IOLockLock(worker->lock);
2841 from->removeProperty( gPMHaltClientAcknowledgeKey );
2842 thread_wakeup((event_t) worker);
2843 IOLockUnlock(worker->lock);
2844 worker->release();
2845 }
2846 else
2847 {
2848 DEBUG_LOG("%s acknowledged without worker property\n",
2849 from->getName());
2850 }
2851 }
2852
2853 //*********************************************************************************
2854 // notifySystemShutdown
2855 //
2856 // Notify all objects in PM tree that system will shutdown or restart
2857 //*********************************************************************************
2858
2859 static void
2860 notifySystemShutdown( IOService * root, unsigned long event )
2861 {
2862 #define PLACEHOLDER ((OSSet *)gPMHaltArray)
2863 IORegistryIterator * iter;
2864 IORegistryEntry * entry;
2865 IOService * node;
2866 OSSet * inner;
2867 PMHaltWorker * workers[kPMHaltMaxWorkers];
2868 AbsoluteTime deadline;
2869 unsigned int totalNodes = 0;
2870 unsigned int depth;
2871 unsigned int rootDepth;
2872 unsigned int numWorkers;
2873 unsigned int count;
2874 int waitResult;
2875 void * baseFunc;
2876 bool ok;
2877
2878 DEBUG_LOG("%s event = %lx\n", __FUNCTION__, event);
2879
2880 baseFunc = OSMemberFunctionCast(void *, root, &IOService::systemWillShutdown);
2881
2882 // Iterate the entire PM tree starting from root
2883
2884 rootDepth = root->getDepth( gIOPowerPlane );
2885 if (!rootDepth) goto done;
2886
2887 // debug - for repeated test runs
2888 while (PMHaltWorker::metaClass->getInstanceCount())
2889 IOSleep(1);
2890
2891 if (!gPMHaltArray)
2892 {
2893 gPMHaltArray = OSArray::withCapacity(40);
2894 if (!gPMHaltArray) goto done;
2895 }
2896 else // debug
2897 gPMHaltArray->flushCollection();
2898
2899 if (!gPMHaltLock)
2900 {
2901 gPMHaltLock = IOLockAlloc();
2902 if (!gPMHaltLock) goto done;
2903 }
2904
2905 if (!gPMHaltClientAcknowledgeKey)
2906 {
2907 gPMHaltClientAcknowledgeKey =
2908 OSSymbol::withCStringNoCopy("PMShutdown");
2909 if (!gPMHaltClientAcknowledgeKey) goto done;
2910 }
2911
2912 gPMHaltEvent = event;
2913
2914 // Depth-first walk of PM plane
2915
2916 iter = IORegistryIterator::iterateOver(
2917 root, gIOPowerPlane, kIORegistryIterateRecursively);
2918
2919 if (iter)
2920 {
2921 while ((entry = iter->getNextObject()))
2922 {
2923 node = OSDynamicCast(IOService, entry);
2924 if (!node)
2925 continue;
2926
2927 if (baseFunc ==
2928 OSMemberFunctionCast(void *, node, &IOService::systemWillShutdown))
2929 continue;
2930
2931 depth = node->getDepth( gIOPowerPlane );
2932 if (depth <= rootDepth)
2933 continue;
2934
2935 ok = false;
2936
2937 // adjust to zero based depth
2938 depth -= (rootDepth + 1);
2939
2940 // gPMHaltArray is an array of containers, each container
2941 // refers to nodes with the same depth.
2942
2943 count = gPMHaltArray->getCount();
2944 while (depth >= count)
2945 {
2946 // expand array and insert placeholders
2947 gPMHaltArray->setObject(PLACEHOLDER);
2948 count++;
2949 }
2950 count = gPMHaltArray->getCount();
2951 if (depth < count)
2952 {
2953 inner = (OSSet *)gPMHaltArray->getObject(depth);
2954 if (inner == PLACEHOLDER)
2955 {
2956 inner = OSSet::withCapacity(40);
2957 if (inner)
2958 {
2959 gPMHaltArray->replaceObject(depth, inner);
2960 inner->release();
2961 }
2962 }
2963
2964 // PM nodes that appear more than once in the tree will have
2965 // the same depth, OSSet will refuse to add the node twice.
2966 if (inner)
2967 ok = inner->setObject(node);
2968 }
2969 if (!ok)
2970 DEBUG_LOG("Skipped PM node %s\n", node->getName());
2971 }
2972 iter->release();
2973 }
2974
2975 // debug only
2976 for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i)); i++)
2977 {
2978 count = 0;
2979 if (inner != PLACEHOLDER)
2980 count = inner->getCount();
2981 DEBUG_LOG("Nodes at depth %u = %u\n", i, count);
2982 }
2983
2984 // strip placeholders (not all depths are populated)
2985 numWorkers = 0;
2986 for (int i = 0; (inner = (OSSet *)gPMHaltArray->getObject(i)); )
2987 {
2988 if (inner == PLACEHOLDER)
2989 {
2990 gPMHaltArray->removeObject(i);
2991 continue;
2992 }
2993 count = inner->getCount();
2994 if (count > numWorkers)
2995 numWorkers = count;
2996 totalNodes += count;
2997 i++;
2998 }
2999
3000 if (gPMHaltArray->getCount() == 0 || !numWorkers)
3001 goto done;
3002
3003 gPMHaltBusyCount = 0;
3004 gPMHaltIdleCount = 0;
3005 gPMHaltDepth = gPMHaltArray->getCount() - 1;
3006
3007 // Create multiple workers (and threads)
3008
3009 if (numWorkers > kPMHaltMaxWorkers)
3010 numWorkers = kPMHaltMaxWorkers;
3011
3012 DEBUG_LOG("PM nodes = %u, maxDepth = %u, workers = %u\n",
3013 totalNodes, gPMHaltArray->getCount(), numWorkers);
3014
3015 for (unsigned int i = 0; i < numWorkers; i++)
3016 workers[i] = PMHaltWorker::worker();
3017
3018 // Wait for workers to exhaust all available work
3019
3020 IOLockLock(gPMHaltLock);
3021 while (gPMHaltDepth >= 0)
3022 {
3023 clock_interval_to_deadline(1000, kMillisecondScale, &deadline);
3024
3025 waitResult = IOLockSleepDeadline(
3026 gPMHaltLock, &gPMHaltDepth, deadline, THREAD_UNINT);
3027 if (THREAD_TIMED_OUT == waitResult)
3028 {
3029 AbsoluteTime now;
3030 clock_get_uptime(&now);
3031
3032 IOLockUnlock(gPMHaltLock);
3033 for (unsigned int i = 0 ; i < numWorkers; i++)
3034 {
3035 if (workers[i])
3036 PMHaltWorker::checkTimeout(workers[i], &now);
3037 }
3038 IOLockLock(gPMHaltLock);
3039 }
3040 }
3041 IOLockUnlock(gPMHaltLock);
3042
3043 // Release all workers
3044
3045 for (unsigned int i = 0; i < numWorkers; i++)
3046 {
3047 if (workers[i])
3048 workers[i]->release();
3049 // worker also retained by it's own thread
3050 }
3051
3052 done:
3053 DEBUG_LOG("%s done\n", __FUNCTION__);
3054 return;
3055 }
3056
3057 #if DEBUG_TEST
3058 // debug - exercise notifySystemShutdown()
3059 bool IOPMrootDomain::serializeProperties( OSSerialize * s ) const
3060 {
3061 IOPMrootDomain * root = (IOPMrootDomain *) this;
3062 notifySystemShutdown( root, kIOMessageSystemWillPowerOff );
3063 return( super::serializeProperties(s) );
3064 }
3065 #endif
3066
3067 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3068
3069
3070
3071 #undef super
3072 #define super OSObject
3073 OSDefineMetaClassAndStructors(PMSettingObject, OSObject)
3074
3075 void PMSettingObject::setPMSetting(const OSSymbol *type, OSObject *obj)
3076 {
3077 (*func)(target, type, obj, refcon);
3078 }
3079
3080 /*
3081 * Static constructor/initializer for PMSettingObject
3082 */
3083 PMSettingObject *PMSettingObject::pmSettingObject(
3084 IOPMrootDomain *parent_arg,
3085 IOPMSettingControllerCallback handler_arg,
3086 OSObject *target_arg,
3087 uintptr_t refcon_arg,
3088 uint32_t supportedPowerSources,
3089 const OSSymbol * settings[])
3090 {
3091 uint32_t objCount = 0;
3092 PMSettingObject *pmso;
3093
3094 if( !parent_arg || !handler_arg || !settings ) return NULL;
3095
3096 // count OSSymbol entries in NULL terminated settings array
3097 while( settings[objCount] ) {
3098 objCount++;
3099 }
3100 if(0 == objCount) return NULL;
3101
3102 pmso = new PMSettingObject;
3103 if(!pmso || !pmso->init()) return NULL;
3104
3105 pmso->parent = parent_arg;
3106 pmso->func = handler_arg;
3107 pmso->target = target_arg;
3108 pmso->refcon = refcon_arg;
3109 pmso->releaseAtCount = objCount + 1; // release when it has count+1 retains
3110
3111 pmso->publishedFeatureID = (uint32_t *)IOMalloc(sizeof(uint32_t)*objCount);
3112 if(pmso->publishedFeatureID) {
3113 for(unsigned int i=0; i<objCount; i++) {
3114 // Since there is now at least one listener to this setting, publish
3115 // PM root domain support for it.
3116 parent_arg->publishFeature( settings[i]->getCStringNoCopy(),
3117 supportedPowerSources, &pmso->publishedFeatureID[i] );
3118 }
3119 }
3120
3121 return pmso;
3122 }
3123
3124 void PMSettingObject::free(void)
3125 {
3126 OSCollectionIterator *settings_iter;
3127 OSSymbol *sym;
3128 OSArray *arr;
3129 int arr_idx;
3130 int i;
3131 int objCount = releaseAtCount - 1;
3132
3133 if(publishedFeatureID) {
3134 for(i=0; i<objCount; i++) {
3135 if(0 != publishedFeatureID[i]) {
3136 parent->removePublishedFeature( publishedFeatureID[i] );
3137 }
3138 }
3139
3140 IOFree(publishedFeatureID, sizeof(uint32_t) * objCount);
3141 }
3142
3143 IORecursiveLockLock(parent->settingsCtrlLock);
3144
3145 // Search each PM settings array in the kernel.
3146 settings_iter = OSCollectionIterator::withCollection(parent->settingsCallbacks);
3147 if(settings_iter)
3148 {
3149 while(( sym = OSDynamicCast(OSSymbol, settings_iter->getNextObject()) ))
3150 {
3151 arr = (OSArray *)parent->settingsCallbacks->getObject(sym);
3152 arr_idx = arr->getNextIndexOfObject(this, 0);
3153 if(-1 != arr_idx) {
3154 // 'this' was found in the array; remove it
3155 arr->removeObject(arr_idx);
3156 }
3157 }
3158
3159 settings_iter->release();
3160 }
3161
3162 IORecursiveLockUnlock(parent->settingsCtrlLock);
3163
3164 super::free();
3165 }
3166
3167 void PMSettingObject::taggedRelease(const void *tag, const int when) const
3168 {
3169 // We have n+1 retains - 1 per array that this PMSettingObject is a member
3170 // of, and 1 retain to ourself. When we get a release with n+1 retains
3171 // remaining, we go ahead and free ourselves, cleaning up array pointers
3172 // in free();
3173
3174 super::taggedRelease(tag, releaseAtCount);
3175 }
3176
3177
3178
3179 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3180
3181 #undef super
3182 #define super IOService
3183
3184 OSDefineMetaClassAndStructors(IORootParent, IOService)
3185
3186 // This array exactly parallels the state array for the root domain.
3187 // Power state changes initiated by a device can be vetoed by a client of the device, and
3188 // power state changes initiated by the parent of a device cannot be vetoed by a client of the device,
3189 // so when the root domain wants a power state change that cannot be vetoed (e.g. demand sleep), it asks
3190 // its parent to make the change. That is the reason for this complexity.
3191
3192 static IOPMPowerState patriarchPowerStates[number_of_power_states] = {
3193 {1,0,0,0,0,0,0,0,0,0,0,0}, // off
3194 {1,0,RESTART_POWER,0,0,0,0,0,0,0,0,0}, // reset
3195 {1,0,SLEEP_POWER,0,0,0,0,0,0,0,0,0}, // sleep
3196 {1,0,DOZE_POWER,0,0,0,0,0,0,0,0,0}, // doze
3197 {1,0,ON_POWER,0,0,0,0,0,0,0,0,0} // running
3198 };
3199
3200 bool IORootParent::start ( IOService * nub )
3201 {
3202 mostRecentChange = ON_STATE;
3203 super::start(nub);
3204 PMinit();
3205 youAreRoot();
3206 registerPowerDriver(this,patriarchPowerStates,number_of_power_states);
3207 wakeSystem();
3208 powerOverrideOnPriv();
3209 return true;
3210 }
3211
3212
3213 void IORootParent::shutDownSystem ( void )
3214 {
3215 mostRecentChange = OFF_STATE;
3216 changePowerStateToPriv(OFF_STATE);
3217 }
3218
3219
3220 void IORootParent::restartSystem ( void )
3221 {
3222 mostRecentChange = RESTART_STATE;
3223 changePowerStateToPriv(RESTART_STATE);
3224 }
3225
3226
3227 void IORootParent::sleepSystem ( void )
3228 {
3229 mostRecentChange = SLEEP_STATE;
3230 changePowerStateToPriv(SLEEP_STATE);
3231 }
3232
3233
3234 void IORootParent::dozeSystem ( void )
3235 {
3236 mostRecentChange = DOZE_STATE;
3237 changePowerStateToPriv(DOZE_STATE);
3238 }
3239
3240 // Called in demand sleep when sleep discovered to be impossible after actually attaining that state.
3241 // This brings the parent to doze, which allows the root to step up from sleep to doze.
3242
3243 // In idle sleep, do nothing because the parent is still on and the root can freely change state.
3244
3245 void IORootParent::sleepToDoze ( void )
3246 {
3247 if ( mostRecentChange == SLEEP_STATE ) {
3248 changePowerStateToPriv(DOZE_STATE);
3249 }
3250 }
3251
3252
3253 void IORootParent::wakeSystem ( void )
3254 {
3255 mostRecentChange = ON_STATE;
3256 changePowerStateToPriv(ON_STATE);
3257 }
3258
3259 IOReturn IORootParent::changePowerStateToPriv ( unsigned long ordinal )
3260 {
3261 IOReturn ret;
3262
3263 if( (SLEEP_STATE == ordinal) && sleepSupportedPEFunction )
3264 {
3265
3266 // Determine if the machine supports sleep, or must doze.
3267 ret = getPlatform()->callPlatformFunction(
3268 sleepSupportedPEFunction, false,
3269 NULL, NULL, NULL, NULL);
3270
3271 // If the machine only supports doze, the callPlatformFunction call
3272 // boils down toIOPMrootDomain::setSleepSupported(kPCICantSleep),
3273 // otherwise nothing.
3274 }
3275
3276 return super::changePowerStateToPriv(ordinal);
3277 }
3278