2 * Copyright (c) 1998-2005 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
22 #include <IOKit/IOWorkLoop.h>
23 #include <IOKit/IOCommandGate.h>
24 #include <IOKit/IOTimerEventSource.h>
25 #include <IOKit/IOPlatformExpert.h>
26 #include <IOKit/IOKitDebug.h>
27 #include <IOKit/IOTimeStamp.h>
28 #include <IOKit/pwr_mgt/RootDomain.h>
29 #include <IOKit/pwr_mgt/IOPMPrivate.h>
30 #include <IOKit/IODeviceTreeSupport.h>
31 #include <IOKit/IOMessage.h>
32 #include "RootDomainUserClient.h"
33 #include "IOKit/pwr_mgt/IOPowerConnection.h"
34 #include "IOPMPowerStateQueue.h"
35 #include <IOKit/IOCatalogue.h>
36 #include <IOKit/IOHibernatePrivate.h>
42 extern "C" void kprintf(const char *, ...);
44 extern const IORegistryPlane
* gIOPowerPlane
;
46 IOReturn
broadcast_aggressiveness ( OSObject
*, void *, void *, void *, void * );
47 static void sleepTimerExpired(thread_call_param_t
);
48 static void wakeupClamshellTimerExpired ( thread_call_param_t us
);
51 #define number_of_power_states 5
53 #define RESTART_STATE 1
58 #define ON_POWER kIOPMPowerOn
59 #define RESTART_POWER kIOPMRestart
60 #define SLEEP_POWER kIOPMAuxPowerOn
61 #define DOZE_POWER kIOPMDoze
63 static IOPMPowerState ourPowerStates
[number_of_power_states
] = {
64 {1,0, 0, 0,0,0,0,0,0,0,0,0}, // state 0, off
65 {1,kIOPMRestartCapability
, kIOPMRestart
, RESTART_POWER
,0,0,0,0,0,0,0,0}, // state 1, restart
66 {1,kIOPMSleepCapability
, kIOPMSleep
, SLEEP_POWER
,0,0,0,0,0,0,0,0}, // state 2, sleep
67 {1,kIOPMDoze
, kIOPMDoze
, DOZE_POWER
,0,0,0,0,0,0,0,0}, // state 3, doze
68 {1,kIOPMPowerOn
, kIOPMPowerOn
, ON_POWER
,0,0,0,0,0,0,0,0}, // state 4, on
71 // RESERVED IOPMrootDomain class variables
72 #define diskSyncCalloutEntry _reserved->diskSyncCalloutEntry
73 #define _settingController _reserved->_settingController
74 #define _batteryLocationNotifier _reserved->_batteryLocationNotifier
75 #define _displayWranglerNotifier _reserved->_displayWranglerNotifier
78 static IOPMrootDomain
* gRootDomain
;
79 static UInt32 gSleepOrShutdownPending
= 0;
82 #define super IOService
83 OSDefineMetaClassAndStructors(IOPMrootDomain
,IOService
)
87 IONotifier
* registerSleepWakeInterest(IOServiceInterestHandler handler
, void * self
, void * ref
)
89 return gRootDomain
->registerInterest( gIOGeneralInterest
, handler
, self
, ref
);
92 IONotifier
* registerPrioritySleepWakeInterest(IOServiceInterestHandler handler
, void * self
, void * ref
)
94 return gRootDomain
->registerInterest( gIOPriorityPowerStateInterest
, handler
, self
, ref
);
97 IOReturn
acknowledgeSleepWakeNotification(void * PMrefcon
)
99 return gRootDomain
->allowPowerChange ( (unsigned long)PMrefcon
);
102 IOReturn
vetoSleepWakeNotification(void * PMrefcon
)
104 return gRootDomain
->cancelPowerChange ( (unsigned long)PMrefcon
);
107 IOReturn
rootDomainRestart ( void )
109 return gRootDomain
->restartSystem();
112 IOReturn
rootDomainShutdown ( void )
114 return gRootDomain
->shutdownSystem();
117 void IOSystemShutdownNotification ( void )
119 IOCatalogue::disableExternalLinker();
120 for ( int i
= 0; i
< 100; i
++ )
122 if ( OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending
) ) break;
127 int sync_internal(void);
131 A device is always in the highest power state which satisfies its driver, its policy-maker, and any power domain
132 children it has, but within the constraint of the power state provided by its parent. The driver expresses its desire by
133 calling changePowerStateTo(), the policy-maker expresses its desire by calling changePowerStateToPriv(), and the children
134 express their desires by calling requestPowerDomainState().
136 The Root Power Domain owns the policy for idle and demand sleep and doze for the system. It is a power-managed IOService just
137 like the others in the system. It implements several power states which correspond to what we see as Sleep, Doze, etc.
139 The sleep/doze policy is as follows:
140 Sleep and Doze are prevented if the case is open so that nobody will think the machine is off and plug/unplug cards.
141 Sleep and Doze are prevented if the sleep timeout slider in the preferences panel is at zero.
142 The system cannot Sleep, but can Doze if some object in the tree is in a power state marked kIOPMPreventSystemSleep.
144 These three conditions are enforced using the "driver clamp" by calling changePowerStateTo(). For example, if the case is
145 opened, changePowerStateTo(ON_STATE) is called to hold the system on regardless of the desires of the children of the root or
146 the state of the other clamp.
148 Demand Sleep/Doze is initiated by pressing the front panel power button, closing the clamshell, or selecting the menu item.
149 In this case the root's parent actually initiates the power state change so that the root has no choice and does not give
150 applications the opportunity to veto the change.
152 Idle Sleep/Doze occurs if no objects in the tree are in a state marked kIOPMPreventIdleSleep. When this is true, the root's
153 children are not holding the root on, so it sets the "policy-maker clamp" by calling changePowerStateToPriv(ON_STATE)
154 to hold itself on until the sleep timer expires. This timer is set for the difference between the sleep timeout slider and
155 the larger of the display dim timeout slider and the disk spindown timeout slider in the Preferences panel. For example, if
156 the system is set to sleep after thirty idle minutes, and the display and disk are set to sleep after five idle minutes,
157 when there is no longer an object in the tree holding the system out of Idle Sleep (via kIOPMPreventIdleSleep), the root
158 sets its timer for 25 minutes (30 - 5). When the timer expires, it releases its clamp and now nothing is holding it awake,
161 Demand sleep is prevented when the system is booting. When preferences are transmitted by the loginwindow at the end of
162 boot, a flag is cleared, and this allows subsequent Demand Sleep.
164 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
165 a clamp, but sets a flag which is noticed before actually sleeping the kernel. If the flag is set, the root steps up
166 one power state from Sleep to Doze, and any objects in the tree for which this is relevent will act appropriately (USB and
167 ADB will turn on again so that they can wake the system out of Doze (keyboard/mouse activity will cause the Display Wrangler
171 // **********************************************************************************
173 IOPMrootDomain
* IOPMrootDomain::construct( void )
175 IOPMrootDomain
*root
;
177 root
= new IOPMrootDomain
;
184 // **********************************************************************************
186 static void disk_sync_callout(thread_call_param_t p0
, thread_call_param_t p1
)
188 IOService
*rootDomain
= (IOService
*) p0
;
189 unsigned long pmRef
= (unsigned long) p1
;
191 IOHibernateSystemSleep();
193 rootDomain
->allowPowerChange(pmRef
);
196 // **********************************************************************************
199 // We don't do much here. The real initialization occurs when the platform
200 // expert informs us we are the root.
201 // **********************************************************************************
204 bool IOPMrootDomain::start ( IOService
* nub
)
206 OSDictionary
*tmpDict
;
208 pmPowerStateQueue
= 0;
210 _reserved
= (ExpansionData
*)IOMalloc(sizeof(ExpansionData
));
211 if(!_reserved
) return false;
218 setProperty("IOSleepSupported","");
221 sleepIsSupported
= true;
222 systemBooting
= true;
223 ignoringClamshell
= true;
225 idleSleepPending
= false;
229 _settingController
= NULL
;
230 ignoringClamshellDuringWakeup
= false;
232 tmpDict
= OSDictionary::withCapacity(1);
233 setProperty(kRootDomainSupportedFeatures
, tmpDict
);
236 pm_vars
->PMworkloop
= IOWorkLoop::workLoop();
237 pmPowerStateQueue
= IOPMPowerStateQueue::PMPowerStateQueue(this);
238 pm_vars
->PMworkloop
->addEventSource(pmPowerStateQueue
);
240 featuresDictLock
= IOLockAlloc();
242 extraSleepTimer
= thread_call_allocate((thread_call_func_t
)sleepTimerExpired
, (thread_call_param_t
) this);
243 clamshellWakeupIgnore
= thread_call_allocate((thread_call_func_t
)wakeupClamshellTimerExpired
, (thread_call_param_t
) this);
244 diskSyncCalloutEntry
= thread_call_allocate(&disk_sync_callout
, (thread_call_param_t
) this);
247 patriarch
= new IORootParent
;
249 patriarch
->attach(this);
250 patriarch
->start(this);
251 patriarch
->youAreRoot();
252 patriarch
->wakeSystem();
253 patriarch
->addPowerChild(this);
255 registerPowerDriver(this,ourPowerStates
,number_of_power_states
);
257 setPMRootDomain(this);
258 // set a clamp until we sleep
259 changePowerStateToPriv(ON_STATE
);
261 // install power change handler
262 registerPrioritySleepWakeInterest( &sysPowerDownHandler
, this, 0);
264 // Register for a notification when IODisplayWrangler is published
265 _displayWranglerNotifier
= addNotification( gIOPublishNotification
,
266 serviceMatching("IODisplayWrangler"),
267 &displayWranglerPublished
, this, 0);
269 _batteryLocationNotifier
= addNotification( gIOPublishNotification
,
270 resourceMatching("battery"),
271 &batteryLocationPublished
, this, this);
273 const OSSymbol
*ucClassName
= OSSymbol::withCStringNoCopy("RootDomainUserClient");
274 setProperty(gIOUserClientClassKey
, (OSObject
*) ucClassName
);
275 ucClassName
->release();
277 IORegistryEntry
*temp_entry
= NULL
;
278 if( (temp_entry
= IORegistryEntry::fromPath("mac-io/battery", gIODTPlane
)) ||
279 (temp_entry
= IORegistryEntry::fromPath("mac-io/via-pmu/battery", gIODTPlane
)))
281 // If this machine has a battery, publish the fact that the backlight
283 // Notice similar call in IOPMrootDomain::batteryLocationPublished() to
284 // detect batteries on SMU machines.
285 publishFeature("DisplayDims");
286 temp_entry
->release();
289 IOHibernateSystemInit(this);
291 registerService(); // let clients find us
296 IOReturn
IOPMrootDomain::setPMSetting(int type
, OSNumber
*n
)
298 if(_settingController
&& _settingController
->func
) {
300 seconds
= n
->unsigned32BitValue();
301 return (*(_settingController
->func
))(type
, seconds
, _settingController
->refcon
);
303 return kIOReturnNoDevice
;
307 // **********************************************************************************
310 // Receive a setProperty call
311 // The "System Boot" property means the system is completely booted.
312 // **********************************************************************************
313 IOReturn
IOPMrootDomain::setProperties ( OSObject
*props_obj
)
315 IOReturn return_value
= kIOReturnSuccess
;
316 OSDictionary
*dict
= OSDynamicCast(OSDictionary
, props_obj
);
320 const OSSymbol
*boot_complete_string
= OSSymbol::withCString("System Boot Complete");
321 const OSSymbol
*power_button_string
= OSSymbol::withCString("DisablePowerButtonSleep");
322 const OSSymbol
*stall_halt_string
= OSSymbol::withCString("StallSystemAtHalt");
323 const OSSymbol
*auto_wake_string
= OSSymbol::withCString("wake");
324 const OSSymbol
*auto_power_string
= OSSymbol::withCString("poweron");
325 const OSSymbol
*wakeonring_string
= OSSymbol::withCString("WakeOnRing");
326 const OSSymbol
*fileserver_string
= OSSymbol::withCString("AutoRestartOnPowerLoss");
327 const OSSymbol
*wakeonlid_string
= OSSymbol::withCString("WakeOnLid");
328 const OSSymbol
*wakeonac_string
= OSSymbol::withCString("WakeOnACChange");
329 const OSSymbol
*hibernatemode_string
= OSSymbol::withCString(kIOHibernateModeKey
);
330 const OSSymbol
*hibernatefile_string
= OSSymbol::withCString(kIOHibernateFileKey
);
331 const OSSymbol
*hibernatefreeratio_string
= OSSymbol::withCString(kIOHibernateFreeRatioKey
);
332 const OSSymbol
*hibernatefreetime_string
= OSSymbol::withCString(kIOHibernateFreeTimeKey
);
333 const OSSymbol
*timezone_string
= OSSymbol::withCString("TimeZoneOffsetSeconds");
337 return_value
= kIOReturnBadArgument
;
342 && boot_complete_string
343 && dict
->getObject(boot_complete_string
))
345 systemBooting
= false;
349 if( power_button_string
350 && (b
= OSDynamicCast(OSBoolean
, dict
->getObject(power_button_string
))) )
352 setProperty(power_button_string
, b
);
355 if( stall_halt_string
356 && (b
= OSDynamicCast(OSBoolean
, dict
->getObject(stall_halt_string
))) )
358 setProperty(stall_halt_string
, b
);
361 if ( hibernatemode_string
362 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(hibernatemode_string
))))
364 setProperty(hibernatemode_string
, n
);
366 if ( hibernatefreeratio_string
367 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(hibernatefreeratio_string
))))
369 setProperty(hibernatefreeratio_string
, n
);
371 if ( hibernatefreetime_string
372 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(hibernatefreetime_string
))))
374 setProperty(hibernatefreetime_string
, n
);
376 if ( hibernatefile_string
377 && (str
= OSDynamicCast(OSString
, dict
->getObject(hibernatefile_string
))))
379 setProperty(hibernatefile_string
, str
);
382 // Relay AutoWake setting to its controller
384 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(auto_wake_string
))) )
386 return_value
= setPMSetting(kIOPMAutoWakeSetting
, n
);
387 if(kIOReturnSuccess
!= return_value
) goto exit
;
390 // Relay AutoPower setting to its controller
391 if( auto_power_string
392 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(auto_power_string
))) )
394 return_value
= setPMSetting(kIOPMAutoPowerOnSetting
, n
);
395 if(kIOReturnSuccess
!= return_value
) goto exit
;
398 // Relay WakeOnRing setting to its controller
399 if( wakeonring_string
400 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(wakeonring_string
))) )
402 return_value
= setPMSetting(kIOPMWakeOnRingSetting
, n
);
403 if(kIOReturnSuccess
!= return_value
) goto exit
;
406 // Relay FileServer setting to its controller
407 if( fileserver_string
408 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(fileserver_string
))) )
410 return_value
= setPMSetting(kIOPMAutoRestartOnPowerLossSetting
, n
);
411 if(kIOReturnSuccess
!= return_value
) goto exit
;
414 // Relay WakeOnLid setting to its controller
416 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(wakeonlid_string
))) )
418 return_value
= setPMSetting(kIOPMWakeOnLidSetting
, n
);
419 if(kIOReturnSuccess
!= return_value
) goto exit
;
422 // Relay WakeOnACChange setting to its controller
424 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(wakeonac_string
))) )
426 return_value
= setPMSetting(kIOPMWakeOnACChangeSetting
, n
);
427 if(kIOReturnSuccess
!= return_value
) goto exit
;
430 // Relay timezone offset in seconds to SMU
432 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(timezone_string
))) )
434 return_value
= setPMSetting(kIOPMTimeZoneSetting
, n
);
435 if(kIOReturnSuccess
!= return_value
) goto exit
;
440 if(boot_complete_string
) boot_complete_string
->release();
441 if(power_button_string
) power_button_string
->release();
442 if(stall_halt_string
) stall_halt_string
->release();
443 if(auto_wake_string
) auto_wake_string
->release();
444 if(auto_power_string
) auto_power_string
->release();
445 if(wakeonring_string
) wakeonring_string
->release();
446 if(fileserver_string
) fileserver_string
->release();
447 if(wakeonlid_string
) wakeonlid_string
->release();
448 if(wakeonac_string
) wakeonac_string
->release();
449 if(timezone_string
) timezone_string
->release();
454 //*********************************************************************************
457 // Power Managment is informing us that we are the root power domain.
458 // We know we are not the root however, since we have just instantiated a parent
459 // for ourselves and made it the root. We override this method so it will have
461 //*********************************************************************************
462 IOReturn
IOPMrootDomain::youAreRoot ( void )
467 // **********************************************************************************
471 // **********************************************************************************
472 void IOPMrootDomain::command_received ( void * w
, void * x
, void * y
, void * z
)
474 super::command_received(w
,x
,y
,z
);
478 // **********************************************************************************
479 // broadcast_aggressiveness
481 // **********************************************************************************
482 IOReturn
broadcast_aggressiveness ( OSObject
* root
, void * x
, void * y
, void *, void * )
484 ((IOPMrootDomain
*)root
)->broadcast_it((unsigned long)x
,(unsigned long)y
);
489 // **********************************************************************************
492 // We are behind the command gate to broadcast an aggressiveness factor. We let the
493 // superclass do it, but we need to snoop on factors that affect idle sleep.
494 // **********************************************************************************
495 void IOPMrootDomain::broadcast_it (unsigned long type
, unsigned long value
)
497 super::setAggressiveness(type
,value
);
499 // Save user's spin down timer to restore after we replace it for idle sleep
500 if( type
== kPMMinutesToSpinDown
) user_spindown
= value
;
502 // Use longestNonSleepSlider to calculate dimming adjust idle sleep timer
503 longestNonSleepSlider
= pm_vars
->current_aggressiveness_values
[kPMMinutesToDim
];
506 if ( type
== kPMMinutesToSleep
) {
507 if ( (sleepSlider
== 0) && (value
!= 0) ) {
509 // idle sleep is now enabled, maybe sleep now
513 if ( sleepSlider
== 0 ) {
514 // idle sleep is now disabled
516 // make sure we're powered
517 patriarch
->wakeSystem();
520 if ( sleepSlider
> longestNonSleepSlider
) {
521 extraSleepDelay
= sleepSlider
- longestNonSleepSlider
;
529 // **********************************************************************************
532 // **********************************************************************************
533 static void sleepTimerExpired ( thread_call_param_t us
)
535 ((IOPMrootDomain
*)us
)->handleSleepTimerExpiration();
539 static void wakeupClamshellTimerExpired ( thread_call_param_t us
)
541 ((IOPMrootDomain
*)us
)->stopIgnoringClamshellEventsDuringWakeup();
545 // **********************************************************************************
546 // handleSleepTimerExpiration
548 // The time between the sleep idle timeout and the next longest one has elapsed.
549 // It's time to sleep. Start that by removing the clamp that's holding us awake.
550 // **********************************************************************************
551 void IOPMrootDomain::handleSleepTimerExpiration ( void )
553 // accelerate disk spin down if spin down timer is non-zero (zero = never spin down)
554 if(0 != user_spindown
)
555 setQuickSpinDownTimeout();
562 void IOPMrootDomain::stopIgnoringClamshellEventsDuringWakeup(void)
566 // Allow clamshell-induced sleep now
567 ignoringClamshellDuringWakeup
= false;
569 if ((state
= getProperty(kAppleClamshellStateKey
)))
570 publishResource(kAppleClamshellStateKey
, state
);
573 //*********************************************************************************
576 // Some aggressiveness factor has changed. We broadcast it to the hierarchy while on
577 // the Power Mangement workloop thread. This enables objects in the
578 // hierarchy to successfully alter their idle timers, which are all on the
580 //*********************************************************************************
582 static int pmsallsetup
= 0;
584 IOReturn
IOPMrootDomain::setAggressiveness ( unsigned long type
, unsigned long newLevel
)
587 if(pmsExperimental
& 3) kprintf("setAggressiveness: type = %08X, newlevel = %08X\n", type
, newLevel
);
588 if(pmsExperimental
& 1) { /* Is experimental mode enabled? */
589 if(pmsInstalled
&& (type
== kPMSetProcessorSpeed
)) { /* We want to look at all processor speed changes if stepper is installed */
590 if(pmsallsetup
) return kIOReturnSuccess
; /* If already running, just eat this */
591 kprintf("setAggressiveness: starting stepper...\n");
592 pmsallsetup
= 1; /* Remember we did this */
594 pmsStart(); /* Get it all started up... */
595 return kIOReturnSuccess
; /* Leave now... */
600 if ( pm_vars
->PMcommandGate
) {
601 pm_vars
->PMcommandGate
->runAction(broadcast_aggressiveness
,(void *)type
,(void *)newLevel
);
604 return kIOReturnSuccess
;
608 // **********************************************************************************
611 // **********************************************************************************
612 IOReturn
IOPMrootDomain::sleepSystem ( void )
614 //kprintf("sleep demand received\n");
615 if ( !systemBooting
&& allowSleep
&& sleepIsSupported
) {
616 patriarch
->sleepSystem();
618 return kIOReturnSuccess
;
620 if ( !systemBooting
&& allowSleep
&& !sleepIsSupported
) {
621 patriarch
->dozeSystem();
622 return kIOReturnSuccess
;
624 return kIOReturnSuccess
;
628 // **********************************************************************************
631 // **********************************************************************************
632 IOReturn
IOPMrootDomain::shutdownSystem ( void )
634 //patriarch->shutDownSystem();
635 return kIOReturnUnsupported
;
639 // **********************************************************************************
642 // **********************************************************************************
643 IOReturn
IOPMrootDomain::restartSystem ( void )
645 //patriarch->restartSystem();
646 return kIOReturnUnsupported
;
650 // **********************************************************************************
653 // This overrides powerChangeDone in IOService.
655 // Finder sleep and idle sleep move us from the ON state to the SLEEP_STATE.
657 // If we just finished going to the SLEEP_STATE, and the platform is capable of true sleep,
658 // sleep the kernel. Otherwise switch up to the DOZE_STATE which will keep almost
659 // everything as off as it can get.
661 // **********************************************************************************
662 void IOPMrootDomain::powerChangeDone ( unsigned long previousState
)
664 OSNumber
* propertyPtr
;
665 unsigned short theProperty
;
666 AbsoluteTime deadline
;
668 switch ( pm_vars
->myCurrentState
) {
670 if ( canSleep
&& sleepIsSupported
)
672 // re-enable this timer for next sleep
673 idleSleepPending
= false;
675 IOLog("System %sSleep\n", gIOHibernateState
? "Safe" : "");
677 IOHibernateSystemHasSlept();
679 pm_vars
->thePlatform
->sleepKernel();
681 // The CPU(s) are off at this point. When they're awakened by CPU interrupt,
682 // code will resume execution here.
684 // Now we're waking...
685 IOHibernateSystemWake();
687 // stay awake for at least 30 seconds
688 clock_interval_to_deadline(30, kSecondScale
, &deadline
);
689 thread_call_enter_delayed(extraSleepTimer
, deadline
);
690 // this gets turned off when we sleep again
691 idleSleepPending
= true;
693 // Ignore closed clamshell during wakeup and for a few seconds
694 // after wakeup is complete
695 ignoringClamshellDuringWakeup
= true;
697 // sleep transition complete
698 gSleepOrShutdownPending
= 0;
700 // trip the reset of the calendar clock
701 clock_wakeup_calendar();
704 patriarch
->wakeSystem();
706 // early stage wake notification
707 tellClients(kIOMessageSystemWillPowerOn
);
709 // tell the tree we're waking
710 IOLog("System %sWake\n", gIOHibernateState
? "SafeSleep " : "");
713 // Allow drivers to request extra processing time before clamshell
714 // sleep if kIOREMSleepEnabledKey is present.
715 // Ignore clamshell events for at least 5 seconds
716 if(getProperty(kIOREMSleepEnabledKey
)) {
717 // clamshellWakeupIgnore callout clears ignoreClamshellDuringWakeup bit
718 clock_interval_to_deadline(5, kSecondScale
, &deadline
);
719 if(clamshellWakeupIgnore
) thread_call_enter_delayed(clamshellWakeupIgnore
, deadline
);
720 } else ignoringClamshellDuringWakeup
= false;
722 // Find out what woke us
723 propertyPtr
= OSDynamicCast(OSNumber
,getProperty("WakeEvent"));
725 theProperty
= propertyPtr
->unsigned16BitValue();
726 IOLog("Wake event %04x\n",theProperty
);
727 if ( (theProperty
& 0x0008) || //lid
728 (theProperty
& 0x0800) || // front panel button
729 (theProperty
& 0x0020) || // external keyboard
730 (theProperty
& 0x0001) ) { // internal keyboard
731 // We've identified the wakeup event as UI driven
735 // Since we can't identify the wakeup event, treat it as UI activity
739 // Wake for thirty seconds
740 changePowerStateToPriv(ON_STATE
);
741 powerOverrideOffPriv();
743 // allow us to step up a power state
744 patriarch
->sleepToDoze();
746 changePowerStateToPriv(DOZE_STATE
);
751 if ( previousState
!= DOZE_STATE
)
753 IOLog("System Doze\n");
755 // re-enable this timer for next sleep
756 idleSleepPending
= false;
757 gSleepOrShutdownPending
= 0;
761 IOLog("System Restart\n");
762 PEHaltRestart(kPERestartCPU
);
766 IOLog("System Halt\n");
767 PEHaltRestart(kPEHaltCPU
);
773 // **********************************************************************************
776 // The Display Wrangler calls here when it switches to its highest state. If the
777 // system is currently dozing, allow it to wake by making sure the parent is
779 // **********************************************************************************
780 void IOPMrootDomain::wakeFromDoze( void )
782 if ( pm_vars
->myCurrentState
== DOZE_STATE
)
784 // reset this till next attempt
786 powerOverrideOffPriv();
788 // early wake notification
789 tellClients(kIOMessageSystemWillPowerOn
);
791 // allow us to wake if children so desire
792 patriarch
->wakeSystem();
797 // **********************************************************************************
800 // Adds a new feature to the supported features dictionary
803 // **********************************************************************************
804 void IOPMrootDomain::publishFeature( const char * feature
)
806 if(featuresDictLock
) IOLockLock(featuresDictLock
);
807 OSDictionary
*features
=
808 (OSDictionary
*) getProperty(kRootDomainSupportedFeatures
);
810 if ( features
&& OSDynamicCast(OSDictionary
, features
))
811 features
= OSDictionary::withDictionary(features
);
813 features
= OSDictionary::withCapacity(1);
815 features
->setObject(feature
, kOSBooleanTrue
);
816 setProperty(kRootDomainSupportedFeatures
, features
);
818 if(featuresDictLock
) IOLockUnlock(featuresDictLock
);
822 void IOPMrootDomain::unIdleDevice( IOService
*theDevice
, unsigned long theState
)
824 if(pmPowerStateQueue
)
825 pmPowerStateQueue
->unIdleOccurred(theDevice
, theState
);
828 void IOPMrootDomain::announcePowerSourceChange( void )
830 IORegistryEntry
*_batteryRegEntry
= (IORegistryEntry
*) getProperty("BatteryEntry");
832 // (if possible) re-publish power source state under IOPMrootDomain
833 // (only done if the battery controller publishes an IOResource defining battery location)
837 batt_info
= (OSArray
*) _batteryRegEntry
->getProperty(kIOBatteryInfoKey
);
839 setProperty(kIOBatteryInfoKey
, batt_info
);
842 messageClients(kIOPMMessageBatteryStatusHasChanged
);
845 IOReturn
IOPMrootDomain::registerPMSettingController
846 (IOPMSettingControllerCallback func
, void *info
)
848 if(_settingController
) return kIOReturnExclusiveAccess
;
850 _settingController
= (PMSettingCtrl
*)IOMalloc(sizeof(PMSettingCtrl
));
851 if(!_settingController
) return kIOReturnNoMemory
;
853 _settingController
->func
= func
;
854 _settingController
->refcon
= info
;
855 return kIOReturnSuccess
;
859 //*********************************************************************************
860 // receivePowerNotification
862 // The power controller is notifying us of a hardware-related power management
863 // event that we must handle. This is a result of an 'environment' interrupt from
864 // the power mgt micro.
865 //*********************************************************************************
867 IOReturn
IOPMrootDomain::receivePowerNotification (UInt32 msg
)
869 if (msg
& kIOPMOverTemp
)
871 IOLog("Power Management received emergency overtemp signal. Going to sleep.");
872 (void) sleepSystem ();
874 if (msg
& kIOPMSetDesktopMode
)
876 desktopMode
= (0 != (msg
& kIOPMSetValue
));
877 msg
&= ~(kIOPMSetDesktopMode
| kIOPMSetValue
);
879 if (msg
& kIOPMSetACAdaptorConnected
)
881 acAdaptorConnect
= (0 != (msg
& kIOPMSetValue
));
882 msg
&= ~(kIOPMSetACAdaptorConnected
| kIOPMSetValue
);
884 if (msg
& kIOPMEnableClamshell
)
886 ignoringClamshell
= false;
888 if (msg
& kIOPMDisableClamshell
)
890 ignoringClamshell
= true;
893 if (msg
& kIOPMProcessorSpeedChange
)
895 IOService
*pmu
= waitForService(serviceMatching("ApplePMU"));
896 pmu
->callPlatformFunction("prepareForSleep", false, 0, 0, 0, 0);
897 pm_vars
->thePlatform
->sleepKernel();
898 pmu
->callPlatformFunction("recoverFromSleep", false, 0, 0, 0, 0);
901 if (msg
& kIOPMSleepNow
)
903 (void) sleepSystem ();
906 if (msg
& kIOPMPowerEmergency
)
908 (void) sleepSystem ();
911 if (msg
& kIOPMClamshellClosed
)
913 if ( !ignoringClamshell
&& !ignoringClamshellDuringWakeup
914 && (!desktopMode
|| !acAdaptorConnect
) )
917 (void) sleepSystem ();
921 if (msg
& kIOPMPowerButton
)
923 // toggle state of sleep/wake
925 if ( pm_vars
->myCurrentState
== DOZE_STATE
)
927 // yes, tell the tree we're waking
929 // wake the Display Wrangler
933 // Check that power button sleep is enabled
934 if(kOSBooleanTrue
!= getProperty(OSString::withCString("DisablePowerButtonSleep")))
939 // if the case has been closed, we allow
940 // the machine to be put to sleep or to idle sleep
942 if ( (msg
& kIOPMAllowSleep
) && !allowSleep
)
948 // if the case has been opened, we disallow sleep/doze
950 if (msg
& kIOPMPreventSleep
) {
953 if ( pm_vars
->myCurrentState
== DOZE_STATE
) {
954 // yes, tell the tree we're waking
957 // wake the Display Wrangler
961 // make sure we have power to clamp
962 patriarch
->wakeSystem();
970 //*********************************************************************************
973 //*********************************************************************************
975 void IOPMrootDomain::setSleepSupported( IOOptionBits flags
)
977 if ( flags
& kPCICantSleep
)
981 platformSleepSupport
= flags
;
986 //*********************************************************************************
987 // requestPowerDomainState
989 // The root domain intercepts this call to the superclass.
991 // If the clamp bit is not set in the desire, then the child doesn't need the power
992 // state it's requesting; it just wants it. The root ignores desires but not needs.
993 // If the clamp bit is not set, the root takes it that the child can tolerate no
994 // power and interprets the request accordingly. If all children can thus tolerate
995 // no power, we are on our way to idle sleep.
996 //*********************************************************************************
998 IOReturn
IOPMrootDomain::requestPowerDomainState ( IOPMPowerFlags desiredState
, IOPowerConnection
* whichChild
, unsigned long specification
)
1002 IOPowerConnection
*connection
;
1003 unsigned long powerRequestFlag
= 0;
1004 IOPMPowerFlags editedDesire
= desiredState
;
1006 // if they don't really need it, they don't get it
1007 if ( !(desiredState
& kIOPMPreventIdleSleep
) ) {
1012 IOLockLock(pm_vars
->childLock
);
1014 // recompute sleepIsSupported and see if all children are asleep
1015 iter
= getChildIterator(gIOPowerPlane
);
1016 sleepIsSupported
= true;
1019 while ( (next
= iter
->getNextObject()) )
1021 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1023 if ( connection
== whichChild
)
1025 powerRequestFlag
+= editedDesire
;
1026 if ( desiredState
& kIOPMPreventSystemSleep
)
1028 sleepIsSupported
= false;
1031 powerRequestFlag
+= connection
->getDesiredDomainState();
1032 if ( connection
->getPreventSystemSleepFlag() )
1034 sleepIsSupported
= false;
1042 if ( (extraSleepDelay
== 0) && (powerRequestFlag
== 0) )
1047 // this may put the system to sleep
1050 IOLockUnlock(pm_vars
->childLock
);
1052 editedDesire
|= desiredState
& kIOPMPreventSystemSleep
;
1054 return super::requestPowerDomainState(editedDesire
,whichChild
,specification
);
1058 //*********************************************************************************
1059 // getSleepSupported
1061 //*********************************************************************************
1063 IOOptionBits
IOPMrootDomain::getSleepSupported( void )
1065 return( platformSleepSupport
);
1069 //*********************************************************************************
1072 // We override the superclass implementation so we can send a different message
1073 // type to the client or application being notified.
1074 //*********************************************************************************
1076 bool IOPMrootDomain::tellChangeDown ( unsigned long stateNum
)
1078 switch ( stateNum
) {
1081 return super::tellClientsWithResponse(kIOMessageSystemWillSleep
);
1083 return super::tellClientsWithResponse(kIOMessageSystemWillRestart
);
1085 return super::tellClientsWithResponse(kIOMessageSystemWillPowerOff
);
1087 // this shouldn't execute
1088 return super::tellChangeDown(stateNum
);
1092 //*********************************************************************************
1095 // We override the superclass implementation so we can send a different message
1096 // type to the client or application being notified.
1098 // This must be idle sleep since we don't ask apps during any other power change.
1099 //*********************************************************************************
1101 bool IOPMrootDomain::askChangeDown ( unsigned long )
1103 return super::tellClientsWithResponse(kIOMessageCanSystemSleep
);
1107 //*********************************************************************************
1110 // Notify registered applications and kernel clients that we are not
1113 // We override the superclass implementation so we can send a different message
1114 // type to the client or application being notified.
1116 // This must be a vetoed idle sleep, since no other power change can be vetoed.
1117 //*********************************************************************************
1119 void IOPMrootDomain::tellNoChangeDown ( unsigned long )
1121 return tellClients(kIOMessageSystemWillNotSleep
);
1125 //*********************************************************************************
1128 // Notify registered applications and kernel clients that we are raising power.
1130 // We override the superclass implementation so we can send a different message
1131 // type to the client or application being notified.
1132 //*********************************************************************************
1134 void IOPMrootDomain::tellChangeUp ( unsigned long stateNum
)
1136 if ( stateNum
== ON_STATE
)
1138 IOHibernateSystemPostWake();
1139 return tellClients(kIOMessageSystemHasPoweredOn
);
1143 //*********************************************************************************
1146 //*********************************************************************************
1148 void IOPMrootDomain::reportUserInput ( void )
1154 iter
= getMatchingServices(serviceMatching("IODisplayWrangler"));
1157 wrangler
= (IOService
*) iter
->getNextObject();
1163 wrangler
->activityTickle(0,0);
1166 //*********************************************************************************
1167 // setQuickSpinDownTimeout
1169 //*********************************************************************************
1171 void IOPMrootDomain::setQuickSpinDownTimeout ( void )
1173 super::setAggressiveness((unsigned long)kPMMinutesToSpinDown
,(unsigned long)1);
1176 //*********************************************************************************
1177 // restoreUserSpinDownTimeout
1179 //*********************************************************************************
1181 void IOPMrootDomain::restoreUserSpinDownTimeout ( void )
1183 super::setAggressiveness((unsigned long)kPMMinutesToSpinDown
,(unsigned long)user_spindown
);
1186 //*********************************************************************************
1187 // changePowerStateTo & changePowerStateToPriv
1189 // Override of these methods for logging purposes.
1190 //*********************************************************************************
1192 IOReturn
IOPMrootDomain::changePowerStateTo ( unsigned long ordinal
)
1194 return super::changePowerStateTo(ordinal
);
1197 IOReturn
IOPMrootDomain::changePowerStateToPriv ( unsigned long ordinal
)
1199 return super::changePowerStateToPriv(ordinal
);
1203 //*********************************************************************************
1204 // sysPowerDownHandler
1206 // Receives a notification when the RootDomain changes state.
1208 // Allows us to take action on system sleep, power down, and restart after
1209 // applications have received their power change notifications and replied,
1210 // but before drivers have powered down. We perform a vfs sync on power down.
1211 //*********************************************************************************
1213 IOReturn
IOPMrootDomain::sysPowerDownHandler( void * target
, void * refCon
,
1214 UInt32 messageType
, IOService
* service
,
1215 void * messageArgument
, vm_size_t argSize
)
1218 IOPowerStateChangeNotification
*params
= (IOPowerStateChangeNotification
*) messageArgument
;
1219 IOPMrootDomain
*rootDomain
= OSDynamicCast(IOPMrootDomain
, service
);
1222 return kIOReturnUnsupported
;
1224 switch (messageType
) {
1225 case kIOMessageSystemWillSleep
:
1226 rootDomain
->powerOverrideOnPriv(); // start ignoring children's requests
1227 // (fall through to other cases)
1229 // Interested applications have been notified of an impending power
1230 // change and have acked (when applicable).
1231 // This is our chance to save whatever state we can before powering
1233 // We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c,
1236 // We will ack within 20 seconds
1237 params
->returnValue
= 20 * 1000 * 1000;
1238 if (gIOHibernateState
)
1239 params
->returnValue
+= gIOHibernateFreeTime
* 1000; //add in time we could spend freeing pages
1241 if ( ! OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending
) )
1243 // Purposely delay the ack and hope that shutdown occurs quickly.
1244 // Another option is not to schedule the thread and wait for
1246 AbsoluteTime deadline
;
1247 clock_interval_to_deadline( 30, kSecondScale
, &deadline
);
1248 thread_call_enter1_delayed( rootDomain
->diskSyncCalloutEntry
,
1249 (thread_call_param_t
)params
->powerRef
,
1253 thread_call_enter1(rootDomain
->diskSyncCalloutEntry
, (thread_call_param_t
)params
->powerRef
);
1254 ret
= kIOReturnSuccess
;
1257 case kIOMessageSystemWillPowerOff
:
1258 case kIOMessageSystemWillRestart
:
1259 ret
= kIOReturnUnsupported
;
1263 ret
= kIOReturnUnsupported
;
1269 //*********************************************************************************
1270 // displayWranglerNotification
1272 // Receives a notification when the IODisplayWrangler changes state.
1274 // Allows us to take action on display dim/undim.
1276 // When the display goes dim we:
1277 // - Start the idle sleep timer
1278 // - set the quick spin down timeout
1280 // On wake from display dim:
1281 // - Cancel the idle sleep timer
1282 // - restore the user's chosen spindown timer from the "quick" spin down value
1283 //*********************************************************************************
1285 IOReturn
IOPMrootDomain::displayWranglerNotification( void * target
, void * refCon
,
1286 UInt32 messageType
, IOService
* service
,
1287 void * messageArgument
, vm_size_t argSize
)
1289 IOPMrootDomain
* rootDomain
= OSDynamicCast(IOPMrootDomain
, (IOService
*)target
);
1290 AbsoluteTime deadline
;
1291 static bool deviceAlreadyPoweredOff
= false;
1294 return kIOReturnUnsupported
;
1296 switch (messageType
) {
1297 case kIOMessageDeviceWillPowerOff
:
1298 // The IODisplayWrangler has powered off either because of idle display sleep
1299 // or force system sleep.
1301 // The display wrangler will send the DeviceWillPowerOff message 4 times until
1302 // it gets into its lowest state. We only want to act on the first of those 4.
1303 if( deviceAlreadyPoweredOff
) return kIOReturnUnsupported
;
1305 deviceAlreadyPoweredOff
= true;
1307 if( rootDomain
->extraSleepDelay
)
1309 // start the extra sleep timer
1310 clock_interval_to_deadline(rootDomain
->extraSleepDelay
*60, kSecondScale
, &deadline
);
1311 thread_call_enter_delayed(rootDomain
->extraSleepTimer
, deadline
);
1312 rootDomain
->idleSleepPending
= true;
1314 // accelerate disk spin down if spin down timer is non-zero (zero = never spin down)
1315 // and if system sleep is non-Never
1316 if( (0 != rootDomain
->user_spindown
) && (0 != rootDomain
->sleepSlider
) )
1317 rootDomain
->setQuickSpinDownTimeout();
1322 case kIOMessageDeviceHasPoweredOn
:
1324 // The display has powered on either because of UI activity or wake from sleep/doze
1325 deviceAlreadyPoweredOff
= false;
1326 rootDomain
->adjustPowerState();
1329 // cancel any pending idle sleep
1330 if(rootDomain
->idleSleepPending
)
1332 thread_call_cancel(rootDomain
->extraSleepTimer
);
1333 rootDomain
->idleSleepPending
= false;
1336 // Change the spindown value back to the user's selection from our accelerated setting
1337 if(0 != rootDomain
->user_spindown
)
1338 rootDomain
->restoreUserSpinDownTimeout();
1340 // Put on the policy maker's on clamp.
1347 return kIOReturnUnsupported
;
1350 //*********************************************************************************
1351 // displayWranglerPublished
1353 // Receives a notification when the IODisplayWrangler is published.
1354 // When it's published we install a power state change handler.
1356 //*********************************************************************************
1358 bool IOPMrootDomain::displayWranglerPublished( void * target
, void * refCon
,
1359 IOService
* newService
)
1361 IOPMrootDomain
* rootDomain
= OSDynamicCast(IOPMrootDomain
, (IOService
*)target
);
1366 rootDomain
->wrangler
= newService
;
1368 // we found the display wrangler, now install a handler
1369 if( !rootDomain
->wrangler
->registerInterest( gIOGeneralInterest
, &displayWranglerNotification
, target
, 0) ) {
1370 IOLog("IOPMrootDomain::displayWranglerPublished registerInterest failed\n");
1377 //*********************************************************************************
1378 // batteryLocationPublished
1380 // Notification on AppleSMU publishing location of battery data
1382 //*********************************************************************************
1384 bool IOPMrootDomain::batteryLocationPublished( void * target
, void * root_domain
,
1385 IOService
* resourceService
)
1387 IORegistryEntry
*battery_location
;
1389 battery_location
= (IORegistryEntry
*) resourceService
->getProperty("battery");
1390 if (!battery_location
|| !OSDynamicCast(IORegistryEntry
, battery_location
))
1393 ((IOPMrootDomain
*)root_domain
)->setProperty("BatteryEntry", battery_location
);
1396 // All laptops have dimmable LCD displays
1397 // All laptops have batteries
1398 // So if this machine has a battery, publish the fact that the backlight
1399 // supports dimming.
1400 ((IOPMrootDomain
*)root_domain
)->publishFeature("DisplayDims");
1402 ((IOPMrootDomain
*)root_domain
)->announcePowerSourceChange();
1408 //*********************************************************************************
1411 // Some condition that affects our wake/sleep/doze decision has changed.
1413 // If the sleep slider is in the off position, we cannot sleep or doze.
1414 // If the enclosure is open, we cannot sleep or doze.
1415 // If the system is still booting, we cannot sleep or doze.
1417 // In those circumstances, we prevent sleep and doze by holding power on with
1418 // changePowerStateToPriv(ON).
1420 // If the above conditions do not exist, and also the sleep timer has expired, we
1421 // allow sleep or doze to occur with either changePowerStateToPriv(SLEEP) or
1422 // changePowerStateToPriv(DOZE) depending on whether or not we already know the
1423 // platform cannot sleep.
1425 // In this case, sleep or doze will either occur immediately or at the next time
1426 // that no children are holding the system out of idle sleep via the
1427 // kIOPMPreventIdleSleep flag in their power state arrays.
1428 //*********************************************************************************
1430 void IOPMrootDomain::adjustPowerState( void )
1432 if ( (sleepSlider
== 0) ||
1435 changePowerStateToPriv(ON_STATE
);
1440 if ( sleepIsSupported
)
1442 changePowerStateToPriv(SLEEP_STATE
);
1444 changePowerStateToPriv(DOZE_STATE
);
1451 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1454 #define super IOService
1456 OSDefineMetaClassAndStructors(IORootParent
, IOService
)
1458 // This array exactly parallels the state array for the root domain.
1459 // Power state changes initiated by a device can be vetoed by a client of the device, and
1460 // power state changes initiated by the parent of a device cannot be vetoed by a client of the device,
1461 // so when the root domain wants a power state change that cannot be vetoed (e.g. demand sleep), it asks
1462 // its parent to make the change. That is the reason for this complexity.
1464 static IOPMPowerState patriarchPowerStates
[number_of_power_states
] = {
1465 {1,0,0,0,0,0,0,0,0,0,0,0}, // off
1466 {1,0,RESTART_POWER
,0,0,0,0,0,0,0,0,0}, // reset
1467 {1,0,SLEEP_POWER
,0,0,0,0,0,0,0,0,0}, // sleep
1468 {1,0,DOZE_POWER
,0,0,0,0,0,0,0,0,0}, // doze
1469 {1,0,ON_POWER
,0,0,0,0,0,0,0,0,0} // running
1472 bool IORootParent::start ( IOService
* nub
)
1474 mostRecentChange
= ON_STATE
;
1477 registerPowerDriver(this,patriarchPowerStates
,number_of_power_states
);
1478 powerOverrideOnPriv();
1483 void IORootParent::shutDownSystem ( void )
1485 mostRecentChange
= OFF_STATE
;
1486 changePowerStateToPriv(OFF_STATE
);
1490 void IORootParent::restartSystem ( void )
1492 mostRecentChange
= RESTART_STATE
;
1493 changePowerStateToPriv(RESTART_STATE
);
1497 void IORootParent::sleepSystem ( void )
1499 mostRecentChange
= SLEEP_STATE
;
1500 changePowerStateToPriv(SLEEP_STATE
);
1504 void IORootParent::dozeSystem ( void )
1506 mostRecentChange
= DOZE_STATE
;
1507 changePowerStateToPriv(DOZE_STATE
);
1510 // Called in demand sleep when sleep discovered to be impossible after actually attaining that state.
1511 // This brings the parent to doze, which allows the root to step up from sleep to doze.
1513 // In idle sleep, do nothing because the parent is still on and the root can freely change state.
1515 void IORootParent::sleepToDoze ( void )
1517 if ( mostRecentChange
== SLEEP_STATE
) {
1518 changePowerStateToPriv(DOZE_STATE
);
1523 void IORootParent::wakeSystem ( void )
1525 mostRecentChange
= ON_STATE
;
1526 changePowerStateToPriv(ON_STATE
);