2 * Copyright (c) 1998-2005 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
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 "RootDomainUserClient.h"
39 #include "IOKit/pwr_mgt/IOPowerConnection.h"
40 #include "IOPMPowerStateQueue.h"
41 #include <IOKit/IOCatalogue.h>
42 #include <IOKit/IOHibernatePrivate.h>
48 extern "C" void kprintf(const char *, ...);
50 extern const IORegistryPlane
* gIOPowerPlane
;
52 IOReturn
broadcast_aggressiveness ( OSObject
*, void *, void *, void *, void * );
53 static void sleepTimerExpired(thread_call_param_t
);
54 static void wakeupClamshellTimerExpired ( thread_call_param_t us
);
57 #define number_of_power_states 5
59 #define RESTART_STATE 1
64 #define ON_POWER kIOPMPowerOn
65 #define RESTART_POWER kIOPMRestart
66 #define SLEEP_POWER kIOPMAuxPowerOn
67 #define DOZE_POWER kIOPMDoze
69 static IOPMPowerState ourPowerStates
[number_of_power_states
] = {
70 {1,0, 0, 0,0,0,0,0,0,0,0,0}, // state 0, off
71 {1,kIOPMRestartCapability
, kIOPMRestart
, RESTART_POWER
,0,0,0,0,0,0,0,0}, // state 1, restart
72 {1,kIOPMSleepCapability
, kIOPMSleep
, SLEEP_POWER
,0,0,0,0,0,0,0,0}, // state 2, sleep
73 {1,kIOPMDoze
, kIOPMDoze
, DOZE_POWER
,0,0,0,0,0,0,0,0}, // state 3, doze
74 {1,kIOPMPowerOn
, kIOPMPowerOn
, ON_POWER
,0,0,0,0,0,0,0,0}, // state 4, on
77 // RESERVED IOPMrootDomain class variables
78 #define diskSyncCalloutEntry _reserved->diskSyncCalloutEntry
79 #define _settingController _reserved->_settingController
80 #define _batteryLocationNotifier _reserved->_batteryLocationNotifier
81 #define _displayWranglerNotifier _reserved->_displayWranglerNotifier
84 static IOPMrootDomain
* gRootDomain
;
85 static UInt32 gSleepOrShutdownPending
= 0;
88 #define super IOService
89 OSDefineMetaClassAndStructors(IOPMrootDomain
,IOService
)
93 IONotifier
* registerSleepWakeInterest(IOServiceInterestHandler handler
, void * self
, void * ref
)
95 return gRootDomain
->registerInterest( gIOGeneralInterest
, handler
, self
, ref
);
98 IONotifier
* registerPrioritySleepWakeInterest(IOServiceInterestHandler handler
, void * self
, void * ref
)
100 return gRootDomain
->registerInterest( gIOPriorityPowerStateInterest
, handler
, self
, ref
);
103 IOReturn
acknowledgeSleepWakeNotification(void * PMrefcon
)
105 return gRootDomain
->allowPowerChange ( (unsigned long)PMrefcon
);
108 IOReturn
vetoSleepWakeNotification(void * PMrefcon
)
110 return gRootDomain
->cancelPowerChange ( (unsigned long)PMrefcon
);
113 IOReturn
rootDomainRestart ( void )
115 return gRootDomain
->restartSystem();
118 IOReturn
rootDomainShutdown ( void )
120 return gRootDomain
->shutdownSystem();
123 void IOSystemShutdownNotification ( void )
125 IOCatalogue::disableExternalLinker();
126 for ( int i
= 0; i
< 100; i
++ )
128 if ( OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending
) ) break;
133 int sync_internal(void);
137 A device is always in the highest power state which satisfies its driver, its policy-maker, and any power domain
138 children it has, but within the constraint of the power state provided by its parent. The driver expresses its desire by
139 calling changePowerStateTo(), the policy-maker expresses its desire by calling changePowerStateToPriv(), and the children
140 express their desires by calling requestPowerDomainState().
142 The Root Power Domain owns the policy for idle and demand sleep and doze for the system. It is a power-managed IOService just
143 like the others in the system. It implements several power states which correspond to what we see as Sleep, Doze, etc.
145 The sleep/doze policy is as follows:
146 Sleep and Doze are prevented if the case is open so that nobody will think the machine is off and plug/unplug cards.
147 Sleep and Doze are prevented if the sleep timeout slider in the preferences panel is at zero.
148 The system cannot Sleep, but can Doze if some object in the tree is in a power state marked kIOPMPreventSystemSleep.
150 These three conditions are enforced using the "driver clamp" by calling changePowerStateTo(). For example, if the case is
151 opened, changePowerStateTo(ON_STATE) is called to hold the system on regardless of the desires of the children of the root or
152 the state of the other clamp.
154 Demand Sleep/Doze is initiated by pressing the front panel power button, closing the clamshell, or selecting the menu item.
155 In this case the root's parent actually initiates the power state change so that the root has no choice and does not give
156 applications the opportunity to veto the change.
158 Idle Sleep/Doze occurs if no objects in the tree are in a state marked kIOPMPreventIdleSleep. When this is true, the root's
159 children are not holding the root on, so it sets the "policy-maker clamp" by calling changePowerStateToPriv(ON_STATE)
160 to hold itself on until the sleep timer expires. This timer is set for the difference between the sleep timeout slider and
161 the larger of the display dim timeout slider and the disk spindown timeout slider in the Preferences panel. For example, if
162 the system is set to sleep after thirty idle minutes, and the display and disk are set to sleep after five idle minutes,
163 when there is no longer an object in the tree holding the system out of Idle Sleep (via kIOPMPreventIdleSleep), the root
164 sets its timer for 25 minutes (30 - 5). When the timer expires, it releases its clamp and now nothing is holding it awake,
167 Demand sleep is prevented when the system is booting. When preferences are transmitted by the loginwindow at the end of
168 boot, a flag is cleared, and this allows subsequent Demand Sleep.
170 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
171 a clamp, but sets a flag which is noticed before actually sleeping the kernel. If the flag is set, the root steps up
172 one power state from Sleep to Doze, and any objects in the tree for which this is relevent will act appropriately (USB and
173 ADB will turn on again so that they can wake the system out of Doze (keyboard/mouse activity will cause the Display Wrangler
177 // **********************************************************************************
179 IOPMrootDomain
* IOPMrootDomain::construct( void )
181 IOPMrootDomain
*root
;
183 root
= new IOPMrootDomain
;
190 // **********************************************************************************
192 static void disk_sync_callout(thread_call_param_t p0
, thread_call_param_t p1
)
194 IOService
*rootDomain
= (IOService
*) p0
;
195 unsigned long pmRef
= (unsigned long) p1
;
197 IOHibernateSystemSleep();
199 rootDomain
->allowPowerChange(pmRef
);
202 // **********************************************************************************
205 // We don't do much here. The real initialization occurs when the platform
206 // expert informs us we are the root.
207 // **********************************************************************************
210 bool IOPMrootDomain::start ( IOService
* nub
)
212 OSDictionary
*tmpDict
;
214 pmPowerStateQueue
= 0;
216 _reserved
= (ExpansionData
*)IOMalloc(sizeof(ExpansionData
));
217 if(!_reserved
) return false;
224 setProperty("IOSleepSupported","");
227 sleepIsSupported
= true;
228 systemBooting
= true;
229 ignoringClamshell
= true;
231 idleSleepPending
= false;
235 _settingController
= NULL
;
236 ignoringClamshellDuringWakeup
= false;
238 tmpDict
= OSDictionary::withCapacity(1);
239 setProperty(kRootDomainSupportedFeatures
, tmpDict
);
242 pm_vars
->PMworkloop
= IOWorkLoop::workLoop();
243 pmPowerStateQueue
= IOPMPowerStateQueue::PMPowerStateQueue(this);
244 pm_vars
->PMworkloop
->addEventSource(pmPowerStateQueue
);
246 featuresDictLock
= IOLockAlloc();
248 extraSleepTimer
= thread_call_allocate((thread_call_func_t
)sleepTimerExpired
, (thread_call_param_t
) this);
249 clamshellWakeupIgnore
= thread_call_allocate((thread_call_func_t
)wakeupClamshellTimerExpired
, (thread_call_param_t
) this);
250 diskSyncCalloutEntry
= thread_call_allocate(&disk_sync_callout
, (thread_call_param_t
) this);
253 patriarch
= new IORootParent
;
255 patriarch
->attach(this);
256 patriarch
->start(this);
257 patriarch
->youAreRoot();
258 patriarch
->wakeSystem();
259 patriarch
->addPowerChild(this);
261 registerPowerDriver(this,ourPowerStates
,number_of_power_states
);
263 setPMRootDomain(this);
264 // set a clamp until we sleep
265 changePowerStateToPriv(ON_STATE
);
267 // install power change handler
268 registerPrioritySleepWakeInterest( &sysPowerDownHandler
, this, 0);
270 // Register for a notification when IODisplayWrangler is published
271 _displayWranglerNotifier
= addNotification( gIOPublishNotification
,
272 serviceMatching("IODisplayWrangler"),
273 &displayWranglerPublished
, this, 0);
275 _batteryLocationNotifier
= addNotification( gIOPublishNotification
,
276 resourceMatching("battery"),
277 &batteryLocationPublished
, this, this);
279 const OSSymbol
*ucClassName
= OSSymbol::withCStringNoCopy("RootDomainUserClient");
280 setProperty(gIOUserClientClassKey
, (OSObject
*) ucClassName
);
281 ucClassName
->release();
283 IORegistryEntry
*temp_entry
= NULL
;
284 if( (temp_entry
= IORegistryEntry::fromPath("mac-io/battery", gIODTPlane
)) ||
285 (temp_entry
= IORegistryEntry::fromPath("mac-io/via-pmu/battery", gIODTPlane
)))
287 // If this machine has a battery, publish the fact that the backlight
289 // Notice similar call in IOPMrootDomain::batteryLocationPublished() to
290 // detect batteries on SMU machines.
291 publishFeature("DisplayDims");
292 temp_entry
->release();
295 IOHibernateSystemInit(this);
297 registerService(); // let clients find us
302 IOReturn
IOPMrootDomain::setPMSetting(int type
, OSNumber
*n
)
304 if(_settingController
&& _settingController
->func
) {
306 seconds
= n
->unsigned32BitValue();
307 return (*(_settingController
->func
))(type
, seconds
, _settingController
->refcon
);
309 return kIOReturnNoDevice
;
313 // **********************************************************************************
316 // Receive a setProperty call
317 // The "System Boot" property means the system is completely booted.
318 // **********************************************************************************
319 IOReturn
IOPMrootDomain::setProperties ( OSObject
*props_obj
)
321 IOReturn return_value
= kIOReturnSuccess
;
322 OSDictionary
*dict
= OSDynamicCast(OSDictionary
, props_obj
);
326 const OSSymbol
*boot_complete_string
= OSSymbol::withCString("System Boot Complete");
327 const OSSymbol
*power_button_string
= OSSymbol::withCString("DisablePowerButtonSleep");
328 const OSSymbol
*stall_halt_string
= OSSymbol::withCString("StallSystemAtHalt");
329 const OSSymbol
*auto_wake_string
= OSSymbol::withCString("wake");
330 const OSSymbol
*auto_power_string
= OSSymbol::withCString("poweron");
331 const OSSymbol
*wakeonring_string
= OSSymbol::withCString("WakeOnRing");
332 const OSSymbol
*fileserver_string
= OSSymbol::withCString("AutoRestartOnPowerLoss");
333 const OSSymbol
*wakeonlid_string
= OSSymbol::withCString("WakeOnLid");
334 const OSSymbol
*wakeonac_string
= OSSymbol::withCString("WakeOnACChange");
335 const OSSymbol
*hibernatemode_string
= OSSymbol::withCString(kIOHibernateModeKey
);
336 const OSSymbol
*hibernatefile_string
= OSSymbol::withCString(kIOHibernateFileKey
);
337 const OSSymbol
*hibernatefreeratio_string
= OSSymbol::withCString(kIOHibernateFreeRatioKey
);
338 const OSSymbol
*hibernatefreetime_string
= OSSymbol::withCString(kIOHibernateFreeTimeKey
);
339 const OSSymbol
*timezone_string
= OSSymbol::withCString("TimeZoneOffsetSeconds");
343 return_value
= kIOReturnBadArgument
;
348 && boot_complete_string
349 && dict
->getObject(boot_complete_string
))
351 systemBooting
= false;
355 if( power_button_string
356 && (b
= OSDynamicCast(OSBoolean
, dict
->getObject(power_button_string
))) )
358 setProperty(power_button_string
, b
);
361 if( stall_halt_string
362 && (b
= OSDynamicCast(OSBoolean
, dict
->getObject(stall_halt_string
))) )
364 setProperty(stall_halt_string
, b
);
367 if ( hibernatemode_string
368 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(hibernatemode_string
))))
370 setProperty(hibernatemode_string
, n
);
372 if ( hibernatefreeratio_string
373 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(hibernatefreeratio_string
))))
375 setProperty(hibernatefreeratio_string
, n
);
377 if ( hibernatefreetime_string
378 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(hibernatefreetime_string
))))
380 setProperty(hibernatefreetime_string
, n
);
382 if ( hibernatefile_string
383 && (str
= OSDynamicCast(OSString
, dict
->getObject(hibernatefile_string
))))
385 setProperty(hibernatefile_string
, str
);
388 // Relay AutoWake setting to its controller
390 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(auto_wake_string
))) )
392 return_value
= setPMSetting(kIOPMAutoWakeSetting
, n
);
393 if(kIOReturnSuccess
!= return_value
) goto exit
;
396 // Relay AutoPower setting to its controller
397 if( auto_power_string
398 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(auto_power_string
))) )
400 return_value
= setPMSetting(kIOPMAutoPowerOnSetting
, n
);
401 if(kIOReturnSuccess
!= return_value
) goto exit
;
404 // Relay WakeOnRing setting to its controller
405 if( wakeonring_string
406 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(wakeonring_string
))) )
408 return_value
= setPMSetting(kIOPMWakeOnRingSetting
, n
);
409 if(kIOReturnSuccess
!= return_value
) goto exit
;
412 // Relay FileServer setting to its controller
413 if( fileserver_string
414 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(fileserver_string
))) )
416 return_value
= setPMSetting(kIOPMAutoRestartOnPowerLossSetting
, n
);
417 if(kIOReturnSuccess
!= return_value
) goto exit
;
420 // Relay WakeOnLid setting to its controller
422 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(wakeonlid_string
))) )
424 return_value
= setPMSetting(kIOPMWakeOnLidSetting
, n
);
425 if(kIOReturnSuccess
!= return_value
) goto exit
;
428 // Relay WakeOnACChange setting to its controller
430 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(wakeonac_string
))) )
432 return_value
= setPMSetting(kIOPMWakeOnACChangeSetting
, n
);
433 if(kIOReturnSuccess
!= return_value
) goto exit
;
436 // Relay timezone offset in seconds to SMU
438 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(timezone_string
))) )
440 return_value
= setPMSetting(kIOPMTimeZoneSetting
, n
);
441 if(kIOReturnSuccess
!= return_value
) goto exit
;
446 if(boot_complete_string
) boot_complete_string
->release();
447 if(power_button_string
) power_button_string
->release();
448 if(stall_halt_string
) stall_halt_string
->release();
449 if(auto_wake_string
) auto_wake_string
->release();
450 if(auto_power_string
) auto_power_string
->release();
451 if(wakeonring_string
) wakeonring_string
->release();
452 if(fileserver_string
) fileserver_string
->release();
453 if(wakeonlid_string
) wakeonlid_string
->release();
454 if(wakeonac_string
) wakeonac_string
->release();
455 if(timezone_string
) timezone_string
->release();
460 //*********************************************************************************
463 // Power Managment is informing us that we are the root power domain.
464 // We know we are not the root however, since we have just instantiated a parent
465 // for ourselves and made it the root. We override this method so it will have
467 //*********************************************************************************
468 IOReturn
IOPMrootDomain::youAreRoot ( void )
473 // **********************************************************************************
477 // **********************************************************************************
478 void IOPMrootDomain::command_received ( void * w
, void * x
, void * y
, void * z
)
480 super::command_received(w
,x
,y
,z
);
484 // **********************************************************************************
485 // broadcast_aggressiveness
487 // **********************************************************************************
488 IOReturn
broadcast_aggressiveness ( OSObject
* root
, void * x
, void * y
, void *, void * )
490 ((IOPMrootDomain
*)root
)->broadcast_it((unsigned long)x
,(unsigned long)y
);
495 // **********************************************************************************
498 // We are behind the command gate to broadcast an aggressiveness factor. We let the
499 // superclass do it, but we need to snoop on factors that affect idle sleep.
500 // **********************************************************************************
501 void IOPMrootDomain::broadcast_it (unsigned long type
, unsigned long value
)
503 super::setAggressiveness(type
,value
);
505 // Save user's spin down timer to restore after we replace it for idle sleep
506 if( type
== kPMMinutesToSpinDown
) user_spindown
= value
;
508 // Use longestNonSleepSlider to calculate dimming adjust idle sleep timer
509 longestNonSleepSlider
= pm_vars
->current_aggressiveness_values
[kPMMinutesToDim
];
512 if ( type
== kPMMinutesToSleep
) {
513 if ( (sleepSlider
== 0) && (value
!= 0) ) {
515 // idle sleep is now enabled, maybe sleep now
519 if ( sleepSlider
== 0 ) {
520 // idle sleep is now disabled
522 // make sure we're powered
523 patriarch
->wakeSystem();
526 if ( sleepSlider
> longestNonSleepSlider
) {
527 extraSleepDelay
= sleepSlider
- longestNonSleepSlider
;
535 // **********************************************************************************
538 // **********************************************************************************
539 static void sleepTimerExpired ( thread_call_param_t us
)
541 ((IOPMrootDomain
*)us
)->handleSleepTimerExpiration();
545 static void wakeupClamshellTimerExpired ( thread_call_param_t us
)
547 ((IOPMrootDomain
*)us
)->stopIgnoringClamshellEventsDuringWakeup();
551 // **********************************************************************************
552 // handleSleepTimerExpiration
554 // The time between the sleep idle timeout and the next longest one has elapsed.
555 // It's time to sleep. Start that by removing the clamp that's holding us awake.
556 // **********************************************************************************
557 void IOPMrootDomain::handleSleepTimerExpiration ( void )
559 // accelerate disk spin down if spin down timer is non-zero (zero = never spin down)
560 if(0 != user_spindown
)
561 setQuickSpinDownTimeout();
568 void IOPMrootDomain::stopIgnoringClamshellEventsDuringWakeup(void)
572 // Allow clamshell-induced sleep now
573 ignoringClamshellDuringWakeup
= false;
575 if ((state
= getProperty(kAppleClamshellStateKey
)))
576 publishResource(kAppleClamshellStateKey
, state
);
579 //*********************************************************************************
582 // Some aggressiveness factor has changed. We broadcast it to the hierarchy while on
583 // the Power Mangement workloop thread. This enables objects in the
584 // hierarchy to successfully alter their idle timers, which are all on the
586 //*********************************************************************************
588 static int pmsallsetup
= 0;
590 IOReturn
IOPMrootDomain::setAggressiveness ( unsigned long type
, unsigned long newLevel
)
593 if(pmsExperimental
& 3) kprintf("setAggressiveness: type = %08X, newlevel = %08X\n", type
, newLevel
);
594 if(pmsExperimental
& 1) { /* Is experimental mode enabled? */
595 if(pmsInstalled
&& (type
== kPMSetProcessorSpeed
)) { /* We want to look at all processor speed changes if stepper is installed */
596 if(pmsallsetup
) return kIOReturnSuccess
; /* If already running, just eat this */
597 kprintf("setAggressiveness: starting stepper...\n");
598 pmsallsetup
= 1; /* Remember we did this */
600 pmsStart(); /* Get it all started up... */
601 return kIOReturnSuccess
; /* Leave now... */
606 if ( pm_vars
->PMcommandGate
) {
607 pm_vars
->PMcommandGate
->runAction(broadcast_aggressiveness
,(void *)type
,(void *)newLevel
);
610 return kIOReturnSuccess
;
614 // **********************************************************************************
617 // **********************************************************************************
618 IOReturn
IOPMrootDomain::sleepSystem ( void )
620 //kprintf("sleep demand received\n");
621 if ( !systemBooting
&& allowSleep
&& sleepIsSupported
) {
622 patriarch
->sleepSystem();
624 return kIOReturnSuccess
;
626 if ( !systemBooting
&& allowSleep
&& !sleepIsSupported
) {
627 patriarch
->dozeSystem();
628 return kIOReturnSuccess
;
630 return kIOReturnSuccess
;
634 // **********************************************************************************
637 // **********************************************************************************
638 IOReturn
IOPMrootDomain::shutdownSystem ( void )
640 //patriarch->shutDownSystem();
641 return kIOReturnUnsupported
;
645 // **********************************************************************************
648 // **********************************************************************************
649 IOReturn
IOPMrootDomain::restartSystem ( void )
651 //patriarch->restartSystem();
652 return kIOReturnUnsupported
;
656 // **********************************************************************************
659 // This overrides powerChangeDone in IOService.
661 // Finder sleep and idle sleep move us from the ON state to the SLEEP_STATE.
663 // If we just finished going to the SLEEP_STATE, and the platform is capable of true sleep,
664 // sleep the kernel. Otherwise switch up to the DOZE_STATE which will keep almost
665 // everything as off as it can get.
667 // **********************************************************************************
668 void IOPMrootDomain::powerChangeDone ( unsigned long previousState
)
670 OSNumber
* propertyPtr
;
671 unsigned short theProperty
;
672 AbsoluteTime deadline
;
674 switch ( pm_vars
->myCurrentState
) {
676 if ( canSleep
&& sleepIsSupported
)
678 // re-enable this timer for next sleep
679 idleSleepPending
= false;
681 IOLog("System %sSleep\n", gIOHibernateState
? "Safe" : "");
683 IOHibernateSystemHasSlept();
685 pm_vars
->thePlatform
->sleepKernel();
687 // The CPU(s) are off at this point. When they're awakened by CPU interrupt,
688 // code will resume execution here.
690 // Now we're waking...
691 IOHibernateSystemWake();
693 // stay awake for at least 30 seconds
694 clock_interval_to_deadline(30, kSecondScale
, &deadline
);
695 thread_call_enter_delayed(extraSleepTimer
, deadline
);
696 // this gets turned off when we sleep again
697 idleSleepPending
= true;
699 // Ignore closed clamshell during wakeup and for a few seconds
700 // after wakeup is complete
701 ignoringClamshellDuringWakeup
= true;
703 // sleep transition complete
704 gSleepOrShutdownPending
= 0;
706 // trip the reset of the calendar clock
707 clock_wakeup_calendar();
710 patriarch
->wakeSystem();
712 // early stage wake notification
713 tellClients(kIOMessageSystemWillPowerOn
);
715 // tell the tree we're waking
716 IOLog("System %sWake\n", gIOHibernateState
? "SafeSleep " : "");
719 // Allow drivers to request extra processing time before clamshell
720 // sleep if kIOREMSleepEnabledKey is present.
721 // Ignore clamshell events for at least 5 seconds
722 if(getProperty(kIOREMSleepEnabledKey
)) {
723 // clamshellWakeupIgnore callout clears ignoreClamshellDuringWakeup bit
724 clock_interval_to_deadline(5, kSecondScale
, &deadline
);
725 if(clamshellWakeupIgnore
) thread_call_enter_delayed(clamshellWakeupIgnore
, deadline
);
726 } else ignoringClamshellDuringWakeup
= false;
728 // Find out what woke us
729 propertyPtr
= OSDynamicCast(OSNumber
,getProperty("WakeEvent"));
731 theProperty
= propertyPtr
->unsigned16BitValue();
732 IOLog("Wake event %04x\n",theProperty
);
733 if ( (theProperty
& 0x0008) || //lid
734 (theProperty
& 0x0800) || // front panel button
735 (theProperty
& 0x0020) || // external keyboard
736 (theProperty
& 0x0001) ) { // internal keyboard
737 // We've identified the wakeup event as UI driven
741 // Since we can't identify the wakeup event, treat it as UI activity
745 // Wake for thirty seconds
746 changePowerStateToPriv(ON_STATE
);
747 powerOverrideOffPriv();
749 // allow us to step up a power state
750 patriarch
->sleepToDoze();
752 changePowerStateToPriv(DOZE_STATE
);
757 if ( previousState
!= DOZE_STATE
)
759 IOLog("System Doze\n");
761 // re-enable this timer for next sleep
762 idleSleepPending
= false;
763 gSleepOrShutdownPending
= 0;
767 IOLog("System Restart\n");
768 PEHaltRestart(kPERestartCPU
);
772 IOLog("System Halt\n");
773 PEHaltRestart(kPEHaltCPU
);
779 // **********************************************************************************
782 // The Display Wrangler calls here when it switches to its highest state. If the
783 // system is currently dozing, allow it to wake by making sure the parent is
785 // **********************************************************************************
786 void IOPMrootDomain::wakeFromDoze( void )
788 if ( pm_vars
->myCurrentState
== DOZE_STATE
)
790 // reset this till next attempt
792 powerOverrideOffPriv();
794 // early wake notification
795 tellClients(kIOMessageSystemWillPowerOn
);
797 // allow us to wake if children so desire
798 patriarch
->wakeSystem();
803 // **********************************************************************************
806 // Adds a new feature to the supported features dictionary
809 // **********************************************************************************
810 void IOPMrootDomain::publishFeature( const char * feature
)
812 if(featuresDictLock
) IOLockLock(featuresDictLock
);
813 OSDictionary
*features
=
814 (OSDictionary
*) getProperty(kRootDomainSupportedFeatures
);
816 if ( features
&& OSDynamicCast(OSDictionary
, features
))
817 features
= OSDictionary::withDictionary(features
);
819 features
= OSDictionary::withCapacity(1);
821 features
->setObject(feature
, kOSBooleanTrue
);
822 setProperty(kRootDomainSupportedFeatures
, features
);
824 if(featuresDictLock
) IOLockUnlock(featuresDictLock
);
828 void IOPMrootDomain::unIdleDevice( IOService
*theDevice
, unsigned long theState
)
830 if(pmPowerStateQueue
)
831 pmPowerStateQueue
->unIdleOccurred(theDevice
, theState
);
834 void IOPMrootDomain::announcePowerSourceChange( void )
836 IORegistryEntry
*_batteryRegEntry
= (IORegistryEntry
*) getProperty("BatteryEntry");
838 // (if possible) re-publish power source state under IOPMrootDomain
839 // (only done if the battery controller publishes an IOResource defining battery location)
843 batt_info
= (OSArray
*) _batteryRegEntry
->getProperty(kIOBatteryInfoKey
);
845 setProperty(kIOBatteryInfoKey
, batt_info
);
848 messageClients(kIOPMMessageBatteryStatusHasChanged
);
851 IOReturn
IOPMrootDomain::registerPMSettingController
852 (IOPMSettingControllerCallback func
, void *info
)
854 if(_settingController
) return kIOReturnExclusiveAccess
;
856 _settingController
= (PMSettingCtrl
*)IOMalloc(sizeof(PMSettingCtrl
));
857 if(!_settingController
) return kIOReturnNoMemory
;
859 _settingController
->func
= func
;
860 _settingController
->refcon
= info
;
861 return kIOReturnSuccess
;
865 //*********************************************************************************
866 // receivePowerNotification
868 // The power controller is notifying us of a hardware-related power management
869 // event that we must handle. This is a result of an 'environment' interrupt from
870 // the power mgt micro.
871 //*********************************************************************************
873 IOReturn
IOPMrootDomain::receivePowerNotification (UInt32 msg
)
875 if (msg
& kIOPMOverTemp
)
877 IOLog("Power Management received emergency overtemp signal. Going to sleep.");
878 (void) sleepSystem ();
880 if (msg
& kIOPMSetDesktopMode
)
882 desktopMode
= (0 != (msg
& kIOPMSetValue
));
883 msg
&= ~(kIOPMSetDesktopMode
| kIOPMSetValue
);
885 if (msg
& kIOPMSetACAdaptorConnected
)
887 acAdaptorConnect
= (0 != (msg
& kIOPMSetValue
));
888 msg
&= ~(kIOPMSetACAdaptorConnected
| kIOPMSetValue
);
890 if (msg
& kIOPMEnableClamshell
)
892 ignoringClamshell
= false;
894 if (msg
& kIOPMDisableClamshell
)
896 ignoringClamshell
= true;
899 if (msg
& kIOPMProcessorSpeedChange
)
901 IOService
*pmu
= waitForService(serviceMatching("ApplePMU"));
902 pmu
->callPlatformFunction("prepareForSleep", false, 0, 0, 0, 0);
903 pm_vars
->thePlatform
->sleepKernel();
904 pmu
->callPlatformFunction("recoverFromSleep", false, 0, 0, 0, 0);
907 if (msg
& kIOPMSleepNow
)
909 (void) sleepSystem ();
912 if (msg
& kIOPMPowerEmergency
)
914 (void) sleepSystem ();
917 if (msg
& kIOPMClamshellClosed
)
919 if ( !ignoringClamshell
&& !ignoringClamshellDuringWakeup
920 && (!desktopMode
|| !acAdaptorConnect
) )
923 (void) sleepSystem ();
927 if (msg
& kIOPMPowerButton
)
929 // toggle state of sleep/wake
931 if ( pm_vars
->myCurrentState
== DOZE_STATE
)
933 // yes, tell the tree we're waking
935 // wake the Display Wrangler
939 // Check that power button sleep is enabled
940 if(kOSBooleanTrue
!= getProperty(OSString::withCString("DisablePowerButtonSleep")))
945 // if the case has been closed, we allow
946 // the machine to be put to sleep or to idle sleep
948 if ( (msg
& kIOPMAllowSleep
) && !allowSleep
)
954 // if the case has been opened, we disallow sleep/doze
956 if (msg
& kIOPMPreventSleep
) {
959 if ( pm_vars
->myCurrentState
== DOZE_STATE
) {
960 // yes, tell the tree we're waking
963 // wake the Display Wrangler
967 // make sure we have power to clamp
968 patriarch
->wakeSystem();
976 //*********************************************************************************
979 //*********************************************************************************
981 void IOPMrootDomain::setSleepSupported( IOOptionBits flags
)
983 if ( flags
& kPCICantSleep
)
987 platformSleepSupport
= flags
;
992 //*********************************************************************************
993 // requestPowerDomainState
995 // The root domain intercepts this call to the superclass.
997 // If the clamp bit is not set in the desire, then the child doesn't need the power
998 // state it's requesting; it just wants it. The root ignores desires but not needs.
999 // If the clamp bit is not set, the root takes it that the child can tolerate no
1000 // power and interprets the request accordingly. If all children can thus tolerate
1001 // no power, we are on our way to idle sleep.
1002 //*********************************************************************************
1004 IOReturn
IOPMrootDomain::requestPowerDomainState ( IOPMPowerFlags desiredState
, IOPowerConnection
* whichChild
, unsigned long specification
)
1008 IOPowerConnection
*connection
;
1009 unsigned long powerRequestFlag
= 0;
1010 IOPMPowerFlags editedDesire
= desiredState
;
1012 // if they don't really need it, they don't get it
1013 if ( !(desiredState
& kIOPMPreventIdleSleep
) ) {
1018 IOLockLock(pm_vars
->childLock
);
1020 // recompute sleepIsSupported and see if all children are asleep
1021 iter
= getChildIterator(gIOPowerPlane
);
1022 sleepIsSupported
= true;
1025 while ( (next
= iter
->getNextObject()) )
1027 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1029 if ( connection
== whichChild
)
1031 powerRequestFlag
+= editedDesire
;
1032 if ( desiredState
& kIOPMPreventSystemSleep
)
1034 sleepIsSupported
= false;
1037 powerRequestFlag
+= connection
->getDesiredDomainState();
1038 if ( connection
->getPreventSystemSleepFlag() )
1040 sleepIsSupported
= false;
1048 if ( (extraSleepDelay
== 0) && (powerRequestFlag
== 0) )
1053 // this may put the system to sleep
1056 IOLockUnlock(pm_vars
->childLock
);
1058 editedDesire
|= desiredState
& kIOPMPreventSystemSleep
;
1060 return super::requestPowerDomainState(editedDesire
,whichChild
,specification
);
1064 //*********************************************************************************
1065 // getSleepSupported
1067 //*********************************************************************************
1069 IOOptionBits
IOPMrootDomain::getSleepSupported( void )
1071 return( platformSleepSupport
);
1075 //*********************************************************************************
1078 // We override the superclass implementation so we can send a different message
1079 // type to the client or application being notified.
1080 //*********************************************************************************
1082 bool IOPMrootDomain::tellChangeDown ( unsigned long stateNum
)
1084 switch ( stateNum
) {
1087 return super::tellClientsWithResponse(kIOMessageSystemWillSleep
);
1089 return super::tellClientsWithResponse(kIOMessageSystemWillRestart
);
1091 return super::tellClientsWithResponse(kIOMessageSystemWillPowerOff
);
1093 // this shouldn't execute
1094 return super::tellChangeDown(stateNum
);
1098 //*********************************************************************************
1101 // We override the superclass implementation so we can send a different message
1102 // type to the client or application being notified.
1104 // This must be idle sleep since we don't ask apps during any other power change.
1105 //*********************************************************************************
1107 bool IOPMrootDomain::askChangeDown ( unsigned long )
1109 return super::tellClientsWithResponse(kIOMessageCanSystemSleep
);
1113 //*********************************************************************************
1116 // Notify registered applications and kernel clients that we are not
1119 // We override the superclass implementation so we can send a different message
1120 // type to the client or application being notified.
1122 // This must be a vetoed idle sleep, since no other power change can be vetoed.
1123 //*********************************************************************************
1125 void IOPMrootDomain::tellNoChangeDown ( unsigned long )
1127 return tellClients(kIOMessageSystemWillNotSleep
);
1131 //*********************************************************************************
1134 // Notify registered applications and kernel clients that we are raising power.
1136 // We override the superclass implementation so we can send a different message
1137 // type to the client or application being notified.
1138 //*********************************************************************************
1140 void IOPMrootDomain::tellChangeUp ( unsigned long stateNum
)
1142 if ( stateNum
== ON_STATE
)
1144 IOHibernateSystemPostWake();
1145 return tellClients(kIOMessageSystemHasPoweredOn
);
1149 //*********************************************************************************
1152 //*********************************************************************************
1154 void IOPMrootDomain::reportUserInput ( void )
1160 iter
= getMatchingServices(serviceMatching("IODisplayWrangler"));
1163 wrangler
= (IOService
*) iter
->getNextObject();
1169 wrangler
->activityTickle(0,0);
1172 //*********************************************************************************
1173 // setQuickSpinDownTimeout
1175 //*********************************************************************************
1177 void IOPMrootDomain::setQuickSpinDownTimeout ( void )
1179 super::setAggressiveness((unsigned long)kPMMinutesToSpinDown
,(unsigned long)1);
1182 //*********************************************************************************
1183 // restoreUserSpinDownTimeout
1185 //*********************************************************************************
1187 void IOPMrootDomain::restoreUserSpinDownTimeout ( void )
1189 super::setAggressiveness((unsigned long)kPMMinutesToSpinDown
,(unsigned long)user_spindown
);
1192 //*********************************************************************************
1193 // changePowerStateTo & changePowerStateToPriv
1195 // Override of these methods for logging purposes.
1196 //*********************************************************************************
1198 IOReturn
IOPMrootDomain::changePowerStateTo ( unsigned long ordinal
)
1200 return super::changePowerStateTo(ordinal
);
1203 IOReturn
IOPMrootDomain::changePowerStateToPriv ( unsigned long ordinal
)
1205 return super::changePowerStateToPriv(ordinal
);
1209 //*********************************************************************************
1210 // sysPowerDownHandler
1212 // Receives a notification when the RootDomain changes state.
1214 // Allows us to take action on system sleep, power down, and restart after
1215 // applications have received their power change notifications and replied,
1216 // but before drivers have powered down. We perform a vfs sync on power down.
1217 //*********************************************************************************
1219 IOReturn
IOPMrootDomain::sysPowerDownHandler( void * target
, void * refCon
,
1220 UInt32 messageType
, IOService
* service
,
1221 void * messageArgument
, vm_size_t argSize
)
1224 IOPowerStateChangeNotification
*params
= (IOPowerStateChangeNotification
*) messageArgument
;
1225 IOPMrootDomain
*rootDomain
= OSDynamicCast(IOPMrootDomain
, service
);
1228 return kIOReturnUnsupported
;
1230 switch (messageType
) {
1231 case kIOMessageSystemWillSleep
:
1232 rootDomain
->powerOverrideOnPriv(); // start ignoring children's requests
1233 // (fall through to other cases)
1235 // Interested applications have been notified of an impending power
1236 // change and have acked (when applicable).
1237 // This is our chance to save whatever state we can before powering
1239 // We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c,
1242 // We will ack within 20 seconds
1243 params
->returnValue
= 20 * 1000 * 1000;
1244 if (gIOHibernateState
)
1245 params
->returnValue
+= gIOHibernateFreeTime
* 1000; //add in time we could spend freeing pages
1247 if ( ! OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending
) )
1249 // Purposely delay the ack and hope that shutdown occurs quickly.
1250 // Another option is not to schedule the thread and wait for
1252 AbsoluteTime deadline
;
1253 clock_interval_to_deadline( 30, kSecondScale
, &deadline
);
1254 thread_call_enter1_delayed( rootDomain
->diskSyncCalloutEntry
,
1255 (thread_call_param_t
)params
->powerRef
,
1259 thread_call_enter1(rootDomain
->diskSyncCalloutEntry
, (thread_call_param_t
)params
->powerRef
);
1260 ret
= kIOReturnSuccess
;
1263 case kIOMessageSystemWillPowerOff
:
1264 case kIOMessageSystemWillRestart
:
1265 ret
= kIOReturnUnsupported
;
1269 ret
= kIOReturnUnsupported
;
1275 //*********************************************************************************
1276 // displayWranglerNotification
1278 // Receives a notification when the IODisplayWrangler changes state.
1280 // Allows us to take action on display dim/undim.
1282 // When the display goes dim we:
1283 // - Start the idle sleep timer
1284 // - set the quick spin down timeout
1286 // On wake from display dim:
1287 // - Cancel the idle sleep timer
1288 // - restore the user's chosen spindown timer from the "quick" spin down value
1289 //*********************************************************************************
1291 IOReturn
IOPMrootDomain::displayWranglerNotification( void * target
, void * refCon
,
1292 UInt32 messageType
, IOService
* service
,
1293 void * messageArgument
, vm_size_t argSize
)
1295 IOPMrootDomain
* rootDomain
= OSDynamicCast(IOPMrootDomain
, (IOService
*)target
);
1296 AbsoluteTime deadline
;
1297 static bool deviceAlreadyPoweredOff
= false;
1300 return kIOReturnUnsupported
;
1302 switch (messageType
) {
1303 case kIOMessageDeviceWillPowerOff
:
1304 // The IODisplayWrangler has powered off either because of idle display sleep
1305 // or force system sleep.
1307 // The display wrangler will send the DeviceWillPowerOff message 4 times until
1308 // it gets into its lowest state. We only want to act on the first of those 4.
1309 if( deviceAlreadyPoweredOff
) return kIOReturnUnsupported
;
1311 deviceAlreadyPoweredOff
= true;
1313 if( rootDomain
->extraSleepDelay
)
1315 // start the extra sleep timer
1316 clock_interval_to_deadline(rootDomain
->extraSleepDelay
*60, kSecondScale
, &deadline
);
1317 thread_call_enter_delayed(rootDomain
->extraSleepTimer
, deadline
);
1318 rootDomain
->idleSleepPending
= true;
1320 // accelerate disk spin down if spin down timer is non-zero (zero = never spin down)
1321 // and if system sleep is non-Never
1322 if( (0 != rootDomain
->user_spindown
) && (0 != rootDomain
->sleepSlider
) )
1323 rootDomain
->setQuickSpinDownTimeout();
1328 case kIOMessageDeviceHasPoweredOn
:
1330 // The display has powered on either because of UI activity or wake from sleep/doze
1331 deviceAlreadyPoweredOff
= false;
1332 rootDomain
->adjustPowerState();
1335 // cancel any pending idle sleep
1336 if(rootDomain
->idleSleepPending
)
1338 thread_call_cancel(rootDomain
->extraSleepTimer
);
1339 rootDomain
->idleSleepPending
= false;
1342 // Change the spindown value back to the user's selection from our accelerated setting
1343 if(0 != rootDomain
->user_spindown
)
1344 rootDomain
->restoreUserSpinDownTimeout();
1346 // Put on the policy maker's on clamp.
1353 return kIOReturnUnsupported
;
1356 //*********************************************************************************
1357 // displayWranglerPublished
1359 // Receives a notification when the IODisplayWrangler is published.
1360 // When it's published we install a power state change handler.
1362 //*********************************************************************************
1364 bool IOPMrootDomain::displayWranglerPublished( void * target
, void * refCon
,
1365 IOService
* newService
)
1367 IOPMrootDomain
* rootDomain
= OSDynamicCast(IOPMrootDomain
, (IOService
*)target
);
1372 rootDomain
->wrangler
= newService
;
1374 // we found the display wrangler, now install a handler
1375 if( !rootDomain
->wrangler
->registerInterest( gIOGeneralInterest
, &displayWranglerNotification
, target
, 0) ) {
1376 IOLog("IOPMrootDomain::displayWranglerPublished registerInterest failed\n");
1383 //*********************************************************************************
1384 // batteryLocationPublished
1386 // Notification on AppleSMU publishing location of battery data
1388 //*********************************************************************************
1390 bool IOPMrootDomain::batteryLocationPublished( void * target
, void * root_domain
,
1391 IOService
* resourceService
)
1393 IORegistryEntry
*battery_location
;
1395 battery_location
= (IORegistryEntry
*) resourceService
->getProperty("battery");
1396 if (!battery_location
|| !OSDynamicCast(IORegistryEntry
, battery_location
))
1399 ((IOPMrootDomain
*)root_domain
)->setProperty("BatteryEntry", battery_location
);
1402 // All laptops have dimmable LCD displays
1403 // All laptops have batteries
1404 // So if this machine has a battery, publish the fact that the backlight
1405 // supports dimming.
1406 ((IOPMrootDomain
*)root_domain
)->publishFeature("DisplayDims");
1408 ((IOPMrootDomain
*)root_domain
)->announcePowerSourceChange();
1414 //*********************************************************************************
1417 // Some condition that affects our wake/sleep/doze decision has changed.
1419 // If the sleep slider is in the off position, we cannot sleep or doze.
1420 // If the enclosure is open, we cannot sleep or doze.
1421 // If the system is still booting, we cannot sleep or doze.
1423 // In those circumstances, we prevent sleep and doze by holding power on with
1424 // changePowerStateToPriv(ON).
1426 // If the above conditions do not exist, and also the sleep timer has expired, we
1427 // allow sleep or doze to occur with either changePowerStateToPriv(SLEEP) or
1428 // changePowerStateToPriv(DOZE) depending on whether or not we already know the
1429 // platform cannot sleep.
1431 // In this case, sleep or doze will either occur immediately or at the next time
1432 // that no children are holding the system out of idle sleep via the
1433 // kIOPMPreventIdleSleep flag in their power state arrays.
1434 //*********************************************************************************
1436 void IOPMrootDomain::adjustPowerState( void )
1438 if ( (sleepSlider
== 0) ||
1441 changePowerStateToPriv(ON_STATE
);
1446 if ( sleepIsSupported
)
1448 changePowerStateToPriv(SLEEP_STATE
);
1450 changePowerStateToPriv(DOZE_STATE
);
1457 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1460 #define super IOService
1462 OSDefineMetaClassAndStructors(IORootParent
, IOService
)
1464 // This array exactly parallels the state array for the root domain.
1465 // Power state changes initiated by a device can be vetoed by a client of the device, and
1466 // power state changes initiated by the parent of a device cannot be vetoed by a client of the device,
1467 // so when the root domain wants a power state change that cannot be vetoed (e.g. demand sleep), it asks
1468 // its parent to make the change. That is the reason for this complexity.
1470 static IOPMPowerState patriarchPowerStates
[number_of_power_states
] = {
1471 {1,0,0,0,0,0,0,0,0,0,0,0}, // off
1472 {1,0,RESTART_POWER
,0,0,0,0,0,0,0,0,0}, // reset
1473 {1,0,SLEEP_POWER
,0,0,0,0,0,0,0,0,0}, // sleep
1474 {1,0,DOZE_POWER
,0,0,0,0,0,0,0,0,0}, // doze
1475 {1,0,ON_POWER
,0,0,0,0,0,0,0,0,0} // running
1478 bool IORootParent::start ( IOService
* nub
)
1480 mostRecentChange
= ON_STATE
;
1483 registerPowerDriver(this,patriarchPowerStates
,number_of_power_states
);
1484 powerOverrideOnPriv();
1489 void IORootParent::shutDownSystem ( void )
1491 mostRecentChange
= OFF_STATE
;
1492 changePowerStateToPriv(OFF_STATE
);
1496 void IORootParent::restartSystem ( void )
1498 mostRecentChange
= RESTART_STATE
;
1499 changePowerStateToPriv(RESTART_STATE
);
1503 void IORootParent::sleepSystem ( void )
1505 mostRecentChange
= SLEEP_STATE
;
1506 changePowerStateToPriv(SLEEP_STATE
);
1510 void IORootParent::dozeSystem ( void )
1512 mostRecentChange
= DOZE_STATE
;
1513 changePowerStateToPriv(DOZE_STATE
);
1516 // Called in demand sleep when sleep discovered to be impossible after actually attaining that state.
1517 // This brings the parent to doze, which allows the root to step up from sleep to doze.
1519 // In idle sleep, do nothing because the parent is still on and the root can freely change state.
1521 void IORootParent::sleepToDoze ( void )
1523 if ( mostRecentChange
== SLEEP_STATE
) {
1524 changePowerStateToPriv(DOZE_STATE
);
1529 void IORootParent::wakeSystem ( void )
1531 mostRecentChange
= ON_STATE
;
1532 changePowerStateToPriv(ON_STATE
);