2 * Copyright (c) 1998-2005 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
30 #include <IOKit/IOWorkLoop.h>
31 #include <IOKit/IOCommandGate.h>
32 #include <IOKit/IOTimerEventSource.h>
33 #include <IOKit/IOPlatformExpert.h>
34 #include <IOKit/IOKitDebug.h>
35 #include <IOKit/IOTimeStamp.h>
36 #include <IOKit/pwr_mgt/RootDomain.h>
37 #include <IOKit/pwr_mgt/IOPMPrivate.h>
38 #include <IOKit/IODeviceTreeSupport.h>
39 #include <IOKit/IOMessage.h>
40 #include "RootDomainUserClient.h"
41 #include "IOKit/pwr_mgt/IOPowerConnection.h"
42 #include "IOPMPowerStateQueue.h"
43 #include <IOKit/IOCatalogue.h>
44 #include <IOKit/IOHibernatePrivate.h>
50 extern "C" void kprintf(const char *, ...);
52 extern const IORegistryPlane
* gIOPowerPlane
;
54 IOReturn
broadcast_aggressiveness ( OSObject
*, void *, void *, void *, void * );
55 static void sleepTimerExpired(thread_call_param_t
);
56 static void wakeupClamshellTimerExpired ( thread_call_param_t us
);
59 #define number_of_power_states 5
61 #define RESTART_STATE 1
66 #define ON_POWER kIOPMPowerOn
67 #define RESTART_POWER kIOPMRestart
68 #define SLEEP_POWER kIOPMAuxPowerOn
69 #define DOZE_POWER kIOPMDoze
71 static IOPMPowerState ourPowerStates
[number_of_power_states
] = {
72 {1,0, 0, 0,0,0,0,0,0,0,0,0}, // state 0, off
73 {1,kIOPMRestartCapability
, kIOPMRestart
, RESTART_POWER
,0,0,0,0,0,0,0,0}, // state 1, restart
74 {1,kIOPMSleepCapability
, kIOPMSleep
, SLEEP_POWER
,0,0,0,0,0,0,0,0}, // state 2, sleep
75 {1,kIOPMDoze
, kIOPMDoze
, DOZE_POWER
,0,0,0,0,0,0,0,0}, // state 3, doze
76 {1,kIOPMPowerOn
, kIOPMPowerOn
, ON_POWER
,0,0,0,0,0,0,0,0}, // state 4, on
79 // RESERVED IOPMrootDomain class variables
80 #define diskSyncCalloutEntry _reserved->diskSyncCalloutEntry
81 #define _settingController _reserved->_settingController
82 #define _batteryLocationNotifier _reserved->_batteryLocationNotifier
83 #define _displayWranglerNotifier _reserved->_displayWranglerNotifier
86 static IOPMrootDomain
* gRootDomain
;
87 static UInt32 gSleepOrShutdownPending
= 0;
90 #define super IOService
91 OSDefineMetaClassAndStructors(IOPMrootDomain
,IOService
)
95 IONotifier
* registerSleepWakeInterest(IOServiceInterestHandler handler
, void * self
, void * ref
)
97 return gRootDomain
->registerInterest( gIOGeneralInterest
, handler
, self
, ref
);
100 IONotifier
* registerPrioritySleepWakeInterest(IOServiceInterestHandler handler
, void * self
, void * ref
)
102 return gRootDomain
->registerInterest( gIOPriorityPowerStateInterest
, handler
, self
, ref
);
105 IOReturn
acknowledgeSleepWakeNotification(void * PMrefcon
)
107 return gRootDomain
->allowPowerChange ( (unsigned long)PMrefcon
);
110 IOReturn
vetoSleepWakeNotification(void * PMrefcon
)
112 return gRootDomain
->cancelPowerChange ( (unsigned long)PMrefcon
);
115 IOReturn
rootDomainRestart ( void )
117 return gRootDomain
->restartSystem();
120 IOReturn
rootDomainShutdown ( void )
122 return gRootDomain
->shutdownSystem();
125 void IOSystemShutdownNotification ( void )
127 IOCatalogue::disableExternalLinker();
128 for ( int i
= 0; i
< 100; i
++ )
130 if ( OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending
) ) break;
135 int sync_internal(void);
139 A device is always in the highest power state which satisfies its driver, its policy-maker, and any power domain
140 children it has, but within the constraint of the power state provided by its parent. The driver expresses its desire by
141 calling changePowerStateTo(), the policy-maker expresses its desire by calling changePowerStateToPriv(), and the children
142 express their desires by calling requestPowerDomainState().
144 The Root Power Domain owns the policy for idle and demand sleep and doze for the system. It is a power-managed IOService just
145 like the others in the system. It implements several power states which correspond to what we see as Sleep, Doze, etc.
147 The sleep/doze policy is as follows:
148 Sleep and Doze are prevented if the case is open so that nobody will think the machine is off and plug/unplug cards.
149 Sleep and Doze are prevented if the sleep timeout slider in the preferences panel is at zero.
150 The system cannot Sleep, but can Doze if some object in the tree is in a power state marked kIOPMPreventSystemSleep.
152 These three conditions are enforced using the "driver clamp" by calling changePowerStateTo(). For example, if the case is
153 opened, changePowerStateTo(ON_STATE) is called to hold the system on regardless of the desires of the children of the root or
154 the state of the other clamp.
156 Demand Sleep/Doze is initiated by pressing the front panel power button, closing the clamshell, or selecting the menu item.
157 In this case the root's parent actually initiates the power state change so that the root has no choice and does not give
158 applications the opportunity to veto the change.
160 Idle Sleep/Doze occurs if no objects in the tree are in a state marked kIOPMPreventIdleSleep. When this is true, the root's
161 children are not holding the root on, so it sets the "policy-maker clamp" by calling changePowerStateToPriv(ON_STATE)
162 to hold itself on until the sleep timer expires. This timer is set for the difference between the sleep timeout slider and
163 the larger of the display dim timeout slider and the disk spindown timeout slider in the Preferences panel. For example, if
164 the system is set to sleep after thirty idle minutes, and the display and disk are set to sleep after five idle minutes,
165 when there is no longer an object in the tree holding the system out of Idle Sleep (via kIOPMPreventIdleSleep), the root
166 sets its timer for 25 minutes (30 - 5). When the timer expires, it releases its clamp and now nothing is holding it awake,
169 Demand sleep is prevented when the system is booting. When preferences are transmitted by the loginwindow at the end of
170 boot, a flag is cleared, and this allows subsequent Demand Sleep.
172 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
173 a clamp, but sets a flag which is noticed before actually sleeping the kernel. If the flag is set, the root steps up
174 one power state from Sleep to Doze, and any objects in the tree for which this is relevent will act appropriately (USB and
175 ADB will turn on again so that they can wake the system out of Doze (keyboard/mouse activity will cause the Display Wrangler
179 // **********************************************************************************
181 IOPMrootDomain
* IOPMrootDomain::construct( void )
183 IOPMrootDomain
*root
;
185 root
= new IOPMrootDomain
;
192 // **********************************************************************************
194 static void disk_sync_callout(thread_call_param_t p0
, thread_call_param_t p1
)
196 IOService
*rootDomain
= (IOService
*) p0
;
197 unsigned long pmRef
= (unsigned long) p1
;
199 IOHibernateSystemSleep();
201 rootDomain
->allowPowerChange(pmRef
);
204 // **********************************************************************************
207 // We don't do much here. The real initialization occurs when the platform
208 // expert informs us we are the root.
209 // **********************************************************************************
212 bool IOPMrootDomain::start ( IOService
* nub
)
214 OSDictionary
*tmpDict
;
216 pmPowerStateQueue
= 0;
218 _reserved
= (ExpansionData
*)IOMalloc(sizeof(ExpansionData
));
219 if(!_reserved
) return false;
226 setProperty("IOSleepSupported","");
229 sleepIsSupported
= true;
230 systemBooting
= true;
231 ignoringClamshell
= true;
233 idleSleepPending
= false;
237 _settingController
= NULL
;
238 ignoringClamshellDuringWakeup
= false;
240 tmpDict
= OSDictionary::withCapacity(1);
241 setProperty(kRootDomainSupportedFeatures
, tmpDict
);
244 pm_vars
->PMworkloop
= IOWorkLoop::workLoop();
245 pmPowerStateQueue
= IOPMPowerStateQueue::PMPowerStateQueue(this);
246 pm_vars
->PMworkloop
->addEventSource(pmPowerStateQueue
);
248 featuresDictLock
= IOLockAlloc();
250 extraSleepTimer
= thread_call_allocate((thread_call_func_t
)sleepTimerExpired
, (thread_call_param_t
) this);
251 clamshellWakeupIgnore
= thread_call_allocate((thread_call_func_t
)wakeupClamshellTimerExpired
, (thread_call_param_t
) this);
252 diskSyncCalloutEntry
= thread_call_allocate(&disk_sync_callout
, (thread_call_param_t
) this);
255 patriarch
= new IORootParent
;
257 patriarch
->attach(this);
258 patriarch
->start(this);
259 patriarch
->youAreRoot();
260 patriarch
->wakeSystem();
261 patriarch
->addPowerChild(this);
263 registerPowerDriver(this,ourPowerStates
,number_of_power_states
);
265 setPMRootDomain(this);
266 // set a clamp until we sleep
267 changePowerStateToPriv(ON_STATE
);
269 // install power change handler
270 registerPrioritySleepWakeInterest( &sysPowerDownHandler
, this, 0);
272 // Register for a notification when IODisplayWrangler is published
273 _displayWranglerNotifier
= addNotification( gIOPublishNotification
,
274 serviceMatching("IODisplayWrangler"),
275 &displayWranglerPublished
, this, 0);
277 _batteryLocationNotifier
= addNotification( gIOPublishNotification
,
278 resourceMatching("battery"),
279 &batteryLocationPublished
, this, this);
281 const OSSymbol
*ucClassName
= OSSymbol::withCStringNoCopy("RootDomainUserClient");
282 setProperty(gIOUserClientClassKey
, (OSObject
*) ucClassName
);
283 ucClassName
->release();
285 IORegistryEntry
*temp_entry
= NULL
;
286 if( (temp_entry
= IORegistryEntry::fromPath("mac-io/battery", gIODTPlane
)) ||
287 (temp_entry
= IORegistryEntry::fromPath("mac-io/via-pmu/battery", gIODTPlane
)))
289 // If this machine has a battery, publish the fact that the backlight
291 // Notice similar call in IOPMrootDomain::batteryLocationPublished() to
292 // detect batteries on SMU machines.
293 publishFeature("DisplayDims");
294 temp_entry
->release();
297 IOHibernateSystemInit(this);
299 registerService(); // let clients find us
304 IOReturn
IOPMrootDomain::setPMSetting(int type
, OSNumber
*n
)
306 if(_settingController
&& _settingController
->func
) {
308 seconds
= n
->unsigned32BitValue();
309 return (*(_settingController
->func
))(type
, seconds
, _settingController
->refcon
);
311 return kIOReturnNoDevice
;
315 // **********************************************************************************
318 // Receive a setProperty call
319 // The "System Boot" property means the system is completely booted.
320 // **********************************************************************************
321 IOReturn
IOPMrootDomain::setProperties ( OSObject
*props_obj
)
323 IOReturn return_value
= kIOReturnSuccess
;
324 OSDictionary
*dict
= OSDynamicCast(OSDictionary
, props_obj
);
328 const OSSymbol
*boot_complete_string
= OSSymbol::withCString("System Boot Complete");
329 const OSSymbol
*power_button_string
= OSSymbol::withCString("DisablePowerButtonSleep");
330 const OSSymbol
*stall_halt_string
= OSSymbol::withCString("StallSystemAtHalt");
331 const OSSymbol
*auto_wake_string
= OSSymbol::withCString("wake");
332 const OSSymbol
*auto_power_string
= OSSymbol::withCString("poweron");
333 const OSSymbol
*wakeonring_string
= OSSymbol::withCString("WakeOnRing");
334 const OSSymbol
*fileserver_string
= OSSymbol::withCString("AutoRestartOnPowerLoss");
335 const OSSymbol
*wakeonlid_string
= OSSymbol::withCString("WakeOnLid");
336 const OSSymbol
*wakeonac_string
= OSSymbol::withCString("WakeOnACChange");
337 const OSSymbol
*hibernatemode_string
= OSSymbol::withCString(kIOHibernateModeKey
);
338 const OSSymbol
*hibernatefile_string
= OSSymbol::withCString(kIOHibernateFileKey
);
339 const OSSymbol
*hibernatefreeratio_string
= OSSymbol::withCString(kIOHibernateFreeRatioKey
);
340 const OSSymbol
*hibernatefreetime_string
= OSSymbol::withCString(kIOHibernateFreeTimeKey
);
341 const OSSymbol
*timezone_string
= OSSymbol::withCString("TimeZoneOffsetSeconds");
345 return_value
= kIOReturnBadArgument
;
350 && boot_complete_string
351 && dict
->getObject(boot_complete_string
))
353 systemBooting
= false;
357 if( power_button_string
358 && (b
= OSDynamicCast(OSBoolean
, dict
->getObject(power_button_string
))) )
360 setProperty(power_button_string
, b
);
363 if( stall_halt_string
364 && (b
= OSDynamicCast(OSBoolean
, dict
->getObject(stall_halt_string
))) )
366 setProperty(stall_halt_string
, b
);
369 if ( hibernatemode_string
370 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(hibernatemode_string
))))
372 setProperty(hibernatemode_string
, n
);
374 if ( hibernatefreeratio_string
375 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(hibernatefreeratio_string
))))
377 setProperty(hibernatefreeratio_string
, n
);
379 if ( hibernatefreetime_string
380 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(hibernatefreetime_string
))))
382 setProperty(hibernatefreetime_string
, n
);
384 if ( hibernatefile_string
385 && (str
= OSDynamicCast(OSString
, dict
->getObject(hibernatefile_string
))))
387 setProperty(hibernatefile_string
, str
);
390 // Relay AutoWake setting to its controller
392 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(auto_wake_string
))) )
394 return_value
= setPMSetting(kIOPMAutoWakeSetting
, n
);
395 if(kIOReturnSuccess
!= return_value
) goto exit
;
398 // Relay AutoPower setting to its controller
399 if( auto_power_string
400 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(auto_power_string
))) )
402 return_value
= setPMSetting(kIOPMAutoPowerOnSetting
, n
);
403 if(kIOReturnSuccess
!= return_value
) goto exit
;
406 // Relay WakeOnRing setting to its controller
407 if( wakeonring_string
408 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(wakeonring_string
))) )
410 return_value
= setPMSetting(kIOPMWakeOnRingSetting
, n
);
411 if(kIOReturnSuccess
!= return_value
) goto exit
;
414 // Relay FileServer setting to its controller
415 if( fileserver_string
416 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(fileserver_string
))) )
418 return_value
= setPMSetting(kIOPMAutoRestartOnPowerLossSetting
, n
);
419 if(kIOReturnSuccess
!= return_value
) goto exit
;
422 // Relay WakeOnLid setting to its controller
424 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(wakeonlid_string
))) )
426 return_value
= setPMSetting(kIOPMWakeOnLidSetting
, n
);
427 if(kIOReturnSuccess
!= return_value
) goto exit
;
430 // Relay WakeOnACChange setting to its controller
432 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(wakeonac_string
))) )
434 return_value
= setPMSetting(kIOPMWakeOnACChangeSetting
, n
);
435 if(kIOReturnSuccess
!= return_value
) goto exit
;
438 // Relay timezone offset in seconds to SMU
440 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(timezone_string
))) )
442 return_value
= setPMSetting(kIOPMTimeZoneSetting
, n
);
443 if(kIOReturnSuccess
!= return_value
) goto exit
;
448 if(boot_complete_string
) boot_complete_string
->release();
449 if(power_button_string
) power_button_string
->release();
450 if(stall_halt_string
) stall_halt_string
->release();
451 if(auto_wake_string
) auto_wake_string
->release();
452 if(auto_power_string
) auto_power_string
->release();
453 if(wakeonring_string
) wakeonring_string
->release();
454 if(fileserver_string
) fileserver_string
->release();
455 if(wakeonlid_string
) wakeonlid_string
->release();
456 if(wakeonac_string
) wakeonac_string
->release();
457 if(timezone_string
) timezone_string
->release();
462 //*********************************************************************************
465 // Power Managment is informing us that we are the root power domain.
466 // We know we are not the root however, since we have just instantiated a parent
467 // for ourselves and made it the root. We override this method so it will have
469 //*********************************************************************************
470 IOReturn
IOPMrootDomain::youAreRoot ( void )
475 // **********************************************************************************
479 // **********************************************************************************
480 void IOPMrootDomain::command_received ( void * w
, void * x
, void * y
, void * z
)
482 super::command_received(w
,x
,y
,z
);
486 // **********************************************************************************
487 // broadcast_aggressiveness
489 // **********************************************************************************
490 IOReturn
broadcast_aggressiveness ( OSObject
* root
, void * x
, void * y
, void *, void * )
492 ((IOPMrootDomain
*)root
)->broadcast_it((unsigned long)x
,(unsigned long)y
);
497 // **********************************************************************************
500 // We are behind the command gate to broadcast an aggressiveness factor. We let the
501 // superclass do it, but we need to snoop on factors that affect idle sleep.
502 // **********************************************************************************
503 void IOPMrootDomain::broadcast_it (unsigned long type
, unsigned long value
)
505 super::setAggressiveness(type
,value
);
507 // Save user's spin down timer to restore after we replace it for idle sleep
508 if( type
== kPMMinutesToSpinDown
) user_spindown
= value
;
510 // Use longestNonSleepSlider to calculate dimming adjust idle sleep timer
511 longestNonSleepSlider
= pm_vars
->current_aggressiveness_values
[kPMMinutesToDim
];
514 if ( type
== kPMMinutesToSleep
) {
515 if ( (sleepSlider
== 0) && (value
!= 0) ) {
517 // idle sleep is now enabled, maybe sleep now
521 if ( sleepSlider
== 0 ) {
522 // idle sleep is now disabled
524 // make sure we're powered
525 patriarch
->wakeSystem();
528 if ( sleepSlider
> longestNonSleepSlider
) {
529 extraSleepDelay
= sleepSlider
- longestNonSleepSlider
;
537 // **********************************************************************************
540 // **********************************************************************************
541 static void sleepTimerExpired ( thread_call_param_t us
)
543 ((IOPMrootDomain
*)us
)->handleSleepTimerExpiration();
547 static void wakeupClamshellTimerExpired ( thread_call_param_t us
)
549 ((IOPMrootDomain
*)us
)->stopIgnoringClamshellEventsDuringWakeup();
553 // **********************************************************************************
554 // handleSleepTimerExpiration
556 // The time between the sleep idle timeout and the next longest one has elapsed.
557 // It's time to sleep. Start that by removing the clamp that's holding us awake.
558 // **********************************************************************************
559 void IOPMrootDomain::handleSleepTimerExpiration ( void )
561 // accelerate disk spin down if spin down timer is non-zero (zero = never spin down)
562 if(0 != user_spindown
)
563 setQuickSpinDownTimeout();
570 void IOPMrootDomain::stopIgnoringClamshellEventsDuringWakeup(void)
574 // Allow clamshell-induced sleep now
575 ignoringClamshellDuringWakeup
= false;
577 if ((state
= getProperty(kAppleClamshellStateKey
)))
578 publishResource(kAppleClamshellStateKey
, state
);
581 //*********************************************************************************
584 // Some aggressiveness factor has changed. We broadcast it to the hierarchy while on
585 // the Power Mangement workloop thread. This enables objects in the
586 // hierarchy to successfully alter their idle timers, which are all on the
588 //*********************************************************************************
590 static int pmsallsetup
= 0;
592 IOReturn
IOPMrootDomain::setAggressiveness ( unsigned long type
, unsigned long newLevel
)
595 if(pmsExperimental
& 3) kprintf("setAggressiveness: type = %08X, newlevel = %08X\n", type
, newLevel
);
596 if(pmsExperimental
& 1) { /* Is experimental mode enabled? */
597 if(pmsInstalled
&& (type
== kPMSetProcessorSpeed
)) { /* We want to look at all processor speed changes if stepper is installed */
598 if(pmsallsetup
) return kIOReturnSuccess
; /* If already running, just eat this */
599 kprintf("setAggressiveness: starting stepper...\n");
600 pmsallsetup
= 1; /* Remember we did this */
602 pmsStart(); /* Get it all started up... */
603 return kIOReturnSuccess
; /* Leave now... */
608 if ( pm_vars
->PMcommandGate
) {
609 pm_vars
->PMcommandGate
->runAction(broadcast_aggressiveness
,(void *)type
,(void *)newLevel
);
612 return kIOReturnSuccess
;
616 // **********************************************************************************
619 // **********************************************************************************
620 IOReturn
IOPMrootDomain::sleepSystem ( void )
622 //kprintf("sleep demand received\n");
623 if ( !systemBooting
&& allowSleep
&& sleepIsSupported
) {
624 patriarch
->sleepSystem();
626 return kIOReturnSuccess
;
628 if ( !systemBooting
&& allowSleep
&& !sleepIsSupported
) {
629 patriarch
->dozeSystem();
630 return kIOReturnSuccess
;
632 return kIOReturnSuccess
;
636 // **********************************************************************************
639 // **********************************************************************************
640 IOReturn
IOPMrootDomain::shutdownSystem ( void )
642 //patriarch->shutDownSystem();
643 return kIOReturnUnsupported
;
647 // **********************************************************************************
650 // **********************************************************************************
651 IOReturn
IOPMrootDomain::restartSystem ( void )
653 //patriarch->restartSystem();
654 return kIOReturnUnsupported
;
658 // **********************************************************************************
661 // This overrides powerChangeDone in IOService.
663 // Finder sleep and idle sleep move us from the ON state to the SLEEP_STATE.
665 // If we just finished going to the SLEEP_STATE, and the platform is capable of true sleep,
666 // sleep the kernel. Otherwise switch up to the DOZE_STATE which will keep almost
667 // everything as off as it can get.
669 // **********************************************************************************
670 void IOPMrootDomain::powerChangeDone ( unsigned long previousState
)
672 OSNumber
* propertyPtr
;
673 unsigned short theProperty
;
674 AbsoluteTime deadline
;
676 switch ( pm_vars
->myCurrentState
) {
678 if ( canSleep
&& sleepIsSupported
)
680 // re-enable this timer for next sleep
681 idleSleepPending
= false;
683 IOLog("System %sSleep\n", gIOHibernateState
? "Safe" : "");
685 IOHibernateSystemHasSlept();
687 pm_vars
->thePlatform
->sleepKernel();
689 // The CPU(s) are off at this point. When they're awakened by CPU interrupt,
690 // code will resume execution here.
692 // Now we're waking...
693 IOHibernateSystemWake();
695 // stay awake for at least 30 seconds
696 clock_interval_to_deadline(30, kSecondScale
, &deadline
);
697 thread_call_enter_delayed(extraSleepTimer
, deadline
);
698 // this gets turned off when we sleep again
699 idleSleepPending
= true;
701 // Ignore closed clamshell during wakeup and for a few seconds
702 // after wakeup is complete
703 ignoringClamshellDuringWakeup
= true;
705 // sleep transition complete
706 gSleepOrShutdownPending
= 0;
708 // trip the reset of the calendar clock
709 clock_wakeup_calendar();
712 patriarch
->wakeSystem();
714 // early stage wake notification
715 tellClients(kIOMessageSystemWillPowerOn
);
717 // tell the tree we're waking
718 IOLog("System %sWake\n", gIOHibernateState
? "SafeSleep " : "");
721 // Allow drivers to request extra processing time before clamshell
722 // sleep if kIOREMSleepEnabledKey is present.
723 // Ignore clamshell events for at least 5 seconds
724 if(getProperty(kIOREMSleepEnabledKey
)) {
725 // clamshellWakeupIgnore callout clears ignoreClamshellDuringWakeup bit
726 clock_interval_to_deadline(5, kSecondScale
, &deadline
);
727 if(clamshellWakeupIgnore
) thread_call_enter_delayed(clamshellWakeupIgnore
, deadline
);
728 } else ignoringClamshellDuringWakeup
= false;
730 // Find out what woke us
731 propertyPtr
= OSDynamicCast(OSNumber
,getProperty("WakeEvent"));
733 theProperty
= propertyPtr
->unsigned16BitValue();
734 IOLog("Wake event %04x\n",theProperty
);
735 if ( (theProperty
& 0x0008) || //lid
736 (theProperty
& 0x0800) || // front panel button
737 (theProperty
& 0x0020) || // external keyboard
738 (theProperty
& 0x0001) ) { // internal keyboard
739 // We've identified the wakeup event as UI driven
743 // Since we can't identify the wakeup event, treat it as UI activity
747 // Wake for thirty seconds
748 changePowerStateToPriv(ON_STATE
);
749 powerOverrideOffPriv();
751 // allow us to step up a power state
752 patriarch
->sleepToDoze();
754 changePowerStateToPriv(DOZE_STATE
);
759 if ( previousState
!= DOZE_STATE
)
761 IOLog("System Doze\n");
763 // re-enable this timer for next sleep
764 idleSleepPending
= false;
765 gSleepOrShutdownPending
= 0;
769 IOLog("System Restart\n");
770 PEHaltRestart(kPERestartCPU
);
774 IOLog("System Halt\n");
775 PEHaltRestart(kPEHaltCPU
);
781 // **********************************************************************************
784 // The Display Wrangler calls here when it switches to its highest state. If the
785 // system is currently dozing, allow it to wake by making sure the parent is
787 // **********************************************************************************
788 void IOPMrootDomain::wakeFromDoze( void )
790 if ( pm_vars
->myCurrentState
== DOZE_STATE
)
792 // reset this till next attempt
794 powerOverrideOffPriv();
796 // early wake notification
797 tellClients(kIOMessageSystemWillPowerOn
);
799 // allow us to wake if children so desire
800 patriarch
->wakeSystem();
805 // **********************************************************************************
808 // Adds a new feature to the supported features dictionary
811 // **********************************************************************************
812 void IOPMrootDomain::publishFeature( const char * feature
)
814 if(featuresDictLock
) IOLockLock(featuresDictLock
);
815 OSDictionary
*features
=
816 (OSDictionary
*) getProperty(kRootDomainSupportedFeatures
);
818 if ( features
&& OSDynamicCast(OSDictionary
, features
))
819 features
= OSDictionary::withDictionary(features
);
821 features
= OSDictionary::withCapacity(1);
823 features
->setObject(feature
, kOSBooleanTrue
);
824 setProperty(kRootDomainSupportedFeatures
, features
);
826 if(featuresDictLock
) IOLockUnlock(featuresDictLock
);
830 void IOPMrootDomain::unIdleDevice( IOService
*theDevice
, unsigned long theState
)
832 if(pmPowerStateQueue
)
833 pmPowerStateQueue
->unIdleOccurred(theDevice
, theState
);
836 void IOPMrootDomain::announcePowerSourceChange( void )
838 IORegistryEntry
*_batteryRegEntry
= (IORegistryEntry
*) getProperty("BatteryEntry");
840 // (if possible) re-publish power source state under IOPMrootDomain
841 // (only done if the battery controller publishes an IOResource defining battery location)
845 batt_info
= (OSArray
*) _batteryRegEntry
->getProperty(kIOBatteryInfoKey
);
847 setProperty(kIOBatteryInfoKey
, batt_info
);
850 messageClients(kIOPMMessageBatteryStatusHasChanged
);
853 IOReturn
IOPMrootDomain::registerPMSettingController
854 (IOPMSettingControllerCallback func
, void *info
)
856 if(_settingController
) return kIOReturnExclusiveAccess
;
858 _settingController
= (PMSettingCtrl
*)IOMalloc(sizeof(PMSettingCtrl
));
859 if(!_settingController
) return kIOReturnNoMemory
;
861 _settingController
->func
= func
;
862 _settingController
->refcon
= info
;
863 return kIOReturnSuccess
;
867 //*********************************************************************************
868 // receivePowerNotification
870 // The power controller is notifying us of a hardware-related power management
871 // event that we must handle. This is a result of an 'environment' interrupt from
872 // the power mgt micro.
873 //*********************************************************************************
875 IOReturn
IOPMrootDomain::receivePowerNotification (UInt32 msg
)
877 if (msg
& kIOPMOverTemp
)
879 IOLog("Power Management received emergency overtemp signal. Going to sleep.");
880 (void) sleepSystem ();
882 if (msg
& kIOPMSetDesktopMode
)
884 desktopMode
= (0 != (msg
& kIOPMSetValue
));
885 msg
&= ~(kIOPMSetDesktopMode
| kIOPMSetValue
);
887 if (msg
& kIOPMSetACAdaptorConnected
)
889 acAdaptorConnect
= (0 != (msg
& kIOPMSetValue
));
890 msg
&= ~(kIOPMSetACAdaptorConnected
| kIOPMSetValue
);
892 if (msg
& kIOPMEnableClamshell
)
894 ignoringClamshell
= false;
896 if (msg
& kIOPMDisableClamshell
)
898 ignoringClamshell
= true;
901 if (msg
& kIOPMProcessorSpeedChange
)
903 IOService
*pmu
= waitForService(serviceMatching("ApplePMU"));
904 pmu
->callPlatformFunction("prepareForSleep", false, 0, 0, 0, 0);
905 pm_vars
->thePlatform
->sleepKernel();
906 pmu
->callPlatformFunction("recoverFromSleep", false, 0, 0, 0, 0);
909 if (msg
& kIOPMSleepNow
)
911 (void) sleepSystem ();
914 if (msg
& kIOPMPowerEmergency
)
916 (void) sleepSystem ();
919 if (msg
& kIOPMClamshellClosed
)
921 if ( !ignoringClamshell
&& !ignoringClamshellDuringWakeup
922 && (!desktopMode
|| !acAdaptorConnect
) )
925 (void) sleepSystem ();
929 if (msg
& kIOPMPowerButton
)
931 // toggle state of sleep/wake
933 if ( pm_vars
->myCurrentState
== DOZE_STATE
)
935 // yes, tell the tree we're waking
937 // wake the Display Wrangler
941 // Check that power button sleep is enabled
942 if(kOSBooleanTrue
!= getProperty(OSString::withCString("DisablePowerButtonSleep")))
947 // if the case has been closed, we allow
948 // the machine to be put to sleep or to idle sleep
950 if ( (msg
& kIOPMAllowSleep
) && !allowSleep
)
956 // if the case has been opened, we disallow sleep/doze
958 if (msg
& kIOPMPreventSleep
) {
961 if ( pm_vars
->myCurrentState
== DOZE_STATE
) {
962 // yes, tell the tree we're waking
965 // wake the Display Wrangler
969 // make sure we have power to clamp
970 patriarch
->wakeSystem();
978 //*********************************************************************************
981 //*********************************************************************************
983 void IOPMrootDomain::setSleepSupported( IOOptionBits flags
)
985 if ( flags
& kPCICantSleep
)
989 platformSleepSupport
= flags
;
994 //*********************************************************************************
995 // requestPowerDomainState
997 // The root domain intercepts this call to the superclass.
999 // If the clamp bit is not set in the desire, then the child doesn't need the power
1000 // state it's requesting; it just wants it. The root ignores desires but not needs.
1001 // If the clamp bit is not set, the root takes it that the child can tolerate no
1002 // power and interprets the request accordingly. If all children can thus tolerate
1003 // no power, we are on our way to idle sleep.
1004 //*********************************************************************************
1006 IOReturn
IOPMrootDomain::requestPowerDomainState ( IOPMPowerFlags desiredState
, IOPowerConnection
* whichChild
, unsigned long specification
)
1010 IOPowerConnection
*connection
;
1011 unsigned long powerRequestFlag
= 0;
1012 IOPMPowerFlags editedDesire
= desiredState
;
1014 // if they don't really need it, they don't get it
1015 if ( !(desiredState
& kIOPMPreventIdleSleep
) ) {
1020 IOLockLock(pm_vars
->childLock
);
1022 // recompute sleepIsSupported and see if all children are asleep
1023 iter
= getChildIterator(gIOPowerPlane
);
1024 sleepIsSupported
= true;
1027 while ( (next
= iter
->getNextObject()) )
1029 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1031 if ( connection
== whichChild
)
1033 powerRequestFlag
+= editedDesire
;
1034 if ( desiredState
& kIOPMPreventSystemSleep
)
1036 sleepIsSupported
= false;
1039 powerRequestFlag
+= connection
->getDesiredDomainState();
1040 if ( connection
->getPreventSystemSleepFlag() )
1042 sleepIsSupported
= false;
1050 if ( (extraSleepDelay
== 0) && (powerRequestFlag
== 0) )
1055 // this may put the system to sleep
1058 IOLockUnlock(pm_vars
->childLock
);
1060 editedDesire
|= desiredState
& kIOPMPreventSystemSleep
;
1062 return super::requestPowerDomainState(editedDesire
,whichChild
,specification
);
1066 //*********************************************************************************
1067 // getSleepSupported
1069 //*********************************************************************************
1071 IOOptionBits
IOPMrootDomain::getSleepSupported( void )
1073 return( platformSleepSupport
);
1077 //*********************************************************************************
1080 // We override the superclass implementation so we can send a different message
1081 // type to the client or application being notified.
1082 //*********************************************************************************
1084 bool IOPMrootDomain::tellChangeDown ( unsigned long stateNum
)
1086 switch ( stateNum
) {
1089 return super::tellClientsWithResponse(kIOMessageSystemWillSleep
);
1091 return super::tellClientsWithResponse(kIOMessageSystemWillRestart
);
1093 return super::tellClientsWithResponse(kIOMessageSystemWillPowerOff
);
1095 // this shouldn't execute
1096 return super::tellChangeDown(stateNum
);
1100 //*********************************************************************************
1103 // We override the superclass implementation so we can send a different message
1104 // type to the client or application being notified.
1106 // This must be idle sleep since we don't ask apps during any other power change.
1107 //*********************************************************************************
1109 bool IOPMrootDomain::askChangeDown ( unsigned long )
1111 return super::tellClientsWithResponse(kIOMessageCanSystemSleep
);
1115 //*********************************************************************************
1118 // Notify registered applications and kernel clients that we are not
1121 // We override the superclass implementation so we can send a different message
1122 // type to the client or application being notified.
1124 // This must be a vetoed idle sleep, since no other power change can be vetoed.
1125 //*********************************************************************************
1127 void IOPMrootDomain::tellNoChangeDown ( unsigned long )
1129 return tellClients(kIOMessageSystemWillNotSleep
);
1133 //*********************************************************************************
1136 // Notify registered applications and kernel clients that we are raising power.
1138 // We override the superclass implementation so we can send a different message
1139 // type to the client or application being notified.
1140 //*********************************************************************************
1142 void IOPMrootDomain::tellChangeUp ( unsigned long stateNum
)
1144 if ( stateNum
== ON_STATE
)
1146 IOHibernateSystemPostWake();
1147 return tellClients(kIOMessageSystemHasPoweredOn
);
1151 //*********************************************************************************
1154 //*********************************************************************************
1156 void IOPMrootDomain::reportUserInput ( void )
1162 iter
= getMatchingServices(serviceMatching("IODisplayWrangler"));
1165 wrangler
= (IOService
*) iter
->getNextObject();
1171 wrangler
->activityTickle(0,0);
1174 //*********************************************************************************
1175 // setQuickSpinDownTimeout
1177 //*********************************************************************************
1179 void IOPMrootDomain::setQuickSpinDownTimeout ( void )
1181 super::setAggressiveness((unsigned long)kPMMinutesToSpinDown
,(unsigned long)1);
1184 //*********************************************************************************
1185 // restoreUserSpinDownTimeout
1187 //*********************************************************************************
1189 void IOPMrootDomain::restoreUserSpinDownTimeout ( void )
1191 super::setAggressiveness((unsigned long)kPMMinutesToSpinDown
,(unsigned long)user_spindown
);
1194 //*********************************************************************************
1195 // changePowerStateTo & changePowerStateToPriv
1197 // Override of these methods for logging purposes.
1198 //*********************************************************************************
1200 IOReturn
IOPMrootDomain::changePowerStateTo ( unsigned long ordinal
)
1202 return super::changePowerStateTo(ordinal
);
1205 IOReturn
IOPMrootDomain::changePowerStateToPriv ( unsigned long ordinal
)
1207 return super::changePowerStateToPriv(ordinal
);
1211 //*********************************************************************************
1212 // sysPowerDownHandler
1214 // Receives a notification when the RootDomain changes state.
1216 // Allows us to take action on system sleep, power down, and restart after
1217 // applications have received their power change notifications and replied,
1218 // but before drivers have powered down. We perform a vfs sync on power down.
1219 //*********************************************************************************
1221 IOReturn
IOPMrootDomain::sysPowerDownHandler( void * target
, void * refCon
,
1222 UInt32 messageType
, IOService
* service
,
1223 void * messageArgument
, vm_size_t argSize
)
1226 IOPowerStateChangeNotification
*params
= (IOPowerStateChangeNotification
*) messageArgument
;
1227 IOPMrootDomain
*rootDomain
= OSDynamicCast(IOPMrootDomain
, service
);
1230 return kIOReturnUnsupported
;
1232 switch (messageType
) {
1233 case kIOMessageSystemWillSleep
:
1234 rootDomain
->powerOverrideOnPriv(); // start ignoring children's requests
1235 // (fall through to other cases)
1237 // Interested applications have been notified of an impending power
1238 // change and have acked (when applicable).
1239 // This is our chance to save whatever state we can before powering
1241 // We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c,
1244 // We will ack within 20 seconds
1245 params
->returnValue
= 20 * 1000 * 1000;
1246 if (gIOHibernateState
)
1247 params
->returnValue
+= gIOHibernateFreeTime
* 1000; //add in time we could spend freeing pages
1249 if ( ! OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending
) )
1251 // Purposely delay the ack and hope that shutdown occurs quickly.
1252 // Another option is not to schedule the thread and wait for
1254 AbsoluteTime deadline
;
1255 clock_interval_to_deadline( 30, kSecondScale
, &deadline
);
1256 thread_call_enter1_delayed( rootDomain
->diskSyncCalloutEntry
,
1257 (thread_call_param_t
)params
->powerRef
,
1261 thread_call_enter1(rootDomain
->diskSyncCalloutEntry
, (thread_call_param_t
)params
->powerRef
);
1262 ret
= kIOReturnSuccess
;
1265 case kIOMessageSystemWillPowerOff
:
1266 case kIOMessageSystemWillRestart
:
1267 ret
= kIOReturnUnsupported
;
1271 ret
= kIOReturnUnsupported
;
1277 //*********************************************************************************
1278 // displayWranglerNotification
1280 // Receives a notification when the IODisplayWrangler changes state.
1282 // Allows us to take action on display dim/undim.
1284 // When the display goes dim we:
1285 // - Start the idle sleep timer
1286 // - set the quick spin down timeout
1288 // On wake from display dim:
1289 // - Cancel the idle sleep timer
1290 // - restore the user's chosen spindown timer from the "quick" spin down value
1291 //*********************************************************************************
1293 IOReturn
IOPMrootDomain::displayWranglerNotification( void * target
, void * refCon
,
1294 UInt32 messageType
, IOService
* service
,
1295 void * messageArgument
, vm_size_t argSize
)
1297 IOPMrootDomain
* rootDomain
= OSDynamicCast(IOPMrootDomain
, (IOService
*)target
);
1298 AbsoluteTime deadline
;
1299 static bool deviceAlreadyPoweredOff
= false;
1302 return kIOReturnUnsupported
;
1304 switch (messageType
) {
1305 case kIOMessageDeviceWillPowerOff
:
1306 // The IODisplayWrangler has powered off either because of idle display sleep
1307 // or force system sleep.
1309 // The display wrangler will send the DeviceWillPowerOff message 4 times until
1310 // it gets into its lowest state. We only want to act on the first of those 4.
1311 if( deviceAlreadyPoweredOff
) return kIOReturnUnsupported
;
1313 deviceAlreadyPoweredOff
= true;
1315 if( rootDomain
->extraSleepDelay
)
1317 // start the extra sleep timer
1318 clock_interval_to_deadline(rootDomain
->extraSleepDelay
*60, kSecondScale
, &deadline
);
1319 thread_call_enter_delayed(rootDomain
->extraSleepTimer
, deadline
);
1320 rootDomain
->idleSleepPending
= true;
1322 // accelerate disk spin down if spin down timer is non-zero (zero = never spin down)
1323 // and if system sleep is non-Never
1324 if( (0 != rootDomain
->user_spindown
) && (0 != rootDomain
->sleepSlider
) )
1325 rootDomain
->setQuickSpinDownTimeout();
1330 case kIOMessageDeviceHasPoweredOn
:
1332 // The display has powered on either because of UI activity or wake from sleep/doze
1333 deviceAlreadyPoweredOff
= false;
1334 rootDomain
->adjustPowerState();
1337 // cancel any pending idle sleep
1338 if(rootDomain
->idleSleepPending
)
1340 thread_call_cancel(rootDomain
->extraSleepTimer
);
1341 rootDomain
->idleSleepPending
= false;
1344 // Change the spindown value back to the user's selection from our accelerated setting
1345 if(0 != rootDomain
->user_spindown
)
1346 rootDomain
->restoreUserSpinDownTimeout();
1348 // Put on the policy maker's on clamp.
1355 return kIOReturnUnsupported
;
1358 //*********************************************************************************
1359 // displayWranglerPublished
1361 // Receives a notification when the IODisplayWrangler is published.
1362 // When it's published we install a power state change handler.
1364 //*********************************************************************************
1366 bool IOPMrootDomain::displayWranglerPublished( void * target
, void * refCon
,
1367 IOService
* newService
)
1369 IOPMrootDomain
* rootDomain
= OSDynamicCast(IOPMrootDomain
, (IOService
*)target
);
1374 rootDomain
->wrangler
= newService
;
1376 // we found the display wrangler, now install a handler
1377 if( !rootDomain
->wrangler
->registerInterest( gIOGeneralInterest
, &displayWranglerNotification
, target
, 0) ) {
1378 IOLog("IOPMrootDomain::displayWranglerPublished registerInterest failed\n");
1385 //*********************************************************************************
1386 // batteryLocationPublished
1388 // Notification on AppleSMU publishing location of battery data
1390 //*********************************************************************************
1392 bool IOPMrootDomain::batteryLocationPublished( void * target
, void * root_domain
,
1393 IOService
* resourceService
)
1395 IORegistryEntry
*battery_location
;
1397 battery_location
= (IORegistryEntry
*) resourceService
->getProperty("battery");
1398 if (!battery_location
|| !OSDynamicCast(IORegistryEntry
, battery_location
))
1401 ((IOPMrootDomain
*)root_domain
)->setProperty("BatteryEntry", battery_location
);
1404 // All laptops have dimmable LCD displays
1405 // All laptops have batteries
1406 // So if this machine has a battery, publish the fact that the backlight
1407 // supports dimming.
1408 ((IOPMrootDomain
*)root_domain
)->publishFeature("DisplayDims");
1410 ((IOPMrootDomain
*)root_domain
)->announcePowerSourceChange();
1416 //*********************************************************************************
1419 // Some condition that affects our wake/sleep/doze decision has changed.
1421 // If the sleep slider is in the off position, we cannot sleep or doze.
1422 // If the enclosure is open, we cannot sleep or doze.
1423 // If the system is still booting, we cannot sleep or doze.
1425 // In those circumstances, we prevent sleep and doze by holding power on with
1426 // changePowerStateToPriv(ON).
1428 // If the above conditions do not exist, and also the sleep timer has expired, we
1429 // allow sleep or doze to occur with either changePowerStateToPriv(SLEEP) or
1430 // changePowerStateToPriv(DOZE) depending on whether or not we already know the
1431 // platform cannot sleep.
1433 // In this case, sleep or doze will either occur immediately or at the next time
1434 // that no children are holding the system out of idle sleep via the
1435 // kIOPMPreventIdleSleep flag in their power state arrays.
1436 //*********************************************************************************
1438 void IOPMrootDomain::adjustPowerState( void )
1440 if ( (sleepSlider
== 0) ||
1443 changePowerStateToPriv(ON_STATE
);
1448 if ( sleepIsSupported
)
1450 changePowerStateToPriv(SLEEP_STATE
);
1452 changePowerStateToPriv(DOZE_STATE
);
1459 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1462 #define super IOService
1464 OSDefineMetaClassAndStructors(IORootParent
, IOService
)
1466 // This array exactly parallels the state array for the root domain.
1467 // Power state changes initiated by a device can be vetoed by a client of the device, and
1468 // power state changes initiated by the parent of a device cannot be vetoed by a client of the device,
1469 // so when the root domain wants a power state change that cannot be vetoed (e.g. demand sleep), it asks
1470 // its parent to make the change. That is the reason for this complexity.
1472 static IOPMPowerState patriarchPowerStates
[number_of_power_states
] = {
1473 {1,0,0,0,0,0,0,0,0,0,0,0}, // off
1474 {1,0,RESTART_POWER
,0,0,0,0,0,0,0,0,0}, // reset
1475 {1,0,SLEEP_POWER
,0,0,0,0,0,0,0,0,0}, // sleep
1476 {1,0,DOZE_POWER
,0,0,0,0,0,0,0,0,0}, // doze
1477 {1,0,ON_POWER
,0,0,0,0,0,0,0,0,0} // running
1480 bool IORootParent::start ( IOService
* nub
)
1482 mostRecentChange
= ON_STATE
;
1485 registerPowerDriver(this,patriarchPowerStates
,number_of_power_states
);
1486 powerOverrideOnPriv();
1491 void IORootParent::shutDownSystem ( void )
1493 mostRecentChange
= OFF_STATE
;
1494 changePowerStateToPriv(OFF_STATE
);
1498 void IORootParent::restartSystem ( void )
1500 mostRecentChange
= RESTART_STATE
;
1501 changePowerStateToPriv(RESTART_STATE
);
1505 void IORootParent::sleepSystem ( void )
1507 mostRecentChange
= SLEEP_STATE
;
1508 changePowerStateToPriv(SLEEP_STATE
);
1512 void IORootParent::dozeSystem ( void )
1514 mostRecentChange
= DOZE_STATE
;
1515 changePowerStateToPriv(DOZE_STATE
);
1518 // Called in demand sleep when sleep discovered to be impossible after actually attaining that state.
1519 // This brings the parent to doze, which allows the root to step up from sleep to doze.
1521 // In idle sleep, do nothing because the parent is still on and the root can freely change state.
1523 void IORootParent::sleepToDoze ( void )
1525 if ( mostRecentChange
== SLEEP_STATE
) {
1526 changePowerStateToPriv(DOZE_STATE
);
1531 void IORootParent::wakeSystem ( void )
1533 mostRecentChange
= ON_STATE
;
1534 changePowerStateToPriv(ON_STATE
);