2 * Copyright (c) 1998-2000 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/IOMessage.h>
31 #include "RootDomainUserClient.h"
32 #include "IOKit/pwr_mgt/IOPowerConnection.h"
33 #include "IOPMPowerStateQueue.h"
35 extern "C" void kprintf(const char *, ...);
37 extern const IORegistryPlane
* gIOPowerPlane
;
39 // debug trace function
41 ioSPMTrace(unsigned int csc
,
42 unsigned int a
= 0, unsigned int b
= 0,
43 unsigned int c
= 0, unsigned int d
= 0)
45 if (gIOKitDebug
& kIOLogTracePower
)
46 IOTimeStampConstant(IODBG_POWER(csc
), a
, b
, c
, d
);
49 IOReturn
broadcast_aggressiveness ( OSObject
*, void *, void *, void *, void * );
50 static void sleepTimerExpired(thread_call_param_t
);
51 static void wakeupClamshellTimerExpired ( thread_call_param_t us
);
54 #define number_of_power_states 5
56 #define RESTART_STATE 1
61 #define ON_POWER kIOPMPowerOn
62 #define RESTART_POWER kIOPMRestart
63 #define SLEEP_POWER kIOPMAuxPowerOn
64 #define DOZE_POWER kIOPMDoze
66 static IOPMPowerState ourPowerStates
[number_of_power_states
] = {
67 {1,0, 0, 0,0,0,0,0,0,0,0,0}, // state 0, off
68 {1,kIOPMRestartCapability
, kIOPMRestart
, RESTART_POWER
,0,0,0,0,0,0,0,0}, // state 1, restart
69 {1,kIOPMSleepCapability
, kIOPMSleep
, SLEEP_POWER
,0,0,0,0,0,0,0,0}, // state 2, sleep
70 {1,kIOPMDoze
, kIOPMDoze
, DOZE_POWER
,0,0,0,0,0,0,0,0}, // state 3, doze
71 {1,kIOPMPowerOn
, kIOPMPowerOn
, ON_POWER
,0,0,0,0,0,0,0,0}, // state 4, on
74 // RESERVED IOPMrootDomain class variables
75 #define diskSyncCalloutEntry _reserved->diskSyncCalloutEntry
76 #define _settingController _reserved->_settingController
77 #define _batteryLocationNotifier _reserved->_batteryLocationNotifier
78 #define _displayWranglerNotifier _reserved->_displayWranglerNotifier
81 static IOPMrootDomain
* gRootDomain
;
82 static UInt32 gSleepOrShutdownPending
= 0;
85 #define super IOService
86 OSDefineMetaClassAndStructors(IOPMrootDomain
,IOService
)
90 IONotifier
* registerSleepWakeInterest(IOServiceInterestHandler handler
, void * self
, void * ref
= 0)
92 return gRootDomain
->registerInterest( gIOGeneralInterest
, handler
, self
, ref
);
95 IONotifier
* registerPrioritySleepWakeInterest(IOServiceInterestHandler handler
, void * self
, void * ref
= 0)
97 return gRootDomain
->registerInterest( gIOPriorityPowerStateInterest
, handler
, self
, ref
);
100 IOReturn
acknowledgeSleepWakeNotification(void * PMrefcon
)
102 return gRootDomain
->allowPowerChange ( (unsigned long)PMrefcon
);
105 IOReturn
vetoSleepWakeNotification(void * PMrefcon
)
107 return gRootDomain
->cancelPowerChange ( (unsigned long)PMrefcon
);
110 IOReturn
rootDomainRestart ( void )
112 return gRootDomain
->restartSystem();
115 IOReturn
rootDomainShutdown ( void )
117 return gRootDomain
->shutdownSystem();
120 void IOSystemShutdownNotification ( void )
122 for ( int i
= 0; i
< 100; i
++ )
124 if ( OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending
) ) break;
129 int sync_internal(void);
133 A device is always in the highest power state which satisfies its driver, its policy-maker, and any power domain
134 children it has, but within the constraint of the power state provided by its parent. The driver expresses its desire by
135 calling changePowerStateTo(), the policy-maker expresses its desire by calling changePowerStateToPriv(), and the children
136 express their desires by calling requestPowerDomainState().
138 The Root Power Domain owns the policy for idle and demand sleep and doze for the system. It is a power-managed IOService just
139 like the others in the system. It implements several power states which correspond to what we see as Sleep, Doze, etc.
141 The sleep/doze policy is as follows:
142 Sleep and Doze are prevented if the case is open so that nobody will think the machine is off and plug/unplug cards.
143 Sleep and Doze are prevented if the sleep timeout slider in the preferences panel is at zero.
144 The system cannot Sleep, but can Doze if some object in the tree is in a power state marked kIOPMPreventSystemSleep.
146 These three conditions are enforced using the "driver clamp" by calling changePowerStateTo(). For example, if the case is
147 opened, changePowerStateTo(ON_STATE) is called to hold the system on regardless of the desires of the children of the root or
148 the state of the other clamp.
150 Demand Sleep/Doze is initiated by pressing the front panel power button, closing the clamshell, or selecting the menu item.
151 In this case the root's parent actually initiates the power state change so that the root has no choice and does not give
152 applications the opportunity to veto the change.
154 Idle Sleep/Doze occurs if no objects in the tree are in a state marked kIOPMPreventIdleSleep. When this is true, the root's
155 children are not holding the root on, so it sets the "policy-maker clamp" by calling changePowerStateToPriv(ON_STATE)
156 to hold itself on until the sleep timer expires. This timer is set for the difference between the sleep timeout slider and
157 the larger of the display dim timeout slider and the disk spindown timeout slider in the Preferences panel. For example, if
158 the system is set to sleep after thirty idle minutes, and the display and disk are set to sleep after five idle minutes,
159 when there is no longer an object in the tree holding the system out of Idle Sleep (via kIOPMPreventIdleSleep), the root
160 sets its timer for 25 minutes (30 - 5). When the timer expires, it releases its clamp and now nothing is holding it awake,
163 Demand sleep is prevented when the system is booting. When preferences are transmitted by the loginwindow at the end of
164 boot, a flag is cleared, and this allows subsequent Demand Sleep.
166 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
167 a clamp, but sets a flag which is noticed before actually sleeping the kernel. If the flag is set, the root steps up
168 one power state from Sleep to Doze, and any objects in the tree for which this is relevent will act appropriately (USB and
169 ADB will turn on again so that they can wake the system out of Doze (keyboard/mouse activity will cause the Display Wrangler
173 // **********************************************************************************
175 IOPMrootDomain
* IOPMrootDomain::construct( void )
177 IOPMrootDomain
*root
;
179 root
= new IOPMrootDomain
;
186 // **********************************************************************************
188 static void disk_sync_callout(thread_call_param_t p0
, thread_call_param_t p1
)
190 IOService
*rootDomain
= (IOService
*) p0
;
191 unsigned long pmRef
= (unsigned long) p1
;
194 rootDomain
->allowPowerChange(pmRef
);
197 // **********************************************************************************
200 // We don't do much here. The real initialization occurs when the platform
201 // expert informs us we are the root.
202 // **********************************************************************************
205 bool IOPMrootDomain::start ( IOService
* nub
)
207 OSDictionary
*tmpDict
;
209 pmPowerStateQueue
= 0;
211 _reserved
= (ExpansionData
*)IOMalloc(sizeof(ExpansionData
));
212 if(!_reserved
) return false;
219 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 extraSleepTimer
= thread_call_allocate((thread_call_func_t
)sleepTimerExpired
, (thread_call_param_t
) this);
241 clamshellWakeupIgnore
= thread_call_allocate((thread_call_func_t
)wakeupClamshellTimerExpired
, (thread_call_param_t
) this);
242 diskSyncCalloutEntry
= thread_call_allocate(&disk_sync_callout
, (thread_call_param_t
) this);
245 patriarch
= new IORootParent
;
247 patriarch
->attach(this);
248 patriarch
->start(this);
249 patriarch
->youAreRoot();
250 patriarch
->wakeSystem();
251 patriarch
->addPowerChild(this);
253 registerPowerDriver(this,ourPowerStates
,number_of_power_states
);
255 setPMRootDomain(this);
256 // set a clamp until we sleep
257 changePowerStateToPriv(ON_STATE
);
259 // install power change handler
260 registerPrioritySleepWakeInterest( &sysPowerDownHandler
, this, 0);
262 // Register for a notification when IODisplayWrangler is published
263 _displayWranglerNotifier
= addNotification( gIOPublishNotification
,
264 serviceMatching("IODisplayWrangler"),
265 &displayWranglerPublished
, this, 0);
267 _batteryLocationNotifier
= addNotification( gIOPublishNotification
,
268 resourceMatching("battery"),
269 &batteryLocationPublished
, this, this);
271 const OSSymbol
*ucClassName
= OSSymbol::withCStringNoCopy("RootDomainUserClient");
272 setProperty(gIOUserClientClassKey
, (OSMetaClassBase
*) ucClassName
);
273 ucClassName
->release();
275 registerService(); // let clients find us
280 IOReturn
IOPMrootDomain::setPMSetting(int type
, OSNumber
*n
)
282 if(_settingController
&& _settingController
->func
) {
284 seconds
= n
->unsigned32BitValue();
285 return (*(_settingController
->func
))(type
, seconds
, _settingController
->refcon
);
287 return kIOReturnNoDevice
;
291 // **********************************************************************************
294 // Receive a setProperty call
295 // The "System Boot" property means the system is completely booted.
296 // **********************************************************************************
297 IOReturn
IOPMrootDomain::setProperties ( OSObject
*props_obj
)
299 IOReturn return_value
= kIOReturnSuccess
;
300 OSDictionary
*dict
= OSDynamicCast(OSDictionary
, props_obj
);
303 OSString
*boot_complete_string
= OSString::withCString("System Boot Complete");
304 OSString
*power_button_string
= OSString::withCString("DisablePowerButtonSleep");
305 OSString
*stall_halt_string
= OSString::withCString("StallSystemAtHalt");
306 OSString
*auto_wake_string
= OSString::withCString("wake");
307 OSString
*auto_power_string
= OSString::withCString("poweron");
308 OSString
*wakeonring_string
= OSString::withCString("WakeOnRing");
309 OSString
*fileserver_string
= OSString::withCString("AutoRestartOnPowerLoss");
310 OSString
*wakeonlid_string
= OSString::withCString("WakeOnLid");
311 OSString
*wakeonac_string
= OSString::withCString("WakeOnACChange");
315 return_value
= kIOReturnBadArgument
;
320 && boot_complete_string
321 && dict
->getObject(boot_complete_string
))
323 systemBooting
= false;
327 if( power_button_string
328 && (b
= OSDynamicCast(OSBoolean
, dict
->getObject(power_button_string
))) )
330 setProperty(power_button_string
, b
);
333 if( stall_halt_string
334 && (b
= OSDynamicCast(OSBoolean
, dict
->getObject(stall_halt_string
))) )
336 setProperty(stall_halt_string
, b
);
339 // Relay AutoWake setting to its controller
341 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(auto_wake_string
))) )
343 return_value
= setPMSetting(kIOPMAutoWakeSetting
, n
);
344 if(kIOReturnSuccess
!= return_value
) goto exit
;
347 // Relay AutoPower setting to its controller
348 if( auto_power_string
349 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(auto_power_string
))) )
351 return_value
= setPMSetting(kIOPMAutoPowerOnSetting
, n
);
352 if(kIOReturnSuccess
!= return_value
) goto exit
;
355 // Relay WakeOnRing setting to its controller
356 if( wakeonring_string
357 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(wakeonring_string
))) )
359 return_value
= setPMSetting(kIOPMWakeOnRingSetting
, n
);
360 if(kIOReturnSuccess
!= return_value
) goto exit
;
363 // Relay FileServer setting to its controller
364 if( fileserver_string
365 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(fileserver_string
))) )
367 return_value
= setPMSetting(kIOPMAutoRestartOnPowerLossSetting
, n
);
368 if(kIOReturnSuccess
!= return_value
) goto exit
;
371 // Relay WakeOnLid setting to its controller
373 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(wakeonlid_string
))) )
375 return_value
= setPMSetting(kIOPMWakeOnLidSetting
, n
);
376 if(kIOReturnSuccess
!= return_value
) goto exit
;
379 // Relay WakeOnACChange setting to its controller
381 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(wakeonac_string
))) )
383 return_value
= setPMSetting(kIOPMWakeOnACChangeSetting
, n
);
384 if(kIOReturnSuccess
!= return_value
) goto exit
;
389 if(boot_complete_string
) boot_complete_string
->release();
390 if(power_button_string
) power_button_string
->release();
391 if(stall_halt_string
) stall_halt_string
->release();
392 if(auto_wake_string
) auto_wake_string
->release();
393 if(auto_power_string
) auto_power_string
->release();
394 if(wakeonring_string
) wakeonring_string
->release();
395 if(fileserver_string
) fileserver_string
->release();
396 if(wakeonlid_string
) wakeonlid_string
->release();
397 if(wakeonac_string
) wakeonac_string
->release();
402 //*********************************************************************************
405 // Power Managment is informing us that we are the root power domain.
406 // We know we are not the root however, since we have just instantiated a parent
407 // for ourselves and made it the root. We override this method so it will have
409 //*********************************************************************************
410 IOReturn
IOPMrootDomain::youAreRoot ( void )
415 // **********************************************************************************
419 // **********************************************************************************
420 void IOPMrootDomain::command_received ( void * w
, void * x
, void * y
, void * z
)
422 super::command_received(w
,x
,y
,z
);
426 // **********************************************************************************
427 // broadcast_aggressiveness
429 // **********************************************************************************
430 IOReturn
broadcast_aggressiveness ( OSObject
* root
, void * x
, void * y
, void *, void * )
432 ((IOPMrootDomain
*)root
)->broadcast_it((unsigned long)x
,(unsigned long)y
);
437 // **********************************************************************************
440 // We are behind the command gate to broadcast an aggressiveness factor. We let the
441 // superclass do it, but we need to snoop on factors that affect idle sleep.
442 // **********************************************************************************
443 void IOPMrootDomain::broadcast_it (unsigned long type
, unsigned long value
)
445 super::setAggressiveness(type
,value
);
447 // Save user's spin down timer to restore after we replace it for idle sleep
448 if( type
== kPMMinutesToSpinDown
) user_spindown
= value
;
450 // Use longestNonSleepSlider to calculate dimming adjust idle sleep timer
451 longestNonSleepSlider
= pm_vars
->current_aggressiveness_values
[kPMMinutesToDim
];
454 if ( type
== kPMMinutesToSleep
) {
455 if ( (sleepSlider
== 0) && (value
!= 0) ) {
457 // idle sleep is now enabled, maybe sleep now
461 if ( sleepSlider
== 0 ) {
462 // idle sleep is now disabled
464 // make sure we're powered
465 patriarch
->wakeSystem();
468 if ( sleepSlider
> longestNonSleepSlider
) {
469 extraSleepDelay
= sleepSlider
- longestNonSleepSlider
;
477 // **********************************************************************************
480 // **********************************************************************************
481 static void sleepTimerExpired ( thread_call_param_t us
)
483 ((IOPMrootDomain
*)us
)->handleSleepTimerExpiration();
487 static void wakeupClamshellTimerExpired ( thread_call_param_t us
)
489 ((IOPMrootDomain
*)us
)->stopIgnoringClamshellEventsDuringWakeup();
493 // **********************************************************************************
494 // handleSleepTimerExpiration
496 // The time between the sleep idle timeout and the next longest one has elapsed.
497 // It's time to sleep. Start that by removing the clamp that's holding us awake.
498 // **********************************************************************************
499 void IOPMrootDomain::handleSleepTimerExpiration ( void )
501 // accelerate disk spin down if spin down timer is non-zero (zero = never spin down)
502 if(0 != user_spindown
)
503 setQuickSpinDownTimeout();
510 void IOPMrootDomain::stopIgnoringClamshellEventsDuringWakeup(void)
514 // Allow clamshell-induced sleep now
515 ignoringClamshellDuringWakeup
= false;
517 if ((state
= getProperty(kAppleClamshellStateKey
)))
518 publishResource(kAppleClamshellStateKey
, state
);
521 //*********************************************************************************
524 // Some aggressiveness factor has changed. We broadcast it to the hierarchy while on
525 // the Power Mangement workloop thread. This enables objects in the
526 // hierarchy to successfully alter their idle timers, which are all on the
528 //*********************************************************************************
530 IOReturn
IOPMrootDomain::setAggressiveness ( unsigned long type
, unsigned long newLevel
)
532 if ( pm_vars
->PMcommandGate
) {
533 pm_vars
->PMcommandGate
->runAction(broadcast_aggressiveness
,(void *)type
,(void *)newLevel
);
536 return kIOReturnSuccess
;
540 // **********************************************************************************
543 // **********************************************************************************
544 IOReturn
IOPMrootDomain::sleepSystem ( void )
546 //kprintf("sleep demand received\n");
547 if ( !systemBooting
&& allowSleep
&& sleepIsSupported
) {
548 patriarch
->sleepSystem();
549 return kIOReturnSuccess
;
551 if ( !systemBooting
&& allowSleep
&& !sleepIsSupported
) {
552 patriarch
->dozeSystem();
553 return kIOReturnSuccess
;
555 return kIOReturnSuccess
;
559 // **********************************************************************************
562 // **********************************************************************************
563 IOReturn
IOPMrootDomain::shutdownSystem ( void )
565 //patriarch->shutDownSystem();
566 return kIOReturnUnsupported
;
570 // **********************************************************************************
573 // **********************************************************************************
574 IOReturn
IOPMrootDomain::restartSystem ( void )
576 //patriarch->restartSystem();
577 return kIOReturnUnsupported
;
581 // **********************************************************************************
584 // This overrides powerChangeDone in IOService.
586 // Finder sleep and idle sleep move us from the ON state to the SLEEP_STATE.
588 // If we just finished going to the SLEEP_STATE, and the platform is capable of true sleep,
589 // sleep the kernel. Otherwise switch up to the DOZE_STATE which will keep almost
590 // everything as off as it can get.
592 // **********************************************************************************
593 void IOPMrootDomain::powerChangeDone ( unsigned long previousState
)
595 OSNumber
* propertyPtr
;
596 unsigned short theProperty
;
597 AbsoluteTime deadline
;
599 switch ( pm_vars
->myCurrentState
) {
601 if ( canSleep
&& sleepIsSupported
)
603 // re-enable this timer for next sleep
604 idleSleepPending
= false;
605 IOLog("System Sleep\n");
606 pm_vars
->thePlatform
->sleepKernel();
608 // The CPU(s) are off at this point. When they're awakened by CPU interrupt,
609 // code will resume exeuction here.
611 // Now we're waking...
612 ioSPMTrace(IOPOWER_WAKE
, * (int *) this);
614 // stay awake for at least 30 seconds
615 clock_interval_to_deadline(30, kSecondScale
, &deadline
);
616 thread_call_enter_delayed(extraSleepTimer
, deadline
);
617 // this gets turned off when we sleep again
618 idleSleepPending
= true;
620 // Ignore closed clamshell during wakeup and for a few seconds
621 // after wakeup is complete
622 ignoringClamshellDuringWakeup
= true;
624 // sleep transition complete
625 gSleepOrShutdownPending
= 0;
627 // trip the reset of the calendar clock
628 clock_wakeup_calendar();
631 patriarch
->wakeSystem();
633 // early stage wake notification
634 tellClients(kIOMessageSystemWillPowerOn
);
636 // tell the tree we're waking
637 IOLog("System Wake\n");
640 // Allow drivers to request extra processing time before clamshell
641 // sleep if kIOREMSleepEnabledKey is present.
642 // Ignore clamshell events for at least 5 seconds
643 if(getProperty(kIOREMSleepEnabledKey
)) {
644 // clamshellWakeupIgnore callout clears ignoreClamshellDuringWakeup bit
645 clock_interval_to_deadline(5, kSecondScale
, &deadline
);
646 if(clamshellWakeupIgnore
) thread_call_enter_delayed(clamshellWakeupIgnore
, deadline
);
647 } else ignoringClamshellDuringWakeup
= false;
649 // Find out what woke us
650 propertyPtr
= OSDynamicCast(OSNumber
,getProperty("WakeEvent"));
652 theProperty
= propertyPtr
->unsigned16BitValue();
653 IOLog("Wake event %04x\n",theProperty
);
654 if ( (theProperty
& 0x0008) || //lid
655 (theProperty
& 0x0800) || // front panel button
656 (theProperty
& 0x0020) || // external keyboard
657 (theProperty
& 0x0001) ) { // internal keyboard
658 // We've identified the wakeup event as UI driven
662 // Since we can't identify the wakeup event, treat it as UI activity
666 // Wake for thirty seconds
667 changePowerStateToPriv(ON_STATE
);
668 powerOverrideOffPriv();
670 // allow us to step up a power state
671 patriarch
->sleepToDoze();
673 changePowerStateToPriv(DOZE_STATE
);
678 if ( previousState
!= DOZE_STATE
)
680 IOLog("System Doze\n");
682 // re-enable this timer for next sleep
683 idleSleepPending
= false;
684 gSleepOrShutdownPending
= 0;
688 IOLog("System Restart\n");
689 PEHaltRestart(kPERestartCPU
);
693 IOLog("System Halt\n");
694 PEHaltRestart(kPEHaltCPU
);
700 // **********************************************************************************
703 // The Display Wrangler calls here when it switches to its highest state. If the
704 // system is currently dozing, allow it to wake by making sure the parent is
706 // **********************************************************************************
707 void IOPMrootDomain::wakeFromDoze( void )
709 if ( pm_vars
->myCurrentState
== DOZE_STATE
)
711 // reset this till next attempt
713 powerOverrideOffPriv();
715 // early wake notification
716 tellClients(kIOMessageSystemWillPowerOn
);
718 // allow us to wake if children so desire
719 patriarch
->wakeSystem();
724 // **********************************************************************************
727 // Adds a new feature to the supported features dictionary
730 // **********************************************************************************
731 void IOPMrootDomain::publishFeature( const char * feature
)
733 OSDictionary
*features
= (OSDictionary
*)getProperty(kRootDomainSupportedFeatures
);
735 features
->setObject(feature
, kOSBooleanTrue
);
738 void IOPMrootDomain::unIdleDevice( IOService
*theDevice
, unsigned long theState
)
740 if(pmPowerStateQueue
)
741 pmPowerStateQueue
->unIdleOccurred(theDevice
, theState
);
744 void IOPMrootDomain::announcePowerSourceChange( void )
746 IORegistryEntry
*_batteryRegEntry
= getProperty("BatteryEntry");
748 // (if possible) re-publish power source state under IOPMrootDomain
749 // (only done if the battery controller publishes an IOResource defining battery location)
753 batt_info
= _batteryRegEntry
->getProperty(kIOBatteryInfoKey
);
755 setProperty(kIOBatteryInfoKey
, batt_info
);
758 messageClients(kIOPMMessageBatteryStatusHasChanged
);
761 IOReturn
IOPMrootDomain::registerPMSettingController
762 (IOPMSettingControllerCallback func
, void *info
)
764 if(_settingController
) return kIOReturnExclusiveAccess
;
766 _settingController
= (PMSettingCtrl
*)IOMalloc(sizeof(PMSettingCtrl
));
767 if(!_settingController
) return kIOReturnNoMemory
;
769 _settingController
->func
= func
;
770 _settingController
->refcon
= info
;
771 return kIOReturnSuccess
;
774 IOReturn
IOPMrootDomain::registerPlatformPowerProfiles
775 (OSArray
*system_profiles
)
777 if(!system_profiles
) return kIOReturnBadArgument
;
778 if(getProperty("SystemPowerProfiles")) return kIOReturnExclusiveAccess
;
779 setProperty("SystemPowerProfiles", system_profiles
);
782 //*********************************************************************************
783 // receivePowerNotification
785 // The power controller is notifying us of a hardware-related power management
786 // event that we must handle. This is a result of an 'environment' interrupt from
787 // the power mgt micro.
788 //*********************************************************************************
790 IOReturn
IOPMrootDomain::receivePowerNotification (UInt32 msg
)
792 if (msg
& kIOPMOverTemp
)
794 IOLog("Power Management received emergency overtemp signal. Going to sleep.");
795 (void) sleepSystem ();
797 if (msg
& kIOPMSetDesktopMode
)
799 desktopMode
= (0 != (msg
& kIOPMSetValue
));
800 msg
&= ~(kIOPMSetDesktopMode
| kIOPMSetValue
);
802 if (msg
& kIOPMSetACAdaptorConnected
)
804 acAdaptorConnect
= (0 != (msg
& kIOPMSetValue
));
805 msg
&= ~(kIOPMSetACAdaptorConnected
| kIOPMSetValue
);
807 if (msg
& kIOPMEnableClamshell
)
809 ignoringClamshell
= false;
811 if (msg
& kIOPMDisableClamshell
)
813 ignoringClamshell
= true;
816 if (msg
& kIOPMProcessorSpeedChange
)
818 IOService
*pmu
= waitForService(serviceMatching("ApplePMU"));
819 pmu
->callPlatformFunction("prepareForSleep", false, 0, 0, 0, 0);
820 pm_vars
->thePlatform
->sleepKernel();
821 pmu
->callPlatformFunction("recoverFromSleep", false, 0, 0, 0, 0);
824 if (msg
& kIOPMSleepNow
)
826 (void) sleepSystem ();
829 if (msg
& kIOPMPowerEmergency
)
831 (void) sleepSystem ();
834 if (msg
& kIOPMClamshellClosed
)
836 if ( !ignoringClamshell
&& !ignoringClamshellDuringWakeup
837 && (!desktopMode
|| !acAdaptorConnect
) )
840 (void) sleepSystem ();
844 if (msg
& kIOPMPowerButton
)
846 // toggle state of sleep/wake
848 if ( pm_vars
->myCurrentState
== DOZE_STATE
)
850 // yes, tell the tree we're waking
852 // wake the Display Wrangler
856 // Check that power button sleep is enabled
857 if(kOSBooleanTrue
!= getProperty(OSString::withCString("DisablePowerButtonSleep")))
862 // if the case has been closed, we allow
863 // the machine to be put to sleep or to idle sleep
865 if ( (msg
& kIOPMAllowSleep
) && !allowSleep
)
871 // if the case has been opened, we disallow sleep/doze
873 if (msg
& kIOPMPreventSleep
) {
876 if ( pm_vars
->myCurrentState
== DOZE_STATE
) {
877 // yes, tell the tree we're waking
880 // wake the Display Wrangler
884 // make sure we have power to clamp
885 patriarch
->wakeSystem();
893 //*********************************************************************************
896 //*********************************************************************************
898 void IOPMrootDomain::setSleepSupported( IOOptionBits flags
)
900 if ( flags
& kPCICantSleep
)
904 platformSleepSupport
= flags
;
909 //*********************************************************************************
910 // requestPowerDomainState
912 // The root domain intercepts this call to the superclass.
914 // If the clamp bit is not set in the desire, then the child doesn't need the power
915 // state it's requesting; it just wants it. The root ignores desires but not needs.
916 // If the clamp bit is not set, the root takes it that the child can tolerate no
917 // power and interprets the request accordingly. If all children can thus tolerate
918 // no power, we are on our way to idle sleep.
919 //*********************************************************************************
921 IOReturn
IOPMrootDomain::requestPowerDomainState ( IOPMPowerFlags desiredState
, IOPowerConnection
* whichChild
, unsigned long specification
)
925 IOPowerConnection
*connection
;
926 unsigned long powerRequestFlag
= 0;
927 IOPMPowerFlags editedDesire
= desiredState
;
929 // if they don't really need it, they don't get it
930 if ( !(desiredState
& kIOPMPreventIdleSleep
) ) {
935 IOLockLock(pm_vars
->childLock
);
937 // recompute sleepIsSupported and see if all children are asleep
938 iter
= getChildIterator(gIOPowerPlane
);
939 sleepIsSupported
= true;
942 while ( (next
= iter
->getNextObject()) )
944 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
946 if ( connection
== whichChild
)
948 powerRequestFlag
+= editedDesire
;
949 if ( desiredState
& kIOPMPreventSystemSleep
)
951 sleepIsSupported
= false;
954 powerRequestFlag
+= connection
->getDesiredDomainState();
955 if ( connection
->getPreventSystemSleepFlag() )
957 sleepIsSupported
= false;
965 if ( (extraSleepDelay
== 0) && (powerRequestFlag
== 0) )
970 // this may put the system to sleep
973 IOLockUnlock(pm_vars
->childLock
);
975 editedDesire
|= desiredState
& kIOPMPreventSystemSleep
;
977 return super::requestPowerDomainState(editedDesire
,whichChild
,specification
);
981 //*********************************************************************************
984 //*********************************************************************************
986 IOOptionBits
IOPMrootDomain::getSleepSupported( void )
988 return( platformSleepSupport
);
992 //*********************************************************************************
995 // We override the superclass implementation so we can send a different message
996 // type to the client or application being notified.
997 //*********************************************************************************
999 bool IOPMrootDomain::tellChangeDown ( unsigned long stateNum
)
1001 switch ( stateNum
) {
1004 return super::tellClientsWithResponse(kIOMessageSystemWillSleep
);
1006 return super::tellClientsWithResponse(kIOMessageSystemWillRestart
);
1008 return super::tellClientsWithResponse(kIOMessageSystemWillPowerOff
);
1010 // this shouldn't execute
1011 return super::tellChangeDown(stateNum
);
1015 //*********************************************************************************
1018 // We override the superclass implementation so we can send a different message
1019 // type to the client or application being notified.
1021 // This must be idle sleep since we don't ask apps during any other power change.
1022 //*********************************************************************************
1024 bool IOPMrootDomain::askChangeDown ( unsigned long )
1026 return super::tellClientsWithResponse(kIOMessageCanSystemSleep
);
1030 //*********************************************************************************
1033 // Notify registered applications and kernel clients that we are not
1036 // We override the superclass implementation so we can send a different message
1037 // type to the client or application being notified.
1039 // This must be a vetoed idle sleep, since no other power change can be vetoed.
1040 //*********************************************************************************
1042 void IOPMrootDomain::tellNoChangeDown ( unsigned long )
1044 return tellClients(kIOMessageSystemWillNotSleep
);
1048 //*********************************************************************************
1051 // Notify registered applications and kernel clients that we are raising power.
1053 // We override the superclass implementation so we can send a different message
1054 // type to the client or application being notified.
1055 //*********************************************************************************
1057 void IOPMrootDomain::tellChangeUp ( unsigned long stateNum
)
1059 if ( stateNum
== ON_STATE
)
1061 return tellClients(kIOMessageSystemHasPoweredOn
);
1065 //*********************************************************************************
1068 //*********************************************************************************
1070 void IOPMrootDomain::reportUserInput ( void )
1076 iter
= getMatchingServices(serviceMatching("IODisplayWrangler"));
1079 wrangler
= (IOService
*) iter
->getNextObject();
1085 wrangler
->activityTickle(0,0);
1088 //*********************************************************************************
1089 // setQuickSpinDownTimeout
1091 //*********************************************************************************
1093 void IOPMrootDomain::setQuickSpinDownTimeout ( void )
1095 super::setAggressiveness((unsigned long)kPMMinutesToSpinDown
,(unsigned long)1);
1098 //*********************************************************************************
1099 // restoreUserSpinDownTimeout
1101 //*********************************************************************************
1103 void IOPMrootDomain::restoreUserSpinDownTimeout ( void )
1105 super::setAggressiveness((unsigned long)kPMMinutesToSpinDown
,(unsigned long)user_spindown
);
1108 //*********************************************************************************
1109 // changePowerStateTo & changePowerStateToPriv
1111 // Override of these methods for logging purposes.
1112 //*********************************************************************************
1114 IOReturn
IOPMrootDomain::changePowerStateTo ( unsigned long ordinal
)
1116 ioSPMTrace(IOPOWER_ROOT
, * (int *) this, (int) true, (int) ordinal
);
1118 return super::changePowerStateTo(ordinal
);
1121 IOReturn
IOPMrootDomain::changePowerStateToPriv ( unsigned long ordinal
)
1123 ioSPMTrace(IOPOWER_ROOT
, * (int *) this, (int) false, (int) ordinal
);
1125 return super::changePowerStateToPriv(ordinal
);
1129 //*********************************************************************************
1130 // sysPowerDownHandler
1132 // Receives a notification when the RootDomain changes state.
1134 // Allows us to take action on system sleep, power down, and restart after
1135 // applications have received their power change notifications and replied,
1136 // but before drivers have powered down. We perform a vfs sync on power down.
1137 //*********************************************************************************
1139 IOReturn
IOPMrootDomain::sysPowerDownHandler( void * target
, void * refCon
,
1140 UInt32 messageType
, IOService
* service
,
1141 void * messageArgument
, vm_size_t argSize
)
1144 IOPowerStateChangeNotification
*params
= (IOPowerStateChangeNotification
*) messageArgument
;
1145 IOPMrootDomain
*rootDomain
= OSDynamicCast(IOPMrootDomain
, service
);
1148 return kIOReturnUnsupported
;
1150 switch (messageType
) {
1151 case kIOMessageSystemWillSleep
:
1152 rootDomain
->powerOverrideOnPriv(); // start ignoring children's requests
1153 // (fall through to other cases)
1155 // Interested applications have been notified of an impending power
1156 // change and have acked (when applicable).
1157 // This is our chance to save whatever state we can before powering
1159 // We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c,
1162 // We will ack within 20 seconds
1163 params
->returnValue
= 20 * 1000 * 1000;
1165 if ( ! OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending
) )
1167 // Purposely delay the ack and hope that shutdown occurs quickly.
1168 // Another option is not to schedule the thread and wait for
1170 AbsoluteTime deadline
;
1171 clock_interval_to_deadline( 30, kSecondScale
, &deadline
);
1172 thread_call_enter1_delayed( rootDomain
->diskSyncCalloutEntry
,
1173 (thread_call_param_t
)params
->powerRef
,
1177 thread_call_enter1(rootDomain
->diskSyncCalloutEntry
, (thread_call_param_t
)params
->powerRef
);
1178 ret
= kIOReturnSuccess
;
1181 case kIOMessageSystemWillPowerOff
:
1182 case kIOMessageSystemWillRestart
:
1183 ret
= kIOReturnUnsupported
;
1187 ret
= kIOReturnUnsupported
;
1193 //*********************************************************************************
1194 // displayWranglerNotification
1196 // Receives a notification when the IODisplayWrangler changes state.
1198 // Allows us to take action on display dim/undim.
1200 // When the display goes dim we:
1201 // - Start the idle sleep timer
1202 // - set the quick spin down timeout
1204 // On wake from display dim:
1205 // - Cancel the idle sleep timer
1206 // - restore the user's chosen spindown timer from the "quick" spin down value
1207 //*********************************************************************************
1209 IOReturn
IOPMrootDomain::displayWranglerNotification( void * target
, void * refCon
,
1210 UInt32 messageType
, IOService
* service
,
1211 void * messageArgument
, vm_size_t argSize
)
1213 IOPMrootDomain
* rootDomain
= OSDynamicCast(IOPMrootDomain
, (IOService
*)target
);
1214 AbsoluteTime deadline
;
1215 static bool deviceAlreadyPoweredOff
= false;
1218 return kIOReturnUnsupported
;
1220 switch (messageType
) {
1221 case kIOMessageDeviceWillPowerOff
:
1222 // The IODisplayWrangler has powered off either because of idle display sleep
1223 // or force system sleep.
1225 // The display wrangler will send the DeviceWillPowerOff message 4 times until
1226 // it gets into its lowest state. We only want to act on the first of those 4.
1227 if( deviceAlreadyPoweredOff
) return kIOReturnUnsupported
;
1229 deviceAlreadyPoweredOff
= true;
1231 if( rootDomain
->extraSleepDelay
)
1233 // start the extra sleep timer
1234 clock_interval_to_deadline(rootDomain
->extraSleepDelay
*60, kSecondScale
, &deadline
);
1235 thread_call_enter_delayed(rootDomain
->extraSleepTimer
, deadline
);
1236 rootDomain
->idleSleepPending
= true;
1238 // accelerate disk spin down if spin down timer is non-zero (zero = never spin down)
1239 // and if system sleep is non-Never
1240 if( (0 != rootDomain
->user_spindown
) && (0 != rootDomain
->sleepSlider
) )
1241 rootDomain
->setQuickSpinDownTimeout();
1246 case kIOMessageDeviceHasPoweredOn
:
1248 // The display has powered on either because of UI activity or wake from sleep/doze
1249 deviceAlreadyPoweredOff
= false;
1250 rootDomain
->adjustPowerState();
1253 // cancel any pending idle sleep
1254 if(rootDomain
->idleSleepPending
)
1256 thread_call_cancel(rootDomain
->extraSleepTimer
);
1257 rootDomain
->idleSleepPending
= false;
1260 // Change the spindown value back to the user's selection from our accelerated setting
1261 if(0 != rootDomain
->user_spindown
)
1262 rootDomain
->restoreUserSpinDownTimeout();
1264 // Put on the policy maker's on clamp.
1271 return kIOReturnUnsupported
;
1274 //*********************************************************************************
1275 // displayWranglerPublished
1277 // Receives a notification when the IODisplayWrangler is published.
1278 // When it's published we install a power state change handler.
1280 //*********************************************************************************
1282 bool IOPMrootDomain::displayWranglerPublished( void * target
, void * refCon
,
1283 IOService
* newService
)
1285 IOPMrootDomain
* rootDomain
= OSDynamicCast(IOPMrootDomain
, (IOService
*)target
);
1290 rootDomain
->wrangler
= newService
;
1292 // we found the display wrangler, now install a handler
1293 if( !rootDomain
->wrangler
->registerInterest( gIOGeneralInterest
, &displayWranglerNotification
, target
, 0) ) {
1294 IOLog("IOPMrootDomain::displayWranglerPublished registerInterest failed\n");
1301 //*********************************************************************************
1302 // batteryLocationPublished
1304 // Notification on AppleSMU publishing location of battery data
1306 //*********************************************************************************
1308 bool IOPMrootDomain::batteryLocationPublished( void * target
, void * root_domain
,
1309 IOService
* resourceService
)
1311 IORegistryEntry
*battery_location
;
1312 char battery_reg_path
[255];
1315 battery_location
= resourceService
->getProperty("battery");
1316 if (!battery_location
|| !OSDynamicCast(IORegistryEntry
, battery_location
))
1319 ((IOPMrootDomain
*)root_domain
)->setProperty("BatteryEntry", battery_location
);
1321 ((IOPMrootDomain
*)root_domain
)->announcePowerSourceChange();
1327 //*********************************************************************************
1330 // Some condition that affects our wake/sleep/doze decision has changed.
1332 // If the sleep slider is in the off position, we cannot sleep or doze.
1333 // If the enclosure is open, we cannot sleep or doze.
1334 // If the system is still booting, we cannot sleep or doze.
1336 // In those circumstances, we prevent sleep and doze by holding power on with
1337 // changePowerStateToPriv(ON).
1339 // If the above conditions do not exist, and also the sleep timer has expired, we
1340 // allow sleep or doze to occur with either changePowerStateToPriv(SLEEP) or
1341 // changePowerStateToPriv(DOZE) depending on whether or not we already know the
1342 // platform cannot sleep.
1344 // In this case, sleep or doze will either occur immediately or at the next time
1345 // that no children are holding the system out of idle sleep via the
1346 // kIOPMPreventIdleSleep flag in their power state arrays.
1347 //*********************************************************************************
1349 void IOPMrootDomain::adjustPowerState( void )
1351 if ( (sleepSlider
== 0) ||
1354 changePowerStateToPriv(ON_STATE
);
1359 if ( sleepIsSupported
)
1361 changePowerStateToPriv(SLEEP_STATE
);
1363 changePowerStateToPriv(DOZE_STATE
);
1370 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1373 #define super IOService
1375 OSDefineMetaClassAndStructors(IORootParent
, IOService
)
1377 // This array exactly parallels the state array for the root domain.
1378 // Power state changes initiated by a device can be vetoed by a client of the device, and
1379 // power state changes initiated by the parent of a device cannot be vetoed by a client of the device,
1380 // so when the root domain wants a power state change that cannot be vetoed (e.g. demand sleep), it asks
1381 // its parent to make the change. That is the reason for this complexity.
1383 static IOPMPowerState patriarchPowerStates
[number_of_power_states
] = {
1384 {1,0,0,0,0,0,0,0,0,0,0,0}, // off
1385 {1,0,RESTART_POWER
,0,0,0,0,0,0,0,0,0}, // reset
1386 {1,0,SLEEP_POWER
,0,0,0,0,0,0,0,0,0}, // sleep
1387 {1,0,DOZE_POWER
,0,0,0,0,0,0,0,0,0}, // doze
1388 {1,0,ON_POWER
,0,0,0,0,0,0,0,0,0} // running
1391 bool IORootParent::start ( IOService
* nub
)
1393 mostRecentChange
= ON_STATE
;
1396 registerPowerDriver(this,patriarchPowerStates
,number_of_power_states
);
1397 powerOverrideOnPriv();
1402 void IORootParent::shutDownSystem ( void )
1404 mostRecentChange
= OFF_STATE
;
1405 changePowerStateToPriv(OFF_STATE
);
1409 void IORootParent::restartSystem ( void )
1411 mostRecentChange
= RESTART_STATE
;
1412 changePowerStateToPriv(RESTART_STATE
);
1416 void IORootParent::sleepSystem ( void )
1418 mostRecentChange
= SLEEP_STATE
;
1419 changePowerStateToPriv(SLEEP_STATE
);
1423 void IORootParent::dozeSystem ( void )
1425 mostRecentChange
= DOZE_STATE
;
1426 changePowerStateToPriv(DOZE_STATE
);
1429 // Called in demand sleep when sleep discovered to be impossible after actually attaining that state.
1430 // This brings the parent to doze, which allows the root to step up from sleep to doze.
1432 // In idle sleep, do nothing because the parent is still on and the root can freely change state.
1434 void IORootParent::sleepToDoze ( void )
1436 if ( mostRecentChange
== SLEEP_STATE
) {
1437 changePowerStateToPriv(DOZE_STATE
);
1442 void IORootParent::wakeSystem ( void )
1444 mostRecentChange
= ON_STATE
;
1445 changePowerStateToPriv(ON_STATE
);