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 <IOKit/IOReturn.h>
33 #include "RootDomainUserClient.h"
34 #include "IOKit/pwr_mgt/IOPowerConnection.h"
35 #include "IOPMPowerStateQueue.h"
36 #include <IOKit/IOCatalogue.h>
37 #include <IOKit/IOHibernatePrivate.h>
44 IOReturn
OSMetaClassSystemSleepOrWake( UInt32
);
47 extern const IORegistryPlane
* gIOPowerPlane
;
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
);
53 // "IOPMSetSleepSupported" callPlatformFunction name
54 static const OSSymbol
*sleepSupportedPEFunction
= NULL
;
56 #define kIOSleepSupportedKey "IOSleepSupported"
58 #define kRD_AllPowerSources (kIOPMSupportedOnAC \
59 | kIOPMSupportedOnBatt \
60 | kIOPMSupportedOnUPS)
62 #define number_of_power_states 5
64 #define RESTART_STATE 1
69 #define ON_POWER kIOPMPowerOn
70 #define RESTART_POWER kIOPMRestart
71 #define SLEEP_POWER kIOPMAuxPowerOn
72 #define DOZE_POWER kIOPMDoze
74 #define kLocalEvalClamshellCommand (1 << 15)
76 static IOPMPowerState ourPowerStates
[number_of_power_states
] = {
78 {1,0, 0, 0,0,0,0,0,0,0,0,0},
80 {1,kIOPMRestartCapability
, kIOPMRestart
, RESTART_POWER
,0,0,0,0,0,0,0,0},
82 {1,kIOPMSleepCapability
, kIOPMSleep
, SLEEP_POWER
,0,0,0,0,0,0,0,0},
84 {1,kIOPMDoze
, kIOPMDoze
, DOZE_POWER
,0,0,0,0,0,0,0,0},
86 {1,kIOPMPowerOn
, kIOPMPowerOn
, ON_POWER
,0,0,0,0,0,0,0,0},
89 static IOPMrootDomain
* gRootDomain
;
90 static UInt32 gSleepOrShutdownPending
= 0;
93 class PMSettingObject
: public OSObject
95 OSDeclareDefaultStructors(PMSettingObject
)
97 IOPMrootDomain
*parent
;
98 IOPMSettingControllerCallback func
;
101 uint32_t *publishedFeatureID
;
104 static PMSettingObject
*pmSettingObject(
105 IOPMrootDomain
*parent_arg
,
106 IOPMSettingControllerCallback handler_arg
,
107 OSObject
*target_arg
,
108 uintptr_t refcon_arg
,
109 uint32_t supportedPowerSources
,
110 const OSSymbol
*settings
[]);
112 void setPMSetting(const OSSymbol
*type
, OSObject
*obj
);
114 void taggedRelease(const void *tag
, const int when
) const;
120 #define super IOService
121 OSDefineMetaClassAndStructors(IOPMrootDomain
,IOService
)
125 IONotifier
* registerSleepWakeInterest(IOServiceInterestHandler handler
, void * self
, void * ref
)
127 return gRootDomain
->registerInterest( gIOGeneralInterest
, handler
, self
, ref
);
130 IONotifier
* registerPrioritySleepWakeInterest(IOServiceInterestHandler handler
, void * self
, void * ref
)
132 return gRootDomain
->registerInterest( gIOPriorityPowerStateInterest
, handler
, self
, ref
);
135 IOReturn
acknowledgeSleepWakeNotification(void * PMrefcon
)
137 return gRootDomain
->allowPowerChange ( (unsigned long)PMrefcon
);
140 IOReturn
vetoSleepWakeNotification(void * PMrefcon
)
142 return gRootDomain
->cancelPowerChange ( (unsigned long)PMrefcon
);
145 IOReturn
rootDomainRestart ( void )
147 return gRootDomain
->restartSystem();
150 IOReturn
rootDomainShutdown ( void )
152 return gRootDomain
->shutdownSystem();
155 void IOSystemShutdownNotification ( void )
157 IOCatalogue::disableExternalLinker();
158 for ( int i
= 0; i
< 100; i
++ )
160 if ( OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending
) ) break;
165 int sync_internal(void);
169 A device is always in the highest power state which satisfies its driver, its policy-maker, and any power domain
170 children it has, but within the constraint of the power state provided by its parent. The driver expresses its desire by
171 calling changePowerStateTo(), the policy-maker expresses its desire by calling changePowerStateToPriv(), and the children
172 express their desires by calling requestPowerDomainState().
174 The Root Power Domain owns the policy for idle and demand sleep and doze for the system. It is a power-managed IOService just
175 like the others in the system. It implements several power states which correspond to what we see as Sleep, Doze, etc.
177 The sleep/doze policy is as follows:
178 Sleep and Doze are prevented if the case is open so that nobody will think the machine is off and plug/unplug cards.
179 Sleep and Doze are prevented if the sleep timeout slider in the preferences panel is at zero.
180 The system cannot Sleep, but can Doze if some object in the tree is in a power state marked kIOPMPreventSystemSleep.
182 These three conditions are enforced using the "driver clamp" by calling changePowerStateTo(). For example, if the case is
183 opened, changePowerStateTo(ON_STATE) is called to hold the system on regardless of the desires of the children of the root or
184 the state of the other clamp.
186 Demand Sleep/Doze is initiated by pressing the front panel power button, closing the clamshell, or selecting the menu item.
187 In this case the root's parent actually initiates the power state change so that the root has no choice and does not give
188 applications the opportunity to veto the change.
190 Idle Sleep/Doze occurs if no objects in the tree are in a state marked kIOPMPreventIdleSleep. When this is true, the root's
191 children are not holding the root on, so it sets the "policy-maker clamp" by calling changePowerStateToPriv(ON_STATE)
192 to hold itself on until the sleep timer expires. This timer is set for the difference between the sleep timeout slider and
193 the larger of the display dim timeout slider and the disk spindown timeout slider in the Preferences panel. For example, if
194 the system is set to sleep after thirty idle minutes, and the display and disk are set to sleep after five idle minutes,
195 when there is no longer an object in the tree holding the system out of Idle Sleep (via kIOPMPreventIdleSleep), the root
196 sets its timer for 25 minutes (30 - 5). When the timer expires, it releases its clamp and now nothing is holding it awake,
199 Demand sleep is prevented when the system is booting. When preferences are transmitted by the loginwindow at the end of
200 boot, a flag is cleared, and this allows subsequent Demand Sleep.
202 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
203 a clamp, but sets a flag which is noticed before actually sleeping the kernel. If the flag is set, the root steps up
204 one power state from Sleep to Doze, and any objects in the tree for which this is relevent will act appropriately (USB and
205 ADB will turn on again so that they can wake the system out of Doze (keyboard/mouse activity will cause the Display Wrangler
209 // **********************************************************************************
211 IOPMrootDomain
* IOPMrootDomain::construct( void )
213 IOPMrootDomain
*root
;
215 root
= new IOPMrootDomain
;
222 // **********************************************************************************
224 static void disk_sync_callout(thread_call_param_t p0
, thread_call_param_t p1
)
226 IOService
*rootDomain
= (IOService
*) p0
;
227 unsigned long pmRef
= (unsigned long) p1
;
229 IOHibernateSystemSleep();
231 rootDomain
->allowPowerChange(pmRef
);
234 // **********************************************************************************
237 // We don't do much here. The real initialization occurs when the platform
238 // expert informs us we are the root.
239 // **********************************************************************************
241 #define kRootDomainSettingsCount 12
243 bool IOPMrootDomain::start ( IOService
* nub
)
245 OSIterator
*psIterator
;
246 OSDictionary
*tmpDict
;
247 const OSSymbol
*settingsArr
[kRootDomainSettingsCount
] =
249 OSSymbol::withCString(kIOPMSettingSleepOnPowerButtonKey
),
250 OSSymbol::withCString(kIOPMSettingAutoWakeSecondsKey
),
251 OSSymbol::withCString(kIOPMSettingAutoPowerSecondsKey
),
252 OSSymbol::withCString(kIOPMSettingAutoWakeCalendarKey
),
253 OSSymbol::withCString(kIOPMSettingAutoPowerCalendarKey
),
254 OSSymbol::withCString(kIOPMSettingDebugWakeRelativeKey
),
255 OSSymbol::withCString(kIOPMSettingDebugPowerRelativeKey
),
256 OSSymbol::withCString(kIOPMSettingWakeOnRingKey
),
257 OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey
),
258 OSSymbol::withCString(kIOPMSettingWakeOnClamshellKey
),
259 OSSymbol::withCString(kIOPMSettingWakeOnACChangeKey
),
260 OSSymbol::withCString(kIOPMSettingTimeZoneOffsetKey
)
264 pmPowerStateQueue
= 0;
266 _reserved
= (ExpansionData
*)IOMalloc(sizeof(ExpansionData
));
267 if(!_reserved
) return false;
275 sleepSupportedPEFunction
= OSSymbol::withCString("IOPMSetSleepSupported");
277 setProperty(kIOSleepSupportedKey
,true);
280 sleepIsSupported
= true;
281 systemBooting
= true;
283 idleSleepPending
= false;
286 clamshellIsClosed
= false;
287 clamshellExists
= false;
288 ignoringClamshell
= true;
289 ignoringClamshellDuringWakeup
= false;
290 acAdaptorConnect
= true;
292 tmpDict
= OSDictionary::withCapacity(1);
293 setProperty(kRootDomainSupportedFeatures
, tmpDict
);
296 settingsCallbacks
= OSDictionary::withCapacity(1);
298 // Create a list of the valid PM settings that we'll relay to
299 // interested clients in setProperties() => setPMSetting()
300 allowedPMSettings
= OSArray::withObjects(
301 (const OSObject
**)settingsArr
,
302 kRootDomainSettingsCount
,
305 fPMSettingsDict
= OSDictionary::withCapacity(5);
307 pm_vars
->PMworkloop
= IOWorkLoop::workLoop();
308 pmPowerStateQueue
= IOPMPowerStateQueue::PMPowerStateQueue(this);
309 pm_vars
->PMworkloop
->addEventSource(pmPowerStateQueue
);
311 featuresDictLock
= IOLockAlloc();
312 settingsCtrlLock
= IORecursiveLockAlloc();
314 extraSleepTimer
= thread_call_allocate(
315 (thread_call_func_t
)sleepTimerExpired
,
316 (thread_call_param_t
) this);
317 clamshellWakeupIgnore
= thread_call_allocate(
318 (thread_call_func_t
)wakeupClamshellTimerExpired
,
319 (thread_call_param_t
) this);
320 diskSyncCalloutEntry
= thread_call_allocate(
322 (thread_call_param_t
) this);
325 patriarch
= new IORootParent
;
327 patriarch
->attach(this);
328 patriarch
->start(this);
329 patriarch
->youAreRoot();
330 patriarch
->wakeSystem();
331 patriarch
->addPowerChild(this);
333 registerPowerDriver(this,ourPowerStates
,number_of_power_states
);
335 setPMRootDomain(this);
336 // set a clamp until we sleep
337 changePowerStateToPriv(ON_STATE
);
339 // install power change handler
340 registerPrioritySleepWakeInterest( &sysPowerDownHandler
, this, 0);
342 // Register for a notification when IODisplayWrangler is published
343 _displayWranglerNotifier
= addNotification(
344 gIOPublishNotification
, serviceMatching("IODisplayWrangler"),
345 &displayWranglerPublished
, this, 0);
347 // Battery location published - ApplePMU support only
348 _batteryPublishNotifier
= addNotification(
349 gIOPublishNotification
, serviceMatching("IOPMPowerSource"),
350 &batteryPublished
, this, this);
353 const OSSymbol
*ucClassName
= OSSymbol::withCStringNoCopy("RootDomainUserClient");
354 setProperty(gIOUserClientClassKey
, (OSObject
*) ucClassName
);
355 ucClassName
->release();
357 // IOBacklightDisplay can take a long time to load at boot, or it may
358 // not load at all if you're booting with clamshell closed. We publish
359 // 'DisplayDims' here redundantly to get it published early and at all.
360 psIterator
= getMatchingServices( serviceMatching("IOPMPowerSource") );
361 if( psIterator
&& psIterator
->getNextObject() )
363 // There's at least one battery on the system, so we publish
364 // 'DisplayDims' support for the LCD.
365 publishFeature("DisplayDims");
368 psIterator
->release();
371 IOHibernateSystemInit(this);
373 registerService(); // let clients find us
378 // **********************************************************************************
381 // Receive a setProperty call
382 // The "System Boot" property means the system is completely booted.
383 // **********************************************************************************
384 IOReturn
IOPMrootDomain::setProperties ( OSObject
*props_obj
)
386 IOReturn return_value
= kIOReturnSuccess
;
387 OSDictionary
*dict
= OSDynamicCast(OSDictionary
, props_obj
);
395 const OSSymbol
*boot_complete_string
=
396 OSSymbol::withCString("System Boot Complete");
397 const OSSymbol
*stall_halt_string
=
398 OSSymbol::withCString("StallSystemAtHalt");
399 const OSSymbol
*hibernatemode_string
=
400 OSSymbol::withCString(kIOHibernateModeKey
);
401 const OSSymbol
*hibernatefile_string
=
402 OSSymbol::withCString(kIOHibernateFileKey
);
403 const OSSymbol
*hibernatefreeratio_string
=
404 OSSymbol::withCString(kIOHibernateFreeRatioKey
);
405 const OSSymbol
*hibernatefreetime_string
=
406 OSSymbol::withCString(kIOHibernateFreeTimeKey
);
410 return_value
= kIOReturnBadArgument
;
415 && boot_complete_string
416 && dict
->getObject(boot_complete_string
))
418 systemBooting
= false;
421 // If lid is closed, re-send lid closed notification
422 // now that booting is complete.
423 if( clamshellIsClosed
)
425 this->receivePowerNotification(kLocalEvalClamshellCommand
);
429 if( stall_halt_string
430 && (b
= OSDynamicCast(OSBoolean
, dict
->getObject(stall_halt_string
))) )
432 setProperty(stall_halt_string
, b
);
435 if ( hibernatemode_string
436 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(hibernatemode_string
))))
438 setProperty(hibernatemode_string
, n
);
440 if ( hibernatefreeratio_string
441 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(hibernatefreeratio_string
))))
443 setProperty(hibernatefreeratio_string
, n
);
445 if ( hibernatefreetime_string
446 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(hibernatefreetime_string
))))
448 setProperty(hibernatefreetime_string
, n
);
450 if ( hibernatefile_string
451 && (str
= OSDynamicCast(OSString
, dict
->getObject(hibernatefile_string
))))
453 setProperty(hibernatefile_string
, str
);
456 // Relay our allowed PM settings onto our registered PM clients
457 for(i
= 0; i
< allowedPMSettings
->getCount(); i
++) {
459 type
= (OSSymbol
*)allowedPMSettings
->getObject(i
);
462 obj
= dict
->getObject(type
);
465 return_value
= setPMSetting(type
, obj
);
467 if(kIOReturnSuccess
!= return_value
) goto exit
;
471 if(boot_complete_string
) boot_complete_string
->release();
472 if(stall_halt_string
) stall_halt_string
->release();
477 //*********************************************************************************
480 // Power Managment is informing us that we are the root power domain.
481 // We know we are not the root however, since we have just instantiated a parent
482 // for ourselves and made it the root. We override this method so it will have
484 //*********************************************************************************
485 IOReturn
IOPMrootDomain::youAreRoot ( void )
490 // **********************************************************************************
494 // **********************************************************************************
495 void IOPMrootDomain::command_received ( void * w
, void * x
, void * y
, void * z
)
497 super::command_received(w
,x
,y
,z
);
501 // **********************************************************************************
502 // broadcast_aggressiveness
504 // **********************************************************************************
505 IOReturn
broadcast_aggressiveness ( OSObject
* root
, void * x
, void * y
, void *, void * )
507 ((IOPMrootDomain
*)root
)->broadcast_it((unsigned long)x
,(unsigned long)y
);
512 // **********************************************************************************
515 // We are behind the command gate to broadcast an aggressiveness factor. We let the
516 // superclass do it, but we need to snoop on factors that affect idle sleep.
517 // **********************************************************************************
518 void IOPMrootDomain::broadcast_it (unsigned long type
, unsigned long value
)
520 super::setAggressiveness(type
,value
);
522 // Save user's spin down timer to restore after we replace it for idle sleep
523 if( type
== kPMMinutesToSpinDown
) user_spindown
= value
;
525 // Use longestNonSleepSlider to calculate dimming adjust idle sleep timer
526 longestNonSleepSlider
= pm_vars
->current_aggressiveness_values
[kPMMinutesToDim
];
529 if ( type
== kPMMinutesToSleep
) {
530 if ( (sleepSlider
== 0) && (value
!= 0) ) {
532 // idle sleep is now enabled, maybe sleep now
536 if ( sleepSlider
== 0 ) {
537 // idle sleep is now disabled
539 // make sure we're powered
540 patriarch
->wakeSystem();
543 if ( sleepSlider
> longestNonSleepSlider
) {
544 extraSleepDelay
= sleepSlider
- longestNonSleepSlider
;
552 // **********************************************************************************
555 // **********************************************************************************
556 static void sleepTimerExpired ( thread_call_param_t us
)
558 ((IOPMrootDomain
*)us
)->handleSleepTimerExpiration();
562 static void wakeupClamshellTimerExpired ( thread_call_param_t us
)
564 ((IOPMrootDomain
*)us
)->stopIgnoringClamshellEventsDuringWakeup();
568 // **********************************************************************************
569 // handleSleepTimerExpiration
571 // The time between the sleep idle timeout and the next longest one has elapsed.
572 // It's time to sleep. Start that by removing the clamp that's holding us awake.
573 // **********************************************************************************
574 void IOPMrootDomain::handleSleepTimerExpiration ( void )
576 // accelerate disk spin down if spin down timer is non-zero (zero = never spin down)
577 if(0 != user_spindown
)
578 setQuickSpinDownTimeout();
585 void IOPMrootDomain::stopIgnoringClamshellEventsDuringWakeup(void)
587 // Allow clamshell-induced sleep now
588 ignoringClamshellDuringWakeup
= false;
590 // Re-send clamshell event, in case it causes a sleep
591 if(clamshellIsClosed
)
592 this->receivePowerNotification( kLocalEvalClamshellCommand
);
595 //*********************************************************************************
598 // Some aggressiveness factor has changed. We broadcast it to the hierarchy while on
599 // the Power Mangement workloop thread. This enables objects in the
600 // hierarchy to successfully alter their idle timers, which are all on the
602 //*********************************************************************************
604 static int pmsallsetup
= 0;
606 IOReturn
IOPMrootDomain::setAggressiveness ( unsigned long type
, unsigned long newLevel
)
609 if(pmsExperimental
& 3) kprintf("setAggressiveness: type = %08X, newlevel = %08X\n", type
, newLevel
);
610 if(pmsExperimental
& 1) { /* Is experimental mode enabled? */
611 if(pmsInstalled
&& (type
== kPMSetProcessorSpeed
)) { /* We want to look at all processor speed changes if stepper is installed */
612 if(pmsallsetup
) return kIOReturnSuccess
; /* If already running, just eat this */
613 kprintf("setAggressiveness: starting stepper...\n");
614 pmsallsetup
= 1; /* Remember we did this */
616 pmsStart(); /* Get it all started up... */
617 return kIOReturnSuccess
; /* Leave now... */
622 if ( pm_vars
->PMcommandGate
) {
623 pm_vars
->PMcommandGate
->runAction(broadcast_aggressiveness
,(void *)type
,(void *)newLevel
);
626 return kIOReturnSuccess
;
630 // **********************************************************************************
633 // **********************************************************************************
634 IOReturn
IOPMrootDomain::sleepSystem ( void )
636 if ( !systemBooting
&& allowSleep
&& sleepIsSupported
) {
637 patriarch
->sleepSystem();
639 return kIOReturnSuccess
;
641 if ( !systemBooting
&& allowSleep
&& !sleepIsSupported
) {
642 patriarch
->dozeSystem();
643 return kIOReturnSuccess
;
645 return kIOReturnSuccess
;
649 // **********************************************************************************
652 // **********************************************************************************
653 IOReturn
IOPMrootDomain::shutdownSystem ( void )
655 //patriarch->shutDownSystem();
656 return kIOReturnUnsupported
;
660 // **********************************************************************************
663 // **********************************************************************************
664 IOReturn
IOPMrootDomain::restartSystem ( void )
666 //patriarch->restartSystem();
667 return kIOReturnUnsupported
;
671 // **********************************************************************************
674 // This overrides powerChangeDone in IOService.
676 // Finder sleep and idle sleep move us from the ON state to the SLEEP_STATE.
678 // If we just finished going to the SLEEP_STATE, and the platform is capable of true sleep,
679 // sleep the kernel. Otherwise switch up to the DOZE_STATE which will keep almost
680 // everything as off as it can get.
682 // **********************************************************************************
683 void IOPMrootDomain::powerChangeDone ( unsigned long previousState
)
685 OSNumber
* propertyPtr
;
686 unsigned short theProperty
;
687 AbsoluteTime deadline
;
689 switch ( pm_vars
->myCurrentState
) {
691 if ( canSleep
&& sleepIsSupported
)
693 // re-enable this timer for next sleep
694 idleSleepPending
= false;
696 IOLog("System %sSleep\n", gIOHibernateState
? "Safe" : "");
698 IOHibernateSystemHasSlept();
700 pm_vars
->thePlatform
->sleepKernel();
702 // The CPU(s) are off at this point. When they're awakened by CPU interrupt,
703 // code will resume execution here.
705 // Now we're waking...
706 IOHibernateSystemWake();
708 // stay awake for at least 30 seconds
709 clock_interval_to_deadline(30, kSecondScale
, &deadline
);
710 thread_call_enter_delayed(extraSleepTimer
, deadline
);
711 // this gets turned off when we sleep again
712 idleSleepPending
= true;
714 // Ignore closed clamshell during wakeup and for a few seconds
715 // after wakeup is complete
716 ignoringClamshellDuringWakeup
= true;
718 // sleep transition complete
719 gSleepOrShutdownPending
= 0;
721 // trip the reset of the calendar clock
722 clock_wakeup_calendar();
725 patriarch
->wakeSystem();
727 // early stage wake notification
728 tellClients(kIOMessageSystemWillPowerOn
);
730 // tell the tree we're waking
731 IOLog("System %sWake\n", gIOHibernateState
? "SafeSleep " : "");
734 // Allow drivers to request extra processing time before clamshell
735 // sleep if kIOREMSleepEnabledKey is present.
736 // Ignore clamshell events for at least 5 seconds
737 if(getProperty(kIOREMSleepEnabledKey
)) {
738 // clamshellWakeupIgnore callout clears ignoreClamshellDuringWakeup bit
739 clock_interval_to_deadline(5, kSecondScale
, &deadline
);
740 if(clamshellWakeupIgnore
) {
741 thread_call_enter_delayed(clamshellWakeupIgnore
, deadline
);
743 } else ignoringClamshellDuringWakeup
= false;
745 // Find out what woke us
746 propertyPtr
= OSDynamicCast(OSNumber
,getProperty("WakeEvent"));
748 theProperty
= propertyPtr
->unsigned16BitValue();
749 IOLog("Wake event %04x\n",theProperty
);
750 if ( (theProperty
& 0x0008) || //lid
751 (theProperty
& 0x0800) || // front panel button
752 (theProperty
& 0x0020) || // external keyboard
753 (theProperty
& 0x0001) ) { // internal keyboard
754 // We've identified the wakeup event as UI driven
758 // Since we can't identify the wakeup event, treat it as UI activity
762 // Wake for thirty seconds
763 changePowerStateToPriv(ON_STATE
);
764 powerOverrideOffPriv();
766 // allow us to step up a power state
767 patriarch
->sleepToDoze();
769 changePowerStateToPriv(DOZE_STATE
);
774 if ( previousState
!= DOZE_STATE
)
776 IOLog("System Doze\n");
778 // re-enable this timer for next sleep
779 idleSleepPending
= false;
780 gSleepOrShutdownPending
= 0;
784 IOLog("System Restart\n");
785 PEHaltRestart(kPERestartCPU
);
789 IOLog("System Halt\n");
790 PEHaltRestart(kPEHaltCPU
);
796 // **********************************************************************************
799 // The Display Wrangler calls here when it switches to its highest state. If the
800 // system is currently dozing, allow it to wake by making sure the parent is
802 // **********************************************************************************
803 void IOPMrootDomain::wakeFromDoze( void )
805 if ( pm_vars
->myCurrentState
== DOZE_STATE
)
807 // Reset sleep support till next sleep attempt.
808 // A machine's support of sleep vs. doze can change over the course of
809 // a running system, so we recalculate it before every sleep.
810 setSleepSupported(0);
812 powerOverrideOffPriv();
814 // early wake notification
815 tellClients(kIOMessageSystemWillPowerOn
);
817 // allow us to wake if children so desire
818 patriarch
->wakeSystem();
823 // *****************************************************************************
826 // Adds a new feature to the supported features dictionary
829 // *****************************************************************************
830 void IOPMrootDomain::publishFeature( const char * feature
)
832 publishFeature(feature
, kIOPMSupportedOnAC
833 | kIOPMSupportedOnBatt
834 | kIOPMSupportedOnUPS
,
840 // *****************************************************************************
841 // publishFeature (with supported power source specified)
843 // Adds a new feature to the supported features dictionary
846 // *****************************************************************************
847 void IOPMrootDomain::publishFeature(
849 uint32_t supportedWhere
,
850 uint32_t *uniqueFeatureID
)
852 static uint16_t next_feature_id
= 500;
854 OSNumber
*new_feature_data
= NULL
;
855 OSNumber
*existing_feature
= NULL
;
856 OSArray
*existing_feature_arr
= NULL
;
857 OSObject
*osObj
= NULL
;
858 uint32_t feature_value
= 0;
860 supportedWhere
&= kRD_AllPowerSources
; // mask off any craziness!
862 if(!supportedWhere
) {
863 // Feature isn't supported anywhere!
867 if(next_feature_id
> 5000) {
868 // Far, far too many features!
872 if(featuresDictLock
) IOLockLock(featuresDictLock
);
874 OSDictionary
*features
=
875 (OSDictionary
*) getProperty(kRootDomainSupportedFeatures
);
877 // Create new features dict if necessary
878 if ( features
&& OSDynamicCast(OSDictionary
, features
)) {
879 features
= OSDictionary::withDictionary(features
);
881 features
= OSDictionary::withCapacity(1);
884 // Create OSNumber to track new feature
886 next_feature_id
+= 1;
887 if( uniqueFeatureID
) {
888 // We don't really mind if the calling kext didn't give us a place
889 // to stash their unique id. Many kexts don't plan to unload, and thus
890 // have no need to remove themselves later.
891 *uniqueFeatureID
= next_feature_id
;
894 feature_value
= supportedWhere
+ (next_feature_id
<< 16);
895 new_feature_data
= OSNumber::withNumber(
896 (unsigned long long)feature_value
, 32);
898 // Does features object already exist?
899 if( (osObj
= features
->getObject(feature
)) )
901 if(( existing_feature
= OSDynamicCast(OSNumber
, osObj
) ))
903 // We need to create an OSArray to hold the now 2 elements.
904 existing_feature_arr
= OSArray::withObjects(
905 (const OSObject
**)&existing_feature
, 1, 2);
906 existing_feature_arr
->setObject(new_feature_data
);
907 features
->setObject(feature
, existing_feature_arr
);
908 } else if(( existing_feature_arr
= OSDynamicCast(OSArray
, osObj
) ))
910 // Add object to existing array
911 existing_feature_arr
->setObject(new_feature_data
);
914 // The easy case: no previously existing features listed. We simply
915 // set the OSNumber at key 'feature' and we're on our way.
916 features
->setObject(feature
, new_feature_data
);
919 new_feature_data
->release();
921 setProperty(kRootDomainSupportedFeatures
, features
);
925 // Notify EnergySaver and all those in user space so they might
926 // re-populate their feature specific UI
927 messageClients(kIOPMMessageFeatureChange
, this);
929 if(featuresDictLock
) IOLockUnlock(featuresDictLock
);
932 // *****************************************************************************
933 // removePublishedFeature
935 // Removes previously published feature
938 // *****************************************************************************
939 IOReturn
IOPMrootDomain::removePublishedFeature( uint32_t removeFeatureID
)
941 IOReturn ret
= kIOReturnError
;
942 uint32_t feature_value
= 0;
943 uint16_t feature_id
= 0;
944 bool madeAChange
= false;
946 OSSymbol
*dictKey
= NULL
;
947 OSCollectionIterator
*dictIterator
= NULL
;
948 OSArray
*arrayMember
= NULL
;
949 OSNumber
*numberMember
= NULL
;
950 OSObject
*osObj
= NULL
;
951 OSNumber
*osNum
= NULL
;
953 if(featuresDictLock
) IOLockLock(featuresDictLock
);
955 OSDictionary
*features
=
956 (OSDictionary
*) getProperty(kRootDomainSupportedFeatures
);
958 if ( features
&& OSDynamicCast(OSDictionary
, features
) )
960 // Any modifications to the dictionary are made to the copy to prevent
961 // races & crashes with userland clients. Dictionary updated
962 // automically later.
963 features
= OSDictionary::withDictionary(features
);
966 ret
= kIOReturnNotFound
;
970 // We iterate 'features' dictionary looking for an entry tagged
971 // with 'removeFeatureID'. If found, we remove it from our tracking
972 // structures and notify the OS via a general interest message.
974 dictIterator
= OSCollectionIterator::withCollection(features
);
979 while( (dictKey
= OSDynamicCast(OSSymbol
, dictIterator
->getNextObject())) )
981 osObj
= features
->getObject(dictKey
);
983 // Each Feature is either tracked by an OSNumber
984 if( osObj
&& (numberMember
= OSDynamicCast(OSNumber
, osObj
)) )
986 feature_value
= numberMember
->unsigned32BitValue();
987 feature_id
= (uint16_t)(feature_value
>> 16);
989 if( feature_id
== (uint16_t)removeFeatureID
)
992 features
->removeObject(dictKey
);
997 // Or tracked by an OSArray of OSNumbers
998 } else if( osObj
&& (arrayMember
= OSDynamicCast(OSArray
, osObj
)) )
1000 unsigned int arrayCount
= arrayMember
->getCount();
1002 for(unsigned int i
=0; i
<arrayCount
; i
++)
1004 osNum
= OSDynamicCast(OSNumber
, arrayMember
->getObject(i
));
1009 feature_value
= osNum
->unsigned32BitValue();
1010 feature_id
= (uint16_t)(feature_value
>> 16);
1012 if( feature_id
== (uint16_t)removeFeatureID
)
1015 if( 1 == arrayCount
) {
1016 // If the array only contains one element, remove
1018 features
->removeObject(dictKey
);
1020 // Otherwise just remove the element in question.
1021 arrayMember
->removeObject(i
);
1032 dictIterator
->release();
1036 ret
= kIOReturnSuccess
;
1038 setProperty(kRootDomainSupportedFeatures
, features
);
1040 // Notify EnergySaver and all those in user space so they might
1041 // re-populate their feature specific UI
1042 messageClients(kIOPMMessageFeatureChange
, this);
1044 ret
= kIOReturnNotFound
;
1048 if(features
) features
->release();
1049 if(featuresDictLock
) IOLockUnlock(featuresDictLock
);
1054 // **********************************************************************************
1057 // Enqueues unidle event to be performed later in a serialized context.
1059 // **********************************************************************************
1060 void IOPMrootDomain::unIdleDevice( IOService
*theDevice
, unsigned long theState
)
1062 if(pmPowerStateQueue
)
1063 pmPowerStateQueue
->unIdleOccurred(theDevice
, theState
);
1066 // **********************************************************************************
1067 // announcePowerSourceChange
1069 // Notifies "interested parties" that the batteries have changed state
1071 // **********************************************************************************
1072 void IOPMrootDomain::announcePowerSourceChange( void )
1074 IORegistryEntry
*_batteryRegEntry
= (IORegistryEntry
*) getProperty("BatteryEntry");
1076 // (if possible) re-publish power source state under IOPMrootDomain;
1077 // only do so if the battery controller publishes an IOResource
1078 // defining battery location. Called from ApplePMU battery driver.
1080 if(_batteryRegEntry
)
1083 batt_info
= (OSArray
*) _batteryRegEntry
->getProperty(kIOBatteryInfoKey
);
1085 setProperty(kIOBatteryInfoKey
, batt_info
);
1091 // *****************************************************************************
1092 // setPMSetting (private)
1094 // Internal helper to relay PM settings changes from user space to individual
1095 // drivers. Should be called only by IOPMrootDomain::setProperties.
1097 // *****************************************************************************
1098 IOReturn
IOPMrootDomain::setPMSetting(
1099 const OSSymbol
*type
,
1102 OSArray
*arr
= NULL
;
1103 PMSettingObject
*p_obj
= NULL
;
1107 if(NULL
== type
) return kIOReturnBadArgument
;
1109 IORecursiveLockLock(settingsCtrlLock
);
1111 fPMSettingsDict
->setObject(type
, obj
);
1113 arr
= (OSArray
*)settingsCallbacks
->getObject(type
);
1114 if(NULL
== arr
) goto exit
;
1115 count
= arr
->getCount();
1116 for(i
=0; i
<count
; i
++) {
1117 p_obj
= (PMSettingObject
*)OSDynamicCast(PMSettingObject
, arr
->getObject(i
));
1118 if(p_obj
) p_obj
->setPMSetting(type
, obj
);
1122 IORecursiveLockUnlock(settingsCtrlLock
);
1123 return kIOReturnSuccess
;
1126 // *****************************************************************************
1127 // copyPMSetting (public)
1129 // Allows kexts to safely read setting values, without being subscribed to
1132 // *****************************************************************************
1133 OSObject
* IOPMrootDomain::copyPMSetting(
1134 OSSymbol
*whichSetting
)
1136 OSObject
*obj
= NULL
;
1138 if(!whichSetting
) return NULL
;
1140 IORecursiveLockLock(settingsCtrlLock
);
1141 obj
= fPMSettingsDict
->getObject(whichSetting
);
1145 IORecursiveLockUnlock(settingsCtrlLock
);
1150 // *****************************************************************************
1151 // registerPMSettingController (public)
1153 // direct wrapper to registerPMSettingController with uint32_t power source arg
1154 // *****************************************************************************
1155 IOReturn
IOPMrootDomain::registerPMSettingController(
1156 const OSSymbol
* settings
[],
1157 IOPMSettingControllerCallback func
,
1162 return registerPMSettingController(
1164 (kIOPMSupportedOnAC
| kIOPMSupportedOnBatt
| kIOPMSupportedOnUPS
),
1165 func
, target
, refcon
, handle
);
1168 // *****************************************************************************
1169 // registerPMSettingController (public)
1171 // Kexts may register for notifications when a particular setting is changed.
1172 // A list of settings is available in IOPM.h.
1174 // * settings - An OSArray containing OSSymbols. Caller should populate this
1175 // array with a list of settings caller wants notifications from.
1176 // * func - A C function callback of the type IOPMSettingControllerCallback
1177 // * target - caller may provide an OSObject *, which PM will pass as an
1178 // target to calls to "func"
1179 // * refcon - caller may provide an void *, which PM will pass as an
1180 // argument to calls to "func"
1181 // * handle - This is a return argument. We will populate this pointer upon
1182 // call success. Hold onto this and pass this argument to
1183 // IOPMrootDomain::deRegisterPMSettingCallback when unloading your kext
1185 // kIOReturnSuccess on success
1186 // *****************************************************************************
1187 IOReturn
IOPMrootDomain::registerPMSettingController(
1188 const OSSymbol
* settings
[],
1189 uint32_t supportedPowerSources
,
1190 IOPMSettingControllerCallback func
,
1195 PMSettingObject
*pmso
= NULL
;
1196 OSArray
*list
= NULL
;
1197 IOReturn ret
= kIOReturnSuccess
;
1200 if( NULL
== settings
||
1204 return kIOReturnBadArgument
;
1208 pmso
= PMSettingObject::pmSettingObject(
1209 (IOPMrootDomain
*)this, func
, target
,
1210 refcon
, supportedPowerSources
, settings
);
1213 ret
= kIOReturnInternalError
;
1214 goto bail_no_unlock
;
1217 IORecursiveLockLock(settingsCtrlLock
);
1218 for(i
=0; settings
[i
]; i
++)
1220 list
= (OSArray
*)settingsCallbacks
->getObject(settings
[i
]);
1222 // New array of callbacks for this setting
1223 list
= OSArray::withCapacity(1);
1224 settingsCallbacks
->setObject(settings
[i
], list
);
1228 // Add caller to the callback list
1229 list
->setObject(pmso
);
1232 ret
= kIOReturnSuccess
;
1234 // Track this instance by its OSData ptr from now on
1237 IORecursiveLockUnlock(settingsCtrlLock
);
1240 if(kIOReturnSuccess
!= ret
)
1242 // Error return case
1243 if(pmso
) pmso
->release();
1244 if(handle
) *handle
= NULL
;
1249 //******************************************************************************
1250 // sleepOnClamshellClosed
1252 // contains the logic to determine if the system should sleep when the clamshell
1254 //******************************************************************************
1256 bool IOPMrootDomain::shouldSleepOnClamshellClosed ( void )
1258 return ( !ignoringClamshell
1259 && !ignoringClamshellDuringWakeup
1260 && !(desktopMode
&& acAdaptorConnect
) );
1263 void IOPMrootDomain::sendClientClamshellNotification ( void )
1265 /* Only broadcast clamshell alert if clamshell exists. */
1266 if(!clamshellExists
)
1269 setProperty(kAppleClamshellStateKey
,
1270 clamshellIsClosed
? kOSBooleanTrue
: kOSBooleanFalse
);
1272 setProperty(kAppleClamshellCausesSleepKey
,
1273 shouldSleepOnClamshellClosed() ? kOSBooleanTrue
: kOSBooleanFalse
);
1276 /* Argument to message is a bitfiel of
1277 * ( kClamshellStateBit | kClamshellSleepBit )
1279 messageClients(kIOPMMessageClamshellStateChange
,
1280 (void *) ( (clamshellIsClosed
? kClamshellStateBit
: 0)
1281 | ( shouldSleepOnClamshellClosed() ? kClamshellSleepBit
: 0)) );
1284 //******************************************************************************
1285 // receivePowerNotification
1287 // The power controller is notifying us of a hardware-related power management
1288 // event that we must handle. This is a result of an 'environment' interrupt from
1289 // the power mgt micro.
1290 //******************************************************************************
1292 IOReturn
IOPMrootDomain::receivePowerNotification (UInt32 msg
)
1294 bool eval_clamshell
= false;
1297 * Local (IOPMrootDomain only) eval clamshell command
1299 if (msg
& kLocalEvalClamshellCommand
)
1301 eval_clamshell
= true;
1307 if (msg
& kIOPMOverTemp
)
1309 IOLog("PowerManagement emergency overtemp signal. Going to sleep!");
1310 (void) sleepSystem ();
1314 * PMU Processor Speed Change
1316 if (msg
& kIOPMProcessorSpeedChange
)
1318 IOService
*pmu
= waitForService(serviceMatching("ApplePMU"));
1319 pmu
->callPlatformFunction("prepareForSleep", false, 0, 0, 0, 0);
1320 pm_vars
->thePlatform
->sleepKernel();
1321 pmu
->callPlatformFunction("recoverFromSleep", false, 0, 0, 0, 0);
1327 if (msg
& kIOPMSleepNow
)
1329 (void) sleepSystem ();
1335 if (msg
& kIOPMPowerEmergency
)
1337 (void) sleepSystem ();
1344 if (msg
& kIOPMClamshellOpened
)
1346 // Received clamshel open message from clamshell controlling driver
1347 // Update our internal state and tell general interest clients
1348 clamshellIsClosed
= false;
1349 clamshellExists
= true;
1351 sendClientClamshellNotification();
1356 * Send the clamshell interest notification since the lid is closing.
1358 if (msg
& kIOPMClamshellClosed
)
1360 // Received clamshel open message from clamshell controlling driver
1361 // Update our internal state and tell general interest clients
1362 clamshellIsClosed
= true;
1363 clamshellExists
= true;
1365 sendClientClamshellNotification();
1367 // And set eval_clamshell = so we can attempt
1368 eval_clamshell
= true;
1372 * Set Desktop mode (sent from graphics)
1374 * -> reevaluate lid state
1376 if (msg
& kIOPMSetDesktopMode
)
1378 desktopMode
= (0 != (msg
& kIOPMSetValue
));
1379 msg
&= ~(kIOPMSetDesktopMode
| kIOPMSetValue
);
1381 sendClientClamshellNotification();
1383 // Re-evaluate the lid state
1384 if( clamshellIsClosed
)
1386 eval_clamshell
= true;
1391 * AC Adaptor connected
1393 * -> reevaluate lid state
1395 if (msg
& kIOPMSetACAdaptorConnected
)
1397 acAdaptorConnect
= (0 != (msg
& kIOPMSetValue
));
1398 msg
&= ~(kIOPMSetACAdaptorConnected
| kIOPMSetValue
);
1400 sendClientClamshellNotification();
1402 // Re-evaluate the lid state
1403 if( clamshellIsClosed
)
1405 eval_clamshell
= true;
1411 * Enable Clamshell (external display disappear)
1413 * -> reevaluate lid state
1415 if (msg
& kIOPMEnableClamshell
)
1417 // Re-evaluate the lid state
1418 // System should sleep on external display disappearance
1419 // in lid closed operation.
1420 if( clamshellIsClosed
&& (true == ignoringClamshell
) )
1422 eval_clamshell
= true;
1425 ignoringClamshell
= false;
1427 sendClientClamshellNotification();
1431 * Disable Clamshell (external display appeared)
1432 * We don't bother re-evaluating clamshell state. If the system is awake,
1433 * the lid is probably open.
1435 if (msg
& kIOPMDisableClamshell
)
1437 ignoringClamshell
= true;
1439 sendClientClamshellNotification();
1443 * Evaluate clamshell and SLEEP if appropiate
1445 if ( eval_clamshell
&& shouldSleepOnClamshellClosed() )
1456 if (msg
& kIOPMPowerButton
)
1458 // toggle state of sleep/wake
1460 if ( pm_vars
->myCurrentState
== DOZE_STATE
)
1462 // yes, tell the tree we're waking
1464 // wake the Display Wrangler
1468 OSString
*pbs
= OSString::withCString("DisablePowerButtonSleep");
1469 // Check that power button sleep is enabled
1471 if( kOSBooleanTrue
!= getProperty(pbs
))
1481 if ( (msg
& kIOPMAllowSleep
) && !allowSleep
)
1491 if (msg
& kIOPMPreventSleep
) {
1494 if ( pm_vars
->myCurrentState
== DOZE_STATE
) {
1495 // yes, tell the tree we're waking
1498 // wake the Display Wrangler
1502 // make sure we have power to clamp
1503 patriarch
->wakeSystem();
1511 //*********************************************************************************
1514 //*********************************************************************************
1516 void IOPMrootDomain::setSleepSupported( IOOptionBits flags
)
1518 if ( flags
& kPCICantSleep
)
1523 platformSleepSupport
= flags
;
1526 setProperty(kIOSleepSupportedKey
, canSleep
);
1530 //*********************************************************************************
1531 // requestPowerDomainState
1533 // The root domain intercepts this call to the superclass.
1535 // If the clamp bit is not set in the desire, then the child doesn't need the power
1536 // state it's requesting; it just wants it. The root ignores desires but not needs.
1537 // If the clamp bit is not set, the root takes it that the child can tolerate no
1538 // power and interprets the request accordingly. If all children can thus tolerate
1539 // no power, we are on our way to idle sleep.
1540 //*********************************************************************************
1542 IOReturn
IOPMrootDomain::requestPowerDomainState ( IOPMPowerFlags desiredState
, IOPowerConnection
* whichChild
, unsigned long specification
)
1546 IOPowerConnection
*connection
;
1547 unsigned long powerRequestFlag
= 0;
1548 IOPMPowerFlags editedDesire
= desiredState
;
1550 // if they don't really need it, they don't get it
1551 if ( !(desiredState
& kIOPMPreventIdleSleep
) ) {
1556 IOLockLock(pm_vars
->childLock
);
1558 // recompute sleepIsSupported and see if all children are asleep
1559 iter
= getChildIterator(gIOPowerPlane
);
1560 sleepIsSupported
= true;
1563 while ( (next
= iter
->getNextObject()) )
1565 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1567 if ( connection
== whichChild
)
1569 powerRequestFlag
+= editedDesire
;
1570 if ( desiredState
& kIOPMPreventSystemSleep
)
1572 sleepIsSupported
= false;
1575 powerRequestFlag
+= connection
->getDesiredDomainState();
1576 if ( connection
->getPreventSystemSleepFlag() )
1578 sleepIsSupported
= false;
1586 if ( (extraSleepDelay
== 0) && (powerRequestFlag
== 0) )
1591 // this may put the system to sleep
1594 IOLockUnlock(pm_vars
->childLock
);
1596 editedDesire
|= desiredState
& kIOPMPreventSystemSleep
;
1598 return super::requestPowerDomainState(editedDesire
,whichChild
,specification
);
1602 //*********************************************************************************
1603 // getSleepSupported
1605 //*********************************************************************************
1607 IOOptionBits
IOPMrootDomain::getSleepSupported( void )
1609 return( platformSleepSupport
);
1613 //*********************************************************************************
1616 // We override the superclass implementation so we can send a different message
1617 // type to the client or application being notified.
1618 //*********************************************************************************
1620 bool IOPMrootDomain::tellChangeDown ( unsigned long stateNum
)
1622 switch ( stateNum
) {
1626 // Direct callout into OSMetaClass so it can disable kmod unloads
1627 // during sleep/wake to prevent deadlocks.
1628 OSMetaClassSystemSleepOrWake( kIOMessageSystemWillSleep
);
1630 return super::tellClientsWithResponse(kIOMessageSystemWillSleep
);
1632 // Unsupported shutdown ordering hack on RESTART only
1633 // For Bluetooth and USB (4368327)
1634 super::tellClients(iokit_common_msg(0x759));
1636 return super::tellClientsWithResponse(kIOMessageSystemWillRestart
);
1638 // Unsupported shutdown ordering hack on SHUTDOWN only
1639 // For Bluetooth and USB (4554440)
1640 super::tellClients(iokit_common_msg(0x749));
1642 return super::tellClientsWithResponse(kIOMessageSystemWillPowerOff
);
1644 // this shouldn't execute
1645 return super::tellChangeDown(stateNum
);
1649 //*********************************************************************************
1652 // We override the superclass implementation so we can send a different message
1653 // type to the client or application being notified.
1655 // This must be idle sleep since we don't ask apps during any other power change.
1656 //*********************************************************************************
1658 bool IOPMrootDomain::askChangeDown ( unsigned long )
1660 return super::tellClientsWithResponse(kIOMessageCanSystemSleep
);
1664 //*********************************************************************************
1667 // Notify registered applications and kernel clients that we are not
1670 // We override the superclass implementation so we can send a different message
1671 // type to the client or application being notified.
1673 // This must be a vetoed idle sleep, since no other power change can be vetoed.
1674 //*********************************************************************************
1676 void IOPMrootDomain::tellNoChangeDown ( unsigned long )
1678 return tellClients(kIOMessageSystemWillNotSleep
);
1682 //*********************************************************************************
1685 // Notify registered applications and kernel clients that we are raising power.
1687 // We override the superclass implementation so we can send a different message
1688 // type to the client or application being notified.
1689 //*********************************************************************************
1691 void IOPMrootDomain::tellChangeUp ( unsigned long stateNum
)
1693 if ( stateNum
== ON_STATE
)
1695 // Direct callout into OSMetaClass so it can disable kmod unloads
1696 // during sleep/wake to prevent deadlocks.
1697 OSMetaClassSystemSleepOrWake( kIOMessageSystemHasPoweredOn
);
1699 IOHibernateSystemPostWake();
1700 return tellClients(kIOMessageSystemHasPoweredOn
);
1704 //*********************************************************************************
1707 //*********************************************************************************
1709 void IOPMrootDomain::reportUserInput ( void )
1715 iter
= getMatchingServices(serviceMatching("IODisplayWrangler"));
1718 wrangler
= (IOService
*) iter
->getNextObject();
1724 wrangler
->activityTickle(0,0);
1727 //*********************************************************************************
1728 // setQuickSpinDownTimeout
1730 //*********************************************************************************
1732 void IOPMrootDomain::setQuickSpinDownTimeout ( void )
1734 super::setAggressiveness((unsigned long)kPMMinutesToSpinDown
,(unsigned long)1);
1737 //*********************************************************************************
1738 // restoreUserSpinDownTimeout
1740 //*********************************************************************************
1742 void IOPMrootDomain::restoreUserSpinDownTimeout ( void )
1744 super::setAggressiveness((unsigned long)kPMMinutesToSpinDown
,(unsigned long)user_spindown
);
1747 //*********************************************************************************
1748 // changePowerStateTo & changePowerStateToPriv
1750 // Override of these methods for logging purposes.
1751 //*********************************************************************************
1753 IOReturn
IOPMrootDomain::changePowerStateTo ( unsigned long ordinal
)
1755 return super::changePowerStateTo(ordinal
);
1758 IOReturn
IOPMrootDomain::changePowerStateToPriv ( unsigned long ordinal
)
1762 if( SLEEP_STATE
== ordinal
&& sleepSupportedPEFunction
)
1765 // Determine if the machine supports sleep, or must doze.
1766 ret
= getPlatform()->callPlatformFunction(
1767 sleepSupportedPEFunction
, false,
1768 NULL
, NULL
, NULL
, NULL
);
1770 // If the machine only supports doze, the callPlatformFunction call
1771 // boils down toIOPMrootDomain::setSleepSupported(kPCICantSleep),
1772 // otherwise nothing.
1775 return super::changePowerStateToPriv(ordinal
);
1779 //*********************************************************************************
1780 // sysPowerDownHandler
1782 // Receives a notification when the RootDomain changes state.
1784 // Allows us to take action on system sleep, power down, and restart after
1785 // applications have received their power change notifications and replied,
1786 // but before drivers have powered down. We perform a vfs sync on power down.
1787 //*********************************************************************************
1789 IOReturn
IOPMrootDomain::sysPowerDownHandler( void * target
, void * refCon
,
1790 UInt32 messageType
, IOService
* service
,
1791 void * messageArgument
, vm_size_t argSize
)
1794 IOPowerStateChangeNotification
*params
= (IOPowerStateChangeNotification
*) messageArgument
;
1795 IOPMrootDomain
*rootDomain
= OSDynamicCast(IOPMrootDomain
, service
);
1798 return kIOReturnUnsupported
;
1800 switch (messageType
) {
1801 case kIOMessageSystemWillSleep
:
1802 rootDomain
->powerOverrideOnPriv(); // start ignoring children's requests
1803 // (fall through to other cases)
1805 // Interested applications have been notified of an impending power
1806 // change and have acked (when applicable).
1807 // This is our chance to save whatever state we can before powering
1809 // We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c,
1812 // We will ack within 20 seconds
1813 params
->returnValue
= 20 * 1000 * 1000;
1814 if (gIOHibernateState
)
1815 params
->returnValue
+= gIOHibernateFreeTime
* 1000; //add in time we could spend freeing pages
1817 if ( ! OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending
) )
1819 // Purposely delay the ack and hope that shutdown occurs quickly.
1820 // Another option is not to schedule the thread and wait for
1822 AbsoluteTime deadline
;
1823 clock_interval_to_deadline( 30, kSecondScale
, &deadline
);
1824 thread_call_enter1_delayed( rootDomain
->diskSyncCalloutEntry
,
1825 (thread_call_param_t
)params
->powerRef
,
1829 thread_call_enter1(rootDomain
->diskSyncCalloutEntry
, (thread_call_param_t
)params
->powerRef
);
1830 ret
= kIOReturnSuccess
;
1833 case kIOMessageSystemWillPowerOff
:
1834 case kIOMessageSystemWillRestart
:
1835 ret
= kIOReturnUnsupported
;
1839 ret
= kIOReturnUnsupported
;
1845 //*********************************************************************************
1846 // displayWranglerNotification
1848 // Receives a notification when the IODisplayWrangler changes state.
1850 // Allows us to take action on display dim/undim.
1852 // When the display goes dim we:
1853 // - Start the idle sleep timer
1854 // - set the quick spin down timeout
1856 // On wake from display dim:
1857 // - Cancel the idle sleep timer
1858 // - restore the user's chosen spindown timer from the "quick" spin down value
1859 //*********************************************************************************
1861 IOReturn
IOPMrootDomain::displayWranglerNotification( void * target
, void * refCon
,
1862 UInt32 messageType
, IOService
* service
,
1863 void * messageArgument
, vm_size_t argSize
)
1865 IOPMrootDomain
* rootDomain
= OSDynamicCast(IOPMrootDomain
, (IOService
*)target
);
1866 AbsoluteTime deadline
;
1867 static bool deviceAlreadyPoweredOff
= false;
1870 return kIOReturnUnsupported
;
1872 switch (messageType
) {
1873 case kIOMessageDeviceWillPowerOff
:
1874 // The IODisplayWrangler has powered off either because of idle display sleep
1875 // or force system sleep.
1877 // The display wrangler will send the DeviceWillPowerOff message 4 times until
1878 // it gets into its lowest state. We only want to act on the first of those 4.
1879 if( deviceAlreadyPoweredOff
) return kIOReturnUnsupported
;
1881 deviceAlreadyPoweredOff
= true;
1883 if( rootDomain
->extraSleepDelay
)
1885 // start the extra sleep timer
1886 clock_interval_to_deadline(rootDomain
->extraSleepDelay
*60, kSecondScale
, &deadline
);
1887 thread_call_enter_delayed(rootDomain
->extraSleepTimer
, deadline
);
1888 rootDomain
->idleSleepPending
= true;
1890 // accelerate disk spin down if spin down timer is non-zero (zero = never spin down)
1891 // and if system sleep is non-Never
1892 if( (0 != rootDomain
->user_spindown
) && (0 != rootDomain
->sleepSlider
) )
1893 rootDomain
->setQuickSpinDownTimeout();
1898 case kIOMessageDeviceHasPoweredOn
:
1900 // The display has powered on either because of UI activity or wake from sleep/doze
1901 deviceAlreadyPoweredOff
= false;
1902 rootDomain
->adjustPowerState();
1905 // cancel any pending idle sleep
1906 if(rootDomain
->idleSleepPending
)
1908 thread_call_cancel(rootDomain
->extraSleepTimer
);
1909 rootDomain
->idleSleepPending
= false;
1912 // Change the spindown value back to the user's selection from our accelerated setting
1913 if(0 != rootDomain
->user_spindown
)
1914 rootDomain
->restoreUserSpinDownTimeout();
1916 // Put on the policy maker's on clamp.
1923 return kIOReturnUnsupported
;
1926 //*********************************************************************************
1927 // displayWranglerPublished
1929 // Receives a notification when the IODisplayWrangler is published.
1930 // When it's published we install a power state change handler.
1932 //*********************************************************************************
1934 bool IOPMrootDomain::displayWranglerPublished(
1937 IOService
* newService
)
1939 IOPMrootDomain
*rootDomain
=
1940 OSDynamicCast(IOPMrootDomain
, (IOService
*)target
);
1945 rootDomain
->wrangler
= newService
;
1947 // we found the display wrangler, now install a handler
1948 if( !rootDomain
->wrangler
->registerInterest( gIOGeneralInterest
,
1949 &displayWranglerNotification
, target
, 0) )
1958 //*********************************************************************************
1961 // Notification on battery class IOPowerSource appearance
1963 //******************************************************************************
1965 bool IOPMrootDomain::batteryPublished(
1968 IOService
* resourceService
)
1970 // rdar://2936060&4435589
1971 // All laptops have dimmable LCD displays
1972 // All laptops have batteries
1973 // So if this machine has a battery, publish the fact that the backlight
1974 // supports dimming.
1975 ((IOPMrootDomain
*)root_domain
)->publishFeature("DisplayDims");
1982 //*********************************************************************************
1985 // Some condition that affects our wake/sleep/doze decision has changed.
1987 // If the sleep slider is in the off position, we cannot sleep or doze.
1988 // If the enclosure is open, we cannot sleep or doze.
1989 // If the system is still booting, we cannot sleep or doze.
1991 // In those circumstances, we prevent sleep and doze by holding power on with
1992 // changePowerStateToPriv(ON).
1994 // If the above conditions do not exist, and also the sleep timer has expired, we
1995 // allow sleep or doze to occur with either changePowerStateToPriv(SLEEP) or
1996 // changePowerStateToPriv(DOZE) depending on whether or not we already know the
1997 // platform cannot sleep.
1999 // In this case, sleep or doze will either occur immediately or at the next time
2000 // that no children are holding the system out of idle sleep via the
2001 // kIOPMPreventIdleSleep flag in their power state arrays.
2002 //*********************************************************************************
2004 void IOPMrootDomain::adjustPowerState( void )
2006 if ( (sleepSlider
== 0) ||
2009 changePowerStateToPriv(ON_STATE
);
2014 if ( sleepIsSupported
)
2016 changePowerStateToPriv(SLEEP_STATE
);
2018 changePowerStateToPriv(DOZE_STATE
);
2024 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2029 #define super OSObject
2030 OSDefineMetaClassAndStructors(PMSettingObject
, OSObject
)
2032 void PMSettingObject::setPMSetting(const OSSymbol
*type
, OSObject
*obj
)
2034 (*func
)(target
, type
, obj
, refcon
);
2038 * Static constructor/initializer for PMSettingObject
2040 PMSettingObject
*PMSettingObject::pmSettingObject(
2041 IOPMrootDomain
*parent_arg
,
2042 IOPMSettingControllerCallback handler_arg
,
2043 OSObject
*target_arg
,
2044 uintptr_t refcon_arg
,
2045 uint32_t supportedPowerSources
,
2046 const OSSymbol
* settings
[])
2048 uint32_t objCount
= 0;
2049 PMSettingObject
*pmso
;
2051 if( !parent_arg
|| !handler_arg
|| !settings
) return NULL
;
2053 // count OSSymbol entries in NULL terminated settings array
2054 while( settings
[objCount
] ) {
2057 if(0 == objCount
) return NULL
;
2059 pmso
= new PMSettingObject
;
2060 if(!pmso
|| !pmso
->init()) return NULL
;
2062 pmso
->parent
= parent_arg
;
2063 pmso
->func
= handler_arg
;
2064 pmso
->target
= target_arg
;
2065 pmso
->refcon
= refcon_arg
;
2066 pmso
->releaseAtCount
= objCount
+ 1; // release when it has count+1 retains
2068 pmso
->publishedFeatureID
= (uint32_t *)IOMalloc(sizeof(uint32_t)*objCount
);
2069 if(pmso
->publishedFeatureID
) {
2070 for(unsigned int i
=0; i
<objCount
; i
++) {
2071 // Since there is now at least one listener to this setting, publish
2072 // PM root domain support for it.
2073 parent_arg
->publishFeature( settings
[i
]->getCStringNoCopy(),
2074 supportedPowerSources
, &pmso
->publishedFeatureID
[i
] );
2081 void PMSettingObject::free(void)
2083 OSCollectionIterator
*settings_iter
;
2088 int objCount
= releaseAtCount
- 1;
2090 if(publishedFeatureID
) {
2091 for(i
=0; i
<objCount
; i
++) {
2092 if(0 != publishedFeatureID
[i
]) {
2093 parent
->removePublishedFeature( publishedFeatureID
[i
] );
2097 IOFree(publishedFeatureID
, sizeof(uint32_t) * objCount
);
2100 IORecursiveLockLock(parent
->settingsCtrlLock
);
2102 // Search each PM settings array in the kernel.
2103 settings_iter
= OSCollectionIterator::withCollection(parent
->settingsCallbacks
);
2106 while(( sym
= OSDynamicCast(OSSymbol
, settings_iter
->getNextObject()) ))
2108 arr
= (OSArray
*)parent
->settingsCallbacks
->getObject(sym
);
2109 arr_idx
= arr
->getNextIndexOfObject(this, 0);
2111 // 'this' was found in the array; remove it
2112 arr
->removeObject(arr_idx
);
2116 settings_iter
->release();
2119 IORecursiveLockUnlock(parent
->settingsCtrlLock
);
2124 void PMSettingObject::taggedRelease(const void *tag
, const int when
) const
2126 // We have n+1 retains - 1 per array that this PMSettingObject is a member
2127 // of, and 1 retain to ourself. When we get a release with n+1 retains
2128 // remaining, we go ahead and free ourselves, cleaning up array pointers
2131 super::taggedRelease(tag
, releaseAtCount
);
2136 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2139 #define super IOService
2141 OSDefineMetaClassAndStructors(IORootParent
, IOService
)
2143 // This array exactly parallels the state array for the root domain.
2144 // Power state changes initiated by a device can be vetoed by a client of the device, and
2145 // power state changes initiated by the parent of a device cannot be vetoed by a client of the device,
2146 // so when the root domain wants a power state change that cannot be vetoed (e.g. demand sleep), it asks
2147 // its parent to make the change. That is the reason for this complexity.
2149 static IOPMPowerState patriarchPowerStates
[number_of_power_states
] = {
2150 {1,0,0,0,0,0,0,0,0,0,0,0}, // off
2151 {1,0,RESTART_POWER
,0,0,0,0,0,0,0,0,0}, // reset
2152 {1,0,SLEEP_POWER
,0,0,0,0,0,0,0,0,0}, // sleep
2153 {1,0,DOZE_POWER
,0,0,0,0,0,0,0,0,0}, // doze
2154 {1,0,ON_POWER
,0,0,0,0,0,0,0,0,0} // running
2157 bool IORootParent::start ( IOService
* nub
)
2159 mostRecentChange
= ON_STATE
;
2162 registerPowerDriver(this,patriarchPowerStates
,number_of_power_states
);
2163 powerOverrideOnPriv();
2168 void IORootParent::shutDownSystem ( void )
2170 mostRecentChange
= OFF_STATE
;
2171 changePowerStateToPriv(OFF_STATE
);
2175 void IORootParent::restartSystem ( void )
2177 mostRecentChange
= RESTART_STATE
;
2178 changePowerStateToPriv(RESTART_STATE
);
2182 void IORootParent::sleepSystem ( void )
2184 mostRecentChange
= SLEEP_STATE
;
2185 changePowerStateToPriv(SLEEP_STATE
);
2189 void IORootParent::dozeSystem ( void )
2191 mostRecentChange
= DOZE_STATE
;
2192 changePowerStateToPriv(DOZE_STATE
);
2195 // Called in demand sleep when sleep discovered to be impossible after actually attaining that state.
2196 // This brings the parent to doze, which allows the root to step up from sleep to doze.
2198 // In idle sleep, do nothing because the parent is still on and the root can freely change state.
2200 void IORootParent::sleepToDoze ( void )
2202 if ( mostRecentChange
== SLEEP_STATE
) {
2203 changePowerStateToPriv(DOZE_STATE
);
2208 void IORootParent::wakeSystem ( void )
2210 mostRecentChange
= ON_STATE
;
2211 changePowerStateToPriv(ON_STATE
);
2214 IOReturn
IORootParent::changePowerStateToPriv ( unsigned long ordinal
)
2218 if( SLEEP_STATE
== ordinal
&& sleepSupportedPEFunction
)
2221 // Determine if the machine supports sleep, or must doze.
2222 ret
= getPlatform()->callPlatformFunction(
2223 sleepSupportedPEFunction
, false,
2224 NULL
, NULL
, NULL
, NULL
);
2226 // If the machine only supports doze, the callPlatformFunction call
2227 // boils down toIOPMrootDomain::setSleepSupported(kPCICantSleep),
2228 // otherwise nothing.
2231 return super::changePowerStateToPriv(ordinal
);