2 * Copyright (c) 1998-2005 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
30 #include <IOKit/IOWorkLoop.h>
31 #include <IOKit/IOCommandGate.h>
32 #include <IOKit/IOTimerEventSource.h>
33 #include <IOKit/IOPlatformExpert.h>
34 #include <IOKit/IOKitDebug.h>
35 #include <IOKit/IOTimeStamp.h>
36 #include <IOKit/pwr_mgt/RootDomain.h>
37 #include <IOKit/pwr_mgt/IOPMPrivate.h>
38 #include <IOKit/IODeviceTreeSupport.h>
39 #include <IOKit/IOMessage.h>
40 #include <IOKit/IOReturn.h>
41 #include "RootDomainUserClient.h"
42 #include "IOKit/pwr_mgt/IOPowerConnection.h"
43 #include "IOPMPowerStateQueue.h"
44 #include <IOKit/IOCatalogue.h>
45 #include <IOKit/IOHibernatePrivate.h>
46 #include "IOPMWorkArbiter.h"
53 IOReturn
OSMetaClassSystemSleepOrWake( UInt32
);
56 extern const IORegistryPlane
* gIOPowerPlane
;
58 IOReturn
broadcast_aggressiveness ( OSObject
*, void *, void *, void *, void * );
59 static void sleepTimerExpired(thread_call_param_t
);
60 static void wakeupClamshellTimerExpired ( thread_call_param_t us
);
62 // "IOPMSetSleepSupported" callPlatformFunction name
63 static const OSSymbol
*sleepSupportedPEFunction
= NULL
;
65 #define kIOSleepSupportedKey "IOSleepSupported"
67 #define kRD_AllPowerSources (kIOPMSupportedOnAC \
68 | kIOPMSupportedOnBatt \
69 | kIOPMSupportedOnUPS)
71 #define number_of_power_states 5
73 #define RESTART_STATE 1
78 #define ON_POWER kIOPMPowerOn
79 #define RESTART_POWER kIOPMRestart
80 #define SLEEP_POWER kIOPMAuxPowerOn
81 #define DOZE_POWER kIOPMDoze
83 #define kLocalEvalClamshellCommand (1 << 15)
85 static IOPMPowerState ourPowerStates
[number_of_power_states
] = {
87 {1,0, 0, 0,0,0,0,0,0,0,0,0},
89 {1,kIOPMRestartCapability
, kIOPMRestart
, RESTART_POWER
,0,0,0,0,0,0,0,0},
91 {1,kIOPMSleepCapability
, kIOPMSleep
, SLEEP_POWER
,0,0,0,0,0,0,0,0},
93 {1,kIOPMDoze
, kIOPMDoze
, DOZE_POWER
,0,0,0,0,0,0,0,0},
95 {1,kIOPMPowerOn
, kIOPMPowerOn
, ON_POWER
,0,0,0,0,0,0,0,0},
98 static IOPMrootDomain
* gRootDomain
;
99 static UInt32 gSleepOrShutdownPending
= 0;
102 class PMSettingObject
: public OSObject
104 OSDeclareDefaultStructors(PMSettingObject
)
106 IOPMrootDomain
*parent
;
107 IOPMSettingControllerCallback func
;
110 uint32_t *publishedFeatureID
;
113 static PMSettingObject
*pmSettingObject(
114 IOPMrootDomain
*parent_arg
,
115 IOPMSettingControllerCallback handler_arg
,
116 OSObject
*target_arg
,
117 uintptr_t refcon_arg
,
118 uint32_t supportedPowerSources
,
119 const OSSymbol
*settings
[]);
121 void setPMSetting(const OSSymbol
*type
, OSObject
*obj
);
123 void taggedRelease(const void *tag
, const int when
) const;
129 #define super IOService
130 OSDefineMetaClassAndStructors(IOPMrootDomain
,IOService
)
134 IONotifier
* registerSleepWakeInterest(IOServiceInterestHandler handler
, void * self
, void * ref
)
136 return gRootDomain
->registerInterest( gIOGeneralInterest
, handler
, self
, ref
);
139 IONotifier
* registerPrioritySleepWakeInterest(IOServiceInterestHandler handler
, void * self
, void * ref
)
141 return gRootDomain
->registerInterest( gIOPriorityPowerStateInterest
, handler
, self
, ref
);
144 IOReturn
acknowledgeSleepWakeNotification(void * PMrefcon
)
146 return gRootDomain
->allowPowerChange ( (unsigned long)PMrefcon
);
149 IOReturn
vetoSleepWakeNotification(void * PMrefcon
)
151 return gRootDomain
->cancelPowerChange ( (unsigned long)PMrefcon
);
154 IOReturn
rootDomainRestart ( void )
156 return gRootDomain
->restartSystem();
159 IOReturn
rootDomainShutdown ( void )
161 return gRootDomain
->shutdownSystem();
164 void IOSystemShutdownNotification ( void )
166 IOCatalogue::disableExternalLinker();
167 for ( int i
= 0; i
< 100; i
++ )
169 if ( OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending
) ) break;
174 int sync_internal(void);
178 A device is always in the highest power state which satisfies its driver, its policy-maker, and any power domain
179 children it has, but within the constraint of the power state provided by its parent. The driver expresses its desire by
180 calling changePowerStateTo(), the policy-maker expresses its desire by calling changePowerStateToPriv(), and the children
181 express their desires by calling requestPowerDomainState().
183 The Root Power Domain owns the policy for idle and demand sleep and doze for the system. It is a power-managed IOService just
184 like the others in the system. It implements several power states which correspond to what we see as Sleep, Doze, etc.
186 The sleep/doze policy is as follows:
187 Sleep and Doze are prevented if the case is open so that nobody will think the machine is off and plug/unplug cards.
188 Sleep and Doze are prevented if the sleep timeout slider in the preferences panel is at zero.
189 The system cannot Sleep, but can Doze if some object in the tree is in a power state marked kIOPMPreventSystemSleep.
191 These three conditions are enforced using the "driver clamp" by calling changePowerStateTo(). For example, if the case is
192 opened, changePowerStateTo(ON_STATE) is called to hold the system on regardless of the desires of the children of the root or
193 the state of the other clamp.
195 Demand Sleep/Doze is initiated by pressing the front panel power button, closing the clamshell, or selecting the menu item.
196 In this case the root's parent actually initiates the power state change so that the root has no choice and does not give
197 applications the opportunity to veto the change.
199 Idle Sleep/Doze occurs if no objects in the tree are in a state marked kIOPMPreventIdleSleep. When this is true, the root's
200 children are not holding the root on, so it sets the "policy-maker clamp" by calling changePowerStateToPriv(ON_STATE)
201 to hold itself on until the sleep timer expires. This timer is set for the difference between the sleep timeout slider and
202 the larger of the display dim timeout slider and the disk spindown timeout slider in the Preferences panel. For example, if
203 the system is set to sleep after thirty idle minutes, and the display and disk are set to sleep after five idle minutes,
204 when there is no longer an object in the tree holding the system out of Idle Sleep (via kIOPMPreventIdleSleep), the root
205 sets its timer for 25 minutes (30 - 5). When the timer expires, it releases its clamp and now nothing is holding it awake,
208 Demand sleep is prevented when the system is booting. When preferences are transmitted by the loginwindow at the end of
209 boot, a flag is cleared, and this allows subsequent Demand Sleep.
211 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
212 a clamp, but sets a flag which is noticed before actually sleeping the kernel. If the flag is set, the root steps up
213 one power state from Sleep to Doze, and any objects in the tree for which this is relevent will act appropriately (USB and
214 ADB will turn on again so that they can wake the system out of Doze (keyboard/mouse activity will cause the Display Wrangler
218 // **********************************************************************************
220 IOPMrootDomain
* IOPMrootDomain::construct( void )
222 IOPMrootDomain
*root
;
224 root
= new IOPMrootDomain
;
231 // **********************************************************************************
233 static void disk_sync_callout(thread_call_param_t p0
, thread_call_param_t p1
)
235 IOService
*rootDomain
= (IOService
*) p0
;
236 unsigned long pmRef
= (unsigned long) p1
;
238 IOHibernateSystemSleep();
240 rootDomain
->allowPowerChange(pmRef
);
243 // **********************************************************************************
244 IOPMWorkArbiter
*IOPMrootDomain::getPMArbiter(void)
250 // **********************************************************************************
253 // We don't do much here. The real initialization occurs when the platform
254 // expert informs us we are the root.
255 // **********************************************************************************
257 #define kRootDomainSettingsCount 12
259 bool IOPMrootDomain::start ( IOService
* nub
)
261 OSIterator
*psIterator
;
262 OSDictionary
*tmpDict
;
263 const OSSymbol
*settingsArr
[kRootDomainSettingsCount
] =
265 OSSymbol::withCString(kIOPMSettingSleepOnPowerButtonKey
),
266 OSSymbol::withCString(kIOPMSettingAutoWakeSecondsKey
),
267 OSSymbol::withCString(kIOPMSettingAutoPowerSecondsKey
),
268 OSSymbol::withCString(kIOPMSettingAutoWakeCalendarKey
),
269 OSSymbol::withCString(kIOPMSettingAutoPowerCalendarKey
),
270 OSSymbol::withCString(kIOPMSettingDebugWakeRelativeKey
),
271 OSSymbol::withCString(kIOPMSettingDebugPowerRelativeKey
),
272 OSSymbol::withCString(kIOPMSettingWakeOnRingKey
),
273 OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey
),
274 OSSymbol::withCString(kIOPMSettingWakeOnClamshellKey
),
275 OSSymbol::withCString(kIOPMSettingWakeOnACChangeKey
),
276 OSSymbol::withCString(kIOPMSettingTimeZoneOffsetKey
)
280 pmPowerStateQueue
= 0;
282 _reserved
= (ExpansionData
*)IOMalloc(sizeof(ExpansionData
));
283 if(!_reserved
) return false;
291 sleepSupportedPEFunction
= OSSymbol::withCString("IOPMSetSleepSupported");
293 setProperty(kIOSleepSupportedKey
,true);
296 sleepIsSupported
= true;
297 systemBooting
= true;
299 idleSleepPending
= false;
302 clamshellIsClosed
= false;
303 clamshellExists
= false;
304 ignoringClamshell
= true;
305 ignoringClamshellDuringWakeup
= false;
306 acAdaptorConnect
= true;
308 tmpDict
= OSDictionary::withCapacity(1);
309 setProperty(kRootDomainSupportedFeatures
, tmpDict
);
312 settingsCallbacks
= OSDictionary::withCapacity(1);
314 // Create a list of the valid PM settings that we'll relay to
315 // interested clients in setProperties() => setPMSetting()
316 allowedPMSettings
= OSArray::withObjects(
317 (const OSObject
**)settingsArr
,
318 kRootDomainSettingsCount
,
321 fPMSettingsDict
= OSDictionary::withCapacity(5);
323 pm_vars
->PMworkloop
= IOWorkLoop::workLoop();
324 pmPowerStateQueue
= IOPMPowerStateQueue::PMPowerStateQueue(this);
325 pm_vars
->PMworkloop
->addEventSource(pmPowerStateQueue
);
327 /* Initialize PM arbiter */
328 pmArbiter
= IOPMWorkArbiter::pmWorkArbiter(this);
329 arbiterWorkLoop
= IOWorkLoop::workLoop();
330 arbiterWorkLoop
->addEventSource(pmArbiter
);
332 featuresDictLock
= IOLockAlloc();
333 settingsCtrlLock
= IORecursiveLockAlloc();
335 extraSleepTimer
= thread_call_allocate(
336 (thread_call_func_t
)sleepTimerExpired
,
337 (thread_call_param_t
) this);
338 clamshellWakeupIgnore
= thread_call_allocate(
339 (thread_call_func_t
)wakeupClamshellTimerExpired
,
340 (thread_call_param_t
) this);
341 diskSyncCalloutEntry
= thread_call_allocate(
343 (thread_call_param_t
) this);
346 patriarch
= new IORootParent
;
348 patriarch
->attach(this);
349 patriarch
->start(this);
350 patriarch
->youAreRoot();
351 patriarch
->wakeSystem();
352 patriarch
->addPowerChild(this);
354 registerPowerDriver(this,ourPowerStates
,number_of_power_states
);
356 setPMRootDomain(this);
357 // set a clamp until we sleep
358 changePowerStateToPriv(ON_STATE
);
360 // install power change handler
361 registerPrioritySleepWakeInterest( &sysPowerDownHandler
, this, 0);
363 // Register for a notification when IODisplayWrangler is published
364 _displayWranglerNotifier
= addNotification(
365 gIOPublishNotification
, serviceMatching("IODisplayWrangler"),
366 &displayWranglerPublished
, this, 0);
368 // Battery location published - ApplePMU support only
369 _batteryPublishNotifier
= addNotification(
370 gIOPublishNotification
, serviceMatching("IOPMPowerSource"),
371 &batteryPublished
, this, this);
374 const OSSymbol
*ucClassName
= OSSymbol::withCStringNoCopy("RootDomainUserClient");
375 setProperty(gIOUserClientClassKey
, (OSObject
*) ucClassName
);
376 ucClassName
->release();
378 // IOBacklightDisplay can take a long time to load at boot, or it may
379 // not load at all if you're booting with clamshell closed. We publish
380 // 'DisplayDims' here redundantly to get it published early and at all.
381 psIterator
= getMatchingServices( serviceMatching("IOPMPowerSource") );
382 if( psIterator
&& psIterator
->getNextObject() )
384 // There's at least one battery on the system, so we publish
385 // 'DisplayDims' support for the LCD.
386 publishFeature("DisplayDims");
389 psIterator
->release();
392 IOHibernateSystemInit(this);
394 registerService(); // let clients find us
399 // **********************************************************************************
402 // Receive a setProperty call
403 // The "System Boot" property means the system is completely booted.
404 // **********************************************************************************
405 IOReturn
IOPMrootDomain::setProperties ( OSObject
*props_obj
)
407 IOReturn return_value
= kIOReturnSuccess
;
408 OSDictionary
*dict
= OSDynamicCast(OSDictionary
, props_obj
);
416 const OSSymbol
*boot_complete_string
=
417 OSSymbol::withCString("System Boot Complete");
418 const OSSymbol
*stall_halt_string
=
419 OSSymbol::withCString("StallSystemAtHalt");
420 const OSSymbol
*hibernatemode_string
=
421 OSSymbol::withCString(kIOHibernateModeKey
);
422 const OSSymbol
*hibernatefile_string
=
423 OSSymbol::withCString(kIOHibernateFileKey
);
424 const OSSymbol
*hibernatefreeratio_string
=
425 OSSymbol::withCString(kIOHibernateFreeRatioKey
);
426 const OSSymbol
*hibernatefreetime_string
=
427 OSSymbol::withCString(kIOHibernateFreeTimeKey
);
431 return_value
= kIOReturnBadArgument
;
436 && boot_complete_string
437 && dict
->getObject(boot_complete_string
))
439 systemBooting
= false;
442 // If lid is closed, re-send lid closed notification
443 // now that booting is complete.
444 if( clamshellIsClosed
)
446 this->receivePowerNotification(kLocalEvalClamshellCommand
);
450 if( stall_halt_string
451 && (b
= OSDynamicCast(OSBoolean
, dict
->getObject(stall_halt_string
))) )
453 setProperty(stall_halt_string
, b
);
456 if ( hibernatemode_string
457 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(hibernatemode_string
))))
459 setProperty(hibernatemode_string
, n
);
461 if ( hibernatefreeratio_string
462 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(hibernatefreeratio_string
))))
464 setProperty(hibernatefreeratio_string
, n
);
466 if ( hibernatefreetime_string
467 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(hibernatefreetime_string
))))
469 setProperty(hibernatefreetime_string
, n
);
471 if ( hibernatefile_string
472 && (str
= OSDynamicCast(OSString
, dict
->getObject(hibernatefile_string
))))
474 setProperty(hibernatefile_string
, str
);
477 // Relay our allowed PM settings onto our registered PM clients
478 for(i
= 0; i
< allowedPMSettings
->getCount(); i
++) {
480 type
= (OSSymbol
*)allowedPMSettings
->getObject(i
);
483 obj
= dict
->getObject(type
);
486 return_value
= setPMSetting(type
, obj
);
488 if(kIOReturnSuccess
!= return_value
) goto exit
;
492 if(boot_complete_string
) boot_complete_string
->release();
493 if(stall_halt_string
) stall_halt_string
->release();
498 //*********************************************************************************
501 // Power Managment is informing us that we are the root power domain.
502 // We know we are not the root however, since we have just instantiated a parent
503 // for ourselves and made it the root. We override this method so it will have
505 //*********************************************************************************
506 IOReturn
IOPMrootDomain::youAreRoot ( void )
511 // **********************************************************************************
515 // **********************************************************************************
516 void IOPMrootDomain::command_received ( void * w
, void * x
, void * y
, void * z
)
518 super::command_received(w
,x
,y
,z
);
522 // **********************************************************************************
523 // broadcast_aggressiveness
525 // **********************************************************************************
526 IOReturn
broadcast_aggressiveness ( OSObject
* root
, void * x
, void * y
, void *, void * )
528 ((IOPMrootDomain
*)root
)->broadcast_it((unsigned long)x
,(unsigned long)y
);
533 // **********************************************************************************
536 // We are behind the command gate to broadcast an aggressiveness factor. We let the
537 // superclass do it, but we need to snoop on factors that affect idle sleep.
538 // **********************************************************************************
539 void IOPMrootDomain::broadcast_it (unsigned long type
, unsigned long value
)
541 super::setAggressiveness(type
,value
);
543 // Save user's spin down timer to restore after we replace it for idle sleep
544 if( type
== kPMMinutesToSpinDown
) user_spindown
= value
;
546 // Use longestNonSleepSlider to calculate dimming adjust idle sleep timer
547 longestNonSleepSlider
= pm_vars
->current_aggressiveness_values
[kPMMinutesToDim
];
550 if ( type
== kPMMinutesToSleep
) {
551 if ( (sleepSlider
== 0) && (value
!= 0) ) {
553 // idle sleep is now enabled, maybe sleep now
557 if ( sleepSlider
== 0 ) {
558 // idle sleep is now disabled
560 // make sure we're powered
561 patriarch
->wakeSystem();
564 if ( sleepSlider
> longestNonSleepSlider
) {
565 extraSleepDelay
= sleepSlider
- longestNonSleepSlider
;
573 // **********************************************************************************
576 // **********************************************************************************
577 static void sleepTimerExpired ( thread_call_param_t us
)
579 ((IOPMrootDomain
*)us
)->handleSleepTimerExpiration();
583 static void wakeupClamshellTimerExpired ( thread_call_param_t us
)
585 ((IOPMrootDomain
*)us
)->stopIgnoringClamshellEventsDuringWakeup();
589 // **********************************************************************************
590 // handleSleepTimerExpiration
592 // The time between the sleep idle timeout and the next longest one has elapsed.
593 // It's time to sleep. Start that by removing the clamp that's holding us awake.
594 // **********************************************************************************
595 void IOPMrootDomain::handleSleepTimerExpiration ( void )
597 // accelerate disk spin down if spin down timer is non-zero (zero = never spin down)
598 if(0 != user_spindown
)
599 setQuickSpinDownTimeout();
606 void IOPMrootDomain::stopIgnoringClamshellEventsDuringWakeup(void)
608 // Allow clamshell-induced sleep now
609 ignoringClamshellDuringWakeup
= false;
611 // Re-send clamshell event, in case it causes a sleep
612 if(clamshellIsClosed
)
613 this->receivePowerNotification( kLocalEvalClamshellCommand
);
616 //*********************************************************************************
619 // Some aggressiveness factor has changed. We broadcast it to the hierarchy while on
620 // the Power Mangement workloop thread. This enables objects in the
621 // hierarchy to successfully alter their idle timers, which are all on the
623 //*********************************************************************************
625 static int pmsallsetup
= 0;
627 IOReturn
IOPMrootDomain::setAggressiveness ( unsigned long type
, unsigned long newLevel
)
630 if(pmsExperimental
& 3) kprintf("setAggressiveness: type = %08X, newlevel = %08X\n", type
, newLevel
);
631 if(pmsExperimental
& 1) { /* Is experimental mode enabled? */
632 if(pmsInstalled
&& (type
== kPMSetProcessorSpeed
)) { /* We want to look at all processor speed changes if stepper is installed */
633 if(pmsallsetup
) return kIOReturnSuccess
; /* If already running, just eat this */
634 kprintf("setAggressiveness: starting stepper...\n");
635 pmsallsetup
= 1; /* Remember we did this */
637 pmsStart(); /* Get it all started up... */
638 return kIOReturnSuccess
; /* Leave now... */
643 if ( pm_vars
->PMcommandGate
) {
644 pm_vars
->PMcommandGate
->runAction(broadcast_aggressiveness
,(void *)type
,(void *)newLevel
);
647 return kIOReturnSuccess
;
651 // **********************************************************************************
654 // **********************************************************************************
655 IOReturn
IOPMrootDomain::sleepSystem ( void )
657 if ( !systemBooting
&& allowSleep
&& sleepIsSupported
) {
658 patriarch
->sleepSystem();
660 return kIOReturnSuccess
;
662 if ( !systemBooting
&& allowSleep
&& !sleepIsSupported
) {
663 patriarch
->dozeSystem();
664 return kIOReturnSuccess
;
666 return kIOReturnSuccess
;
670 // **********************************************************************************
673 // **********************************************************************************
674 IOReturn
IOPMrootDomain::shutdownSystem ( void )
676 //patriarch->shutDownSystem();
677 return kIOReturnUnsupported
;
681 // **********************************************************************************
684 // **********************************************************************************
685 IOReturn
IOPMrootDomain::restartSystem ( void )
687 //patriarch->restartSystem();
688 return kIOReturnUnsupported
;
692 // **********************************************************************************
695 // This overrides powerChangeDone in IOService.
697 // Finder sleep and idle sleep move us from the ON state to the SLEEP_STATE.
699 // If we just finished going to the SLEEP_STATE, and the platform is capable of true sleep,
700 // sleep the kernel. Otherwise switch up to the DOZE_STATE which will keep almost
701 // everything as off as it can get.
703 // **********************************************************************************
704 void IOPMrootDomain::powerChangeDone ( unsigned long previousState
)
706 OSNumber
* propertyPtr
;
707 unsigned short theProperty
;
708 AbsoluteTime deadline
;
710 switch ( pm_vars
->myCurrentState
) {
712 if ( canSleep
&& sleepIsSupported
)
714 // re-enable this timer for next sleep
715 idleSleepPending
= false;
717 IOLog("System %sSleep\n", gIOHibernateState
? "Safe" : "");
719 IOHibernateSystemHasSlept();
721 pm_vars
->thePlatform
->sleepKernel();
723 // The CPU(s) are off at this point. When they're awakened by CPU interrupt,
724 // code will resume execution here.
726 // Now we're waking...
727 IOHibernateSystemWake();
729 // stay awake for at least 30 seconds
730 clock_interval_to_deadline(30, kSecondScale
, &deadline
);
731 thread_call_enter_delayed(extraSleepTimer
, deadline
);
732 // this gets turned off when we sleep again
733 idleSleepPending
= true;
735 // Ignore closed clamshell during wakeup and for a few seconds
736 // after wakeup is complete
737 ignoringClamshellDuringWakeup
= true;
739 // sleep transition complete
740 gSleepOrShutdownPending
= 0;
742 // trip the reset of the calendar clock
743 clock_wakeup_calendar();
746 patriarch
->wakeSystem();
748 // early stage wake notification
749 tellClients(kIOMessageSystemWillPowerOn
);
751 // tell the tree we're waking
752 IOLog("System %sWake\n", gIOHibernateState
? "SafeSleep " : "");
755 // Allow drivers to request extra processing time before clamshell
756 // sleep if kIOREMSleepEnabledKey is present.
757 // Ignore clamshell events for at least 5 seconds
758 if(getProperty(kIOREMSleepEnabledKey
)) {
759 // clamshellWakeupIgnore callout clears ignoreClamshellDuringWakeup bit
760 clock_interval_to_deadline(5, kSecondScale
, &deadline
);
761 if(clamshellWakeupIgnore
) {
762 thread_call_enter_delayed(clamshellWakeupIgnore
, deadline
);
764 } else ignoringClamshellDuringWakeup
= false;
766 // Find out what woke us
767 propertyPtr
= OSDynamicCast(OSNumber
,getProperty("WakeEvent"));
769 theProperty
= propertyPtr
->unsigned16BitValue();
770 IOLog("Wake event %04x\n",theProperty
);
771 if ( (theProperty
& 0x0008) || //lid
772 (theProperty
& 0x0800) || // front panel button
773 (theProperty
& 0x0020) || // external keyboard
774 (theProperty
& 0x0001) ) { // internal keyboard
775 // We've identified the wakeup event as UI driven
779 // Since we can't identify the wakeup event, treat it as UI activity
783 // Wake for thirty seconds
784 changePowerStateToPriv(ON_STATE
);
785 powerOverrideOffPriv();
787 // allow us to step up a power state
788 patriarch
->sleepToDoze();
790 changePowerStateToPriv(DOZE_STATE
);
795 if ( previousState
!= DOZE_STATE
)
797 IOLog("System Doze\n");
799 // re-enable this timer for next sleep
800 idleSleepPending
= false;
801 gSleepOrShutdownPending
= 0;
805 IOLog("System Restart\n");
806 PEHaltRestart(kPERestartCPU
);
810 IOLog("System Halt\n");
811 PEHaltRestart(kPEHaltCPU
);
817 // **********************************************************************************
820 // The Display Wrangler calls here when it switches to its highest state. If the
821 // system is currently dozing, allow it to wake by making sure the parent is
823 // **********************************************************************************
824 void IOPMrootDomain::wakeFromDoze( void )
826 if ( pm_vars
->myCurrentState
== DOZE_STATE
)
828 // Reset sleep support till next sleep attempt.
829 // A machine's support of sleep vs. doze can change over the course of
830 // a running system, so we recalculate it before every sleep.
831 setSleepSupported(0);
833 powerOverrideOffPriv();
835 // early wake notification
836 tellClients(kIOMessageSystemWillPowerOn
);
838 // allow us to wake if children so desire
839 patriarch
->wakeSystem();
844 // *****************************************************************************
847 // Adds a new feature to the supported features dictionary
850 // *****************************************************************************
851 void IOPMrootDomain::publishFeature( const char * feature
)
853 publishFeature(feature
, kIOPMSupportedOnAC
854 | kIOPMSupportedOnBatt
855 | kIOPMSupportedOnUPS
,
861 // *****************************************************************************
862 // publishFeature (with supported power source specified)
864 // Adds a new feature to the supported features dictionary
867 // *****************************************************************************
868 void IOPMrootDomain::publishFeature(
870 uint32_t supportedWhere
,
871 uint32_t *uniqueFeatureID
)
873 static uint16_t next_feature_id
= 500;
875 OSNumber
*new_feature_data
= NULL
;
876 OSNumber
*existing_feature
= NULL
;
877 OSArray
*existing_feature_arr
= NULL
;
878 OSObject
*osObj
= NULL
;
879 uint32_t feature_value
= 0;
881 supportedWhere
&= kRD_AllPowerSources
; // mask off any craziness!
883 if(!supportedWhere
) {
884 // Feature isn't supported anywhere!
888 if(next_feature_id
> 5000) {
889 // Far, far too many features!
893 if(featuresDictLock
) IOLockLock(featuresDictLock
);
895 OSDictionary
*features
=
896 (OSDictionary
*) getProperty(kRootDomainSupportedFeatures
);
898 // Create new features dict if necessary
899 if ( features
&& OSDynamicCast(OSDictionary
, features
)) {
900 features
= OSDictionary::withDictionary(features
);
902 features
= OSDictionary::withCapacity(1);
905 // Create OSNumber to track new feature
907 next_feature_id
+= 1;
908 if( uniqueFeatureID
) {
909 // We don't really mind if the calling kext didn't give us a place
910 // to stash their unique id. Many kexts don't plan to unload, and thus
911 // have no need to remove themselves later.
912 *uniqueFeatureID
= next_feature_id
;
915 feature_value
= supportedWhere
+ (next_feature_id
<< 16);
916 new_feature_data
= OSNumber::withNumber(
917 (unsigned long long)feature_value
, 32);
919 // Does features object already exist?
920 if( (osObj
= features
->getObject(feature
)) )
922 if(( existing_feature
= OSDynamicCast(OSNumber
, osObj
) ))
924 // We need to create an OSArray to hold the now 2 elements.
925 existing_feature_arr
= OSArray::withObjects(
926 (const OSObject
**)&existing_feature
, 1, 2);
927 existing_feature_arr
->setObject(new_feature_data
);
928 features
->setObject(feature
, existing_feature_arr
);
929 } else if(( existing_feature_arr
= OSDynamicCast(OSArray
, osObj
) ))
931 // Add object to existing array
932 existing_feature_arr
->setObject(new_feature_data
);
935 // The easy case: no previously existing features listed. We simply
936 // set the OSNumber at key 'feature' and we're on our way.
937 features
->setObject(feature
, new_feature_data
);
940 new_feature_data
->release();
942 setProperty(kRootDomainSupportedFeatures
, features
);
946 // Notify EnergySaver and all those in user space so they might
947 // re-populate their feature specific UI
948 messageClients(kIOPMMessageFeatureChange
, this);
950 if(featuresDictLock
) IOLockUnlock(featuresDictLock
);
953 // *****************************************************************************
954 // removePublishedFeature
956 // Removes previously published feature
959 // *****************************************************************************
960 IOReturn
IOPMrootDomain::removePublishedFeature( uint32_t removeFeatureID
)
962 IOReturn ret
= kIOReturnError
;
963 uint32_t feature_value
= 0;
964 uint16_t feature_id
= 0;
965 bool madeAChange
= false;
967 OSSymbol
*dictKey
= NULL
;
968 OSCollectionIterator
*dictIterator
= NULL
;
969 OSArray
*arrayMember
= NULL
;
970 OSNumber
*numberMember
= NULL
;
971 OSObject
*osObj
= NULL
;
972 OSNumber
*osNum
= NULL
;
974 if(featuresDictLock
) IOLockLock(featuresDictLock
);
976 OSDictionary
*features
=
977 (OSDictionary
*) getProperty(kRootDomainSupportedFeatures
);
979 if ( features
&& OSDynamicCast(OSDictionary
, features
) )
981 // Any modifications to the dictionary are made to the copy to prevent
982 // races & crashes with userland clients. Dictionary updated
983 // automically later.
984 features
= OSDictionary::withDictionary(features
);
987 ret
= kIOReturnNotFound
;
991 // We iterate 'features' dictionary looking for an entry tagged
992 // with 'removeFeatureID'. If found, we remove it from our tracking
993 // structures and notify the OS via a general interest message.
995 dictIterator
= OSCollectionIterator::withCollection(features
);
1000 while( (dictKey
= OSDynamicCast(OSSymbol
, dictIterator
->getNextObject())) )
1002 osObj
= features
->getObject(dictKey
);
1004 // Each Feature is either tracked by an OSNumber
1005 if( osObj
&& (numberMember
= OSDynamicCast(OSNumber
, osObj
)) )
1007 feature_value
= numberMember
->unsigned32BitValue();
1008 feature_id
= (uint16_t)(feature_value
>> 16);
1010 if( feature_id
== (uint16_t)removeFeatureID
)
1013 features
->removeObject(dictKey
);
1018 // Or tracked by an OSArray of OSNumbers
1019 } else if( osObj
&& (arrayMember
= OSDynamicCast(OSArray
, osObj
)) )
1021 unsigned int arrayCount
= arrayMember
->getCount();
1023 for(unsigned int i
=0; i
<arrayCount
; i
++)
1025 osNum
= OSDynamicCast(OSNumber
, arrayMember
->getObject(i
));
1030 feature_value
= osNum
->unsigned32BitValue();
1031 feature_id
= (uint16_t)(feature_value
>> 16);
1033 if( feature_id
== (uint16_t)removeFeatureID
)
1036 if( 1 == arrayCount
) {
1037 // If the array only contains one element, remove
1039 features
->removeObject(dictKey
);
1041 // Otherwise just remove the element in question.
1042 arrayMember
->removeObject(i
);
1053 dictIterator
->release();
1057 ret
= kIOReturnSuccess
;
1059 setProperty(kRootDomainSupportedFeatures
, features
);
1061 // Notify EnergySaver and all those in user space so they might
1062 // re-populate their feature specific UI
1063 messageClients(kIOPMMessageFeatureChange
, this);
1065 ret
= kIOReturnNotFound
;
1069 if(features
) features
->release();
1070 if(featuresDictLock
) IOLockUnlock(featuresDictLock
);
1075 // **********************************************************************************
1078 // Enqueues unidle event to be performed later in a serialized context.
1080 // **********************************************************************************
1081 void IOPMrootDomain::unIdleDevice( IOService
*theDevice
, unsigned long theState
)
1083 if(pmPowerStateQueue
)
1084 pmPowerStateQueue
->unIdleOccurred(theDevice
, theState
);
1087 // **********************************************************************************
1088 // announcePowerSourceChange
1090 // Notifies "interested parties" that the batteries have changed state
1092 // **********************************************************************************
1093 void IOPMrootDomain::announcePowerSourceChange( void )
1095 IORegistryEntry
*_batteryRegEntry
= (IORegistryEntry
*) getProperty("BatteryEntry");
1097 // (if possible) re-publish power source state under IOPMrootDomain;
1098 // only do so if the battery controller publishes an IOResource
1099 // defining battery location. Called from ApplePMU battery driver.
1101 if(_batteryRegEntry
)
1104 batt_info
= (OSArray
*) _batteryRegEntry
->getProperty(kIOBatteryInfoKey
);
1106 setProperty(kIOBatteryInfoKey
, batt_info
);
1112 // *****************************************************************************
1113 // setPMSetting (private)
1115 // Internal helper to relay PM settings changes from user space to individual
1116 // drivers. Should be called only by IOPMrootDomain::setProperties.
1118 // *****************************************************************************
1119 IOReturn
IOPMrootDomain::setPMSetting(
1120 const OSSymbol
*type
,
1123 OSArray
*arr
= NULL
;
1124 PMSettingObject
*p_obj
= NULL
;
1128 if(NULL
== type
) return kIOReturnBadArgument
;
1130 IORecursiveLockLock(settingsCtrlLock
);
1132 fPMSettingsDict
->setObject(type
, obj
);
1134 arr
= (OSArray
*)settingsCallbacks
->getObject(type
);
1135 if(NULL
== arr
) goto exit
;
1136 count
= arr
->getCount();
1137 for(i
=0; i
<count
; i
++) {
1138 p_obj
= (PMSettingObject
*)OSDynamicCast(PMSettingObject
, arr
->getObject(i
));
1139 if(p_obj
) p_obj
->setPMSetting(type
, obj
);
1143 IORecursiveLockUnlock(settingsCtrlLock
);
1144 return kIOReturnSuccess
;
1147 // *****************************************************************************
1148 // copyPMSetting (public)
1150 // Allows kexts to safely read setting values, without being subscribed to
1153 // *****************************************************************************
1154 OSObject
* IOPMrootDomain::copyPMSetting(
1155 OSSymbol
*whichSetting
)
1157 OSObject
*obj
= NULL
;
1159 if(!whichSetting
) return NULL
;
1161 IORecursiveLockLock(settingsCtrlLock
);
1162 obj
= fPMSettingsDict
->getObject(whichSetting
);
1166 IORecursiveLockUnlock(settingsCtrlLock
);
1171 // *****************************************************************************
1172 // registerPMSettingController (public)
1174 // direct wrapper to registerPMSettingController with uint32_t power source arg
1175 // *****************************************************************************
1176 IOReturn
IOPMrootDomain::registerPMSettingController(
1177 const OSSymbol
* settings
[],
1178 IOPMSettingControllerCallback func
,
1183 return registerPMSettingController(
1185 (kIOPMSupportedOnAC
| kIOPMSupportedOnBatt
| kIOPMSupportedOnUPS
),
1186 func
, target
, refcon
, handle
);
1189 // *****************************************************************************
1190 // registerPMSettingController (public)
1192 // Kexts may register for notifications when a particular setting is changed.
1193 // A list of settings is available in IOPM.h.
1195 // * settings - An OSArray containing OSSymbols. Caller should populate this
1196 // array with a list of settings caller wants notifications from.
1197 // * func - A C function callback of the type IOPMSettingControllerCallback
1198 // * target - caller may provide an OSObject *, which PM will pass as an
1199 // target to calls to "func"
1200 // * refcon - caller may provide an void *, which PM will pass as an
1201 // argument to calls to "func"
1202 // * handle - This is a return argument. We will populate this pointer upon
1203 // call success. Hold onto this and pass this argument to
1204 // IOPMrootDomain::deRegisterPMSettingCallback when unloading your kext
1206 // kIOReturnSuccess on success
1207 // *****************************************************************************
1208 IOReturn
IOPMrootDomain::registerPMSettingController(
1209 const OSSymbol
* settings
[],
1210 uint32_t supportedPowerSources
,
1211 IOPMSettingControllerCallback func
,
1216 PMSettingObject
*pmso
= NULL
;
1217 OSArray
*list
= NULL
;
1218 IOReturn ret
= kIOReturnSuccess
;
1221 if( NULL
== settings
||
1225 return kIOReturnBadArgument
;
1229 pmso
= PMSettingObject::pmSettingObject(
1230 (IOPMrootDomain
*)this, func
, target
,
1231 refcon
, supportedPowerSources
, settings
);
1234 ret
= kIOReturnInternalError
;
1235 goto bail_no_unlock
;
1238 IORecursiveLockLock(settingsCtrlLock
);
1239 for(i
=0; settings
[i
]; i
++)
1241 list
= (OSArray
*)settingsCallbacks
->getObject(settings
[i
]);
1243 // New array of callbacks for this setting
1244 list
= OSArray::withCapacity(1);
1245 settingsCallbacks
->setObject(settings
[i
], list
);
1249 // Add caller to the callback list
1250 list
->setObject(pmso
);
1253 ret
= kIOReturnSuccess
;
1255 // Track this instance by its OSData ptr from now on
1258 IORecursiveLockUnlock(settingsCtrlLock
);
1261 if(kIOReturnSuccess
!= ret
)
1263 // Error return case
1264 if(pmso
) pmso
->release();
1265 if(handle
) *handle
= NULL
;
1270 //******************************************************************************
1271 // sleepOnClamshellClosed
1273 // contains the logic to determine if the system should sleep when the clamshell
1275 //******************************************************************************
1277 bool IOPMrootDomain::shouldSleepOnClamshellClosed ( void )
1279 return ( !ignoringClamshell
1280 && !ignoringClamshellDuringWakeup
1281 && !(desktopMode
&& acAdaptorConnect
) );
1284 void IOPMrootDomain::sendClientClamshellNotification ( void )
1286 /* Only broadcast clamshell alert if clamshell exists. */
1287 if(!clamshellExists
)
1290 setProperty(kAppleClamshellStateKey
,
1291 clamshellIsClosed
? kOSBooleanTrue
: kOSBooleanFalse
);
1293 setProperty(kAppleClamshellCausesSleepKey
,
1294 shouldSleepOnClamshellClosed() ? kOSBooleanTrue
: kOSBooleanFalse
);
1297 /* Argument to message is a bitfield of
1298 * ( kClamshellStateBit | kClamshellSleepBit )
1299 * Carry on the clamshell state change notification from an
1300 * independent thread.
1302 pmArbiter
->clamshellStateChangeOccurred(
1303 (uint32_t) ( (clamshellIsClosed
? kClamshellStateBit
: 0)
1304 | ( shouldSleepOnClamshellClosed() ? kClamshellSleepBit
: 0)));
1307 //******************************************************************************
1308 // receivePowerNotification
1310 // The power controller is notifying us of a hardware-related power management
1311 // event that we must handle. This is a result of an 'environment' interrupt from
1312 // the power mgt micro.
1313 //******************************************************************************
1315 IOReturn
IOPMrootDomain::receivePowerNotification (UInt32 msg
)
1317 bool eval_clamshell
= false;
1320 * Local (IOPMrootDomain only) eval clamshell command
1322 if (msg
& kLocalEvalClamshellCommand
)
1324 eval_clamshell
= true;
1330 if (msg
& kIOPMOverTemp
)
1332 IOLog("PowerManagement emergency overtemp signal. Going to sleep!");
1333 (void) sleepSystem ();
1337 * PMU Processor Speed Change
1339 if (msg
& kIOPMProcessorSpeedChange
)
1341 IOService
*pmu
= waitForService(serviceMatching("ApplePMU"));
1342 pmu
->callPlatformFunction("prepareForSleep", false, 0, 0, 0, 0);
1343 pm_vars
->thePlatform
->sleepKernel();
1344 pmu
->callPlatformFunction("recoverFromSleep", false, 0, 0, 0, 0);
1350 if (msg
& kIOPMSleepNow
)
1352 (void) sleepSystem ();
1358 if (msg
& kIOPMPowerEmergency
)
1360 (void) sleepSystem ();
1367 if (msg
& kIOPMClamshellOpened
)
1369 // Received clamshel open message from clamshell controlling driver
1370 // Update our internal state and tell general interest clients
1371 clamshellIsClosed
= false;
1372 clamshellExists
= true;
1374 sendClientClamshellNotification();
1379 * Send the clamshell interest notification since the lid is closing.
1381 if (msg
& kIOPMClamshellClosed
)
1383 // Received clamshel open message from clamshell controlling driver
1384 // Update our internal state and tell general interest clients
1385 clamshellIsClosed
= true;
1386 clamshellExists
= true;
1388 sendClientClamshellNotification();
1390 // And set eval_clamshell = so we can attempt
1391 eval_clamshell
= true;
1395 * Set Desktop mode (sent from graphics)
1397 * -> reevaluate lid state
1399 if (msg
& kIOPMSetDesktopMode
)
1401 desktopMode
= (0 != (msg
& kIOPMSetValue
));
1402 msg
&= ~(kIOPMSetDesktopMode
| kIOPMSetValue
);
1404 sendClientClamshellNotification();
1406 // Re-evaluate the lid state
1407 if( clamshellIsClosed
)
1409 eval_clamshell
= true;
1414 * AC Adaptor connected
1416 * -> reevaluate lid state
1418 if (msg
& kIOPMSetACAdaptorConnected
)
1420 acAdaptorConnect
= (0 != (msg
& kIOPMSetValue
));
1421 msg
&= ~(kIOPMSetACAdaptorConnected
| kIOPMSetValue
);
1423 sendClientClamshellNotification();
1425 // Re-evaluate the lid state
1426 if( clamshellIsClosed
)
1428 eval_clamshell
= true;
1434 * Enable Clamshell (external display disappear)
1436 * -> reevaluate lid state
1438 if (msg
& kIOPMEnableClamshell
)
1440 // Re-evaluate the lid state
1441 // System should sleep on external display disappearance
1442 // in lid closed operation.
1443 if( clamshellIsClosed
&& (true == ignoringClamshell
) )
1445 eval_clamshell
= true;
1448 ignoringClamshell
= false;
1450 sendClientClamshellNotification();
1454 * Disable Clamshell (external display appeared)
1455 * We don't bother re-evaluating clamshell state. If the system is awake,
1456 * the lid is probably open.
1458 if (msg
& kIOPMDisableClamshell
)
1460 ignoringClamshell
= true;
1462 sendClientClamshellNotification();
1466 * Evaluate clamshell and SLEEP if appropiate
1468 if ( eval_clamshell
&& shouldSleepOnClamshellClosed() )
1479 if (msg
& kIOPMPowerButton
)
1481 // toggle state of sleep/wake
1483 if ( pm_vars
->myCurrentState
== DOZE_STATE
)
1485 // yes, tell the tree we're waking
1487 // wake the Display Wrangler
1491 OSString
*pbs
= OSString::withCString("DisablePowerButtonSleep");
1492 // Check that power button sleep is enabled
1494 if( kOSBooleanTrue
!= getProperty(pbs
))
1504 if ( (msg
& kIOPMAllowSleep
) && !allowSleep
)
1514 if (msg
& kIOPMPreventSleep
) {
1517 if ( pm_vars
->myCurrentState
== DOZE_STATE
) {
1518 // yes, tell the tree we're waking
1521 // wake the Display Wrangler
1525 // make sure we have power to clamp
1526 patriarch
->wakeSystem();
1534 //*********************************************************************************
1537 //*********************************************************************************
1539 void IOPMrootDomain::setSleepSupported( IOOptionBits flags
)
1541 if ( flags
& kPCICantSleep
)
1546 platformSleepSupport
= flags
;
1549 setProperty(kIOSleepSupportedKey
, canSleep
);
1553 //*********************************************************************************
1554 // requestPowerDomainState
1556 // The root domain intercepts this call to the superclass.
1558 // If the clamp bit is not set in the desire, then the child doesn't need the power
1559 // state it's requesting; it just wants it. The root ignores desires but not needs.
1560 // If the clamp bit is not set, the root takes it that the child can tolerate no
1561 // power and interprets the request accordingly. If all children can thus tolerate
1562 // no power, we are on our way to idle sleep.
1563 //*********************************************************************************
1565 IOReturn
IOPMrootDomain::requestPowerDomainState ( IOPMPowerFlags desiredState
, IOPowerConnection
* whichChild
, unsigned long specification
)
1569 IOPowerConnection
*connection
;
1570 unsigned long powerRequestFlag
= 0;
1571 IOPMPowerFlags editedDesire
= desiredState
;
1573 // if they don't really need it, they don't get it
1574 if ( !(desiredState
& kIOPMPreventIdleSleep
) ) {
1579 IOLockLock(pm_vars
->childLock
);
1581 // recompute sleepIsSupported and see if all children are asleep
1582 iter
= getChildIterator(gIOPowerPlane
);
1583 sleepIsSupported
= true;
1586 while ( (next
= iter
->getNextObject()) )
1588 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1590 if ( connection
== whichChild
)
1592 powerRequestFlag
+= editedDesire
;
1593 if ( desiredState
& kIOPMPreventSystemSleep
)
1595 sleepIsSupported
= false;
1598 powerRequestFlag
+= connection
->getDesiredDomainState();
1599 if ( connection
->getPreventSystemSleepFlag() )
1601 sleepIsSupported
= false;
1609 if ( (extraSleepDelay
== 0) && (powerRequestFlag
== 0) )
1614 // this may put the system to sleep
1617 IOLockUnlock(pm_vars
->childLock
);
1619 editedDesire
|= desiredState
& kIOPMPreventSystemSleep
;
1621 return super::requestPowerDomainState(editedDesire
,whichChild
,specification
);
1625 //*********************************************************************************
1626 // getSleepSupported
1628 //*********************************************************************************
1630 IOOptionBits
IOPMrootDomain::getSleepSupported( void )
1632 return( platformSleepSupport
);
1636 //*********************************************************************************
1639 // We override the superclass implementation so we can send a different message
1640 // type to the client or application being notified.
1641 //*********************************************************************************
1643 bool IOPMrootDomain::tellChangeDown ( unsigned long stateNum
)
1645 switch ( stateNum
) {
1649 // Direct callout into OSMetaClass so it can disable kmod unloads
1650 // during sleep/wake to prevent deadlocks.
1651 OSMetaClassSystemSleepOrWake( kIOMessageSystemWillSleep
);
1653 return super::tellClientsWithResponse(kIOMessageSystemWillSleep
);
1655 // Unsupported shutdown ordering hack on RESTART only
1656 // For Bluetooth and USB (4368327)
1657 super::tellClients(iokit_common_msg(0x759));
1659 return super::tellClientsWithResponse(kIOMessageSystemWillRestart
);
1661 // Unsupported shutdown ordering hack on SHUTDOWN only
1662 // For Bluetooth and USB (4554440)
1663 super::tellClients(iokit_common_msg(0x749));
1665 return super::tellClientsWithResponse(kIOMessageSystemWillPowerOff
);
1667 // this shouldn't execute
1668 return super::tellChangeDown(stateNum
);
1672 //*********************************************************************************
1675 // We override the superclass implementation so we can send a different message
1676 // type to the client or application being notified.
1678 // This must be idle sleep since we don't ask apps during any other power change.
1679 //*********************************************************************************
1681 bool IOPMrootDomain::askChangeDown ( unsigned long )
1683 return super::tellClientsWithResponse(kIOMessageCanSystemSleep
);
1687 //*********************************************************************************
1690 // Notify registered applications and kernel clients that we are not
1693 // We override the superclass implementation so we can send a different message
1694 // type to the client or application being notified.
1696 // This must be a vetoed idle sleep, since no other power change can be vetoed.
1697 //*********************************************************************************
1699 void IOPMrootDomain::tellNoChangeDown ( unsigned long )
1701 return tellClients(kIOMessageSystemWillNotSleep
);
1705 //*********************************************************************************
1708 // Notify registered applications and kernel clients that we are raising power.
1710 // We override the superclass implementation so we can send a different message
1711 // type to the client or application being notified.
1712 //*********************************************************************************
1714 void IOPMrootDomain::tellChangeUp ( unsigned long stateNum
)
1716 if ( stateNum
== ON_STATE
)
1718 // Direct callout into OSMetaClass so it can disable kmod unloads
1719 // during sleep/wake to prevent deadlocks.
1720 OSMetaClassSystemSleepOrWake( kIOMessageSystemHasPoweredOn
);
1722 IOHibernateSystemPostWake();
1723 return tellClients(kIOMessageSystemHasPoweredOn
);
1727 //*********************************************************************************
1730 //*********************************************************************************
1732 void IOPMrootDomain::reportUserInput ( void )
1738 iter
= getMatchingServices(serviceMatching("IODisplayWrangler"));
1741 wrangler
= (IOService
*) iter
->getNextObject();
1747 wrangler
->activityTickle(0,0);
1750 //*********************************************************************************
1751 // setQuickSpinDownTimeout
1753 //*********************************************************************************
1755 void IOPMrootDomain::setQuickSpinDownTimeout ( void )
1757 super::setAggressiveness((unsigned long)kPMMinutesToSpinDown
,(unsigned long)1);
1760 //*********************************************************************************
1761 // restoreUserSpinDownTimeout
1763 //*********************************************************************************
1765 void IOPMrootDomain::restoreUserSpinDownTimeout ( void )
1767 super::setAggressiveness((unsigned long)kPMMinutesToSpinDown
,(unsigned long)user_spindown
);
1770 //*********************************************************************************
1771 // changePowerStateTo & changePowerStateToPriv
1773 // Override of these methods for logging purposes.
1774 //*********************************************************************************
1776 IOReturn
IOPMrootDomain::changePowerStateTo ( unsigned long ordinal
)
1778 return super::changePowerStateTo(ordinal
);
1781 IOReturn
IOPMrootDomain::changePowerStateToPriv ( unsigned long ordinal
)
1785 if( SLEEP_STATE
== ordinal
&& sleepSupportedPEFunction
)
1788 // Determine if the machine supports sleep, or must doze.
1789 ret
= getPlatform()->callPlatformFunction(
1790 sleepSupportedPEFunction
, false,
1791 NULL
, NULL
, NULL
, NULL
);
1793 // If the machine only supports doze, the callPlatformFunction call
1794 // boils down toIOPMrootDomain::setSleepSupported(kPCICantSleep),
1795 // otherwise nothing.
1798 return super::changePowerStateToPriv(ordinal
);
1802 //*********************************************************************************
1803 // sysPowerDownHandler
1805 // Receives a notification when the RootDomain changes state.
1807 // Allows us to take action on system sleep, power down, and restart after
1808 // applications have received their power change notifications and replied,
1809 // but before drivers have powered down. We perform a vfs sync on power down.
1810 //*********************************************************************************
1812 IOReturn
IOPMrootDomain::sysPowerDownHandler( void * target
, void * refCon
,
1813 UInt32 messageType
, IOService
* service
,
1814 void * messageArgument
, vm_size_t argSize
)
1817 IOPowerStateChangeNotification
*params
= (IOPowerStateChangeNotification
*) messageArgument
;
1818 IOPMrootDomain
*rootDomain
= OSDynamicCast(IOPMrootDomain
, service
);
1821 return kIOReturnUnsupported
;
1823 switch (messageType
) {
1824 case kIOMessageSystemWillSleep
:
1825 rootDomain
->powerOverrideOnPriv(); // start ignoring children's requests
1826 // (fall through to other cases)
1828 // Interested applications have been notified of an impending power
1829 // change and have acked (when applicable).
1830 // This is our chance to save whatever state we can before powering
1832 // We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c,
1835 // We will ack within 20 seconds
1836 params
->returnValue
= 20 * 1000 * 1000;
1837 if (gIOHibernateState
)
1838 params
->returnValue
+= gIOHibernateFreeTime
* 1000; //add in time we could spend freeing pages
1840 if ( ! OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending
) )
1842 // Purposely delay the ack and hope that shutdown occurs quickly.
1843 // Another option is not to schedule the thread and wait for
1845 AbsoluteTime deadline
;
1846 clock_interval_to_deadline( 30, kSecondScale
, &deadline
);
1847 thread_call_enter1_delayed( rootDomain
->diskSyncCalloutEntry
,
1848 (thread_call_param_t
)params
->powerRef
,
1852 thread_call_enter1(rootDomain
->diskSyncCalloutEntry
, (thread_call_param_t
)params
->powerRef
);
1853 ret
= kIOReturnSuccess
;
1856 case kIOMessageSystemWillPowerOff
:
1857 case kIOMessageSystemWillRestart
:
1858 ret
= kIOReturnUnsupported
;
1862 ret
= kIOReturnUnsupported
;
1868 //*********************************************************************************
1869 // displayWranglerNotification
1871 // Receives a notification when the IODisplayWrangler changes state.
1873 // Allows us to take action on display dim/undim.
1875 // When the display goes dim we:
1876 // - Start the idle sleep timer
1877 // - set the quick spin down timeout
1879 // On wake from display dim:
1880 // - Cancel the idle sleep timer
1881 // - restore the user's chosen spindown timer from the "quick" spin down value
1882 //*********************************************************************************
1884 IOReturn
IOPMrootDomain::displayWranglerNotification( void * target
, void * refCon
,
1885 UInt32 messageType
, IOService
* service
,
1886 void * messageArgument
, vm_size_t argSize
)
1888 IOPMrootDomain
* rootDomain
= OSDynamicCast(IOPMrootDomain
, (IOService
*)target
);
1889 AbsoluteTime deadline
;
1890 static bool deviceAlreadyPoweredOff
= false;
1893 return kIOReturnUnsupported
;
1895 switch (messageType
) {
1896 case kIOMessageDeviceWillPowerOff
:
1897 // The IODisplayWrangler has powered off either because of idle display sleep
1898 // or force system sleep.
1900 // The display wrangler will send the DeviceWillPowerOff message 4 times until
1901 // it gets into its lowest state. We only want to act on the first of those 4.
1902 if( deviceAlreadyPoweredOff
) return kIOReturnUnsupported
;
1904 deviceAlreadyPoweredOff
= true;
1906 if( rootDomain
->extraSleepDelay
)
1908 // start the extra sleep timer
1909 clock_interval_to_deadline(rootDomain
->extraSleepDelay
*60, kSecondScale
, &deadline
);
1910 thread_call_enter_delayed(rootDomain
->extraSleepTimer
, deadline
);
1911 rootDomain
->idleSleepPending
= true;
1913 // accelerate disk spin down if spin down timer is non-zero (zero = never spin down)
1914 // and if system sleep is non-Never
1915 if( (0 != rootDomain
->user_spindown
) && (0 != rootDomain
->sleepSlider
) )
1916 rootDomain
->setQuickSpinDownTimeout();
1921 case kIOMessageDeviceHasPoweredOn
:
1923 // The display has powered on either because of UI activity or wake from sleep/doze
1924 deviceAlreadyPoweredOff
= false;
1925 rootDomain
->adjustPowerState();
1928 // cancel any pending idle sleep
1929 if(rootDomain
->idleSleepPending
)
1931 thread_call_cancel(rootDomain
->extraSleepTimer
);
1932 rootDomain
->idleSleepPending
= false;
1935 // Change the spindown value back to the user's selection from our accelerated setting
1936 if(0 != rootDomain
->user_spindown
)
1937 rootDomain
->restoreUserSpinDownTimeout();
1939 // Put on the policy maker's on clamp.
1946 return kIOReturnUnsupported
;
1949 //*********************************************************************************
1950 // displayWranglerPublished
1952 // Receives a notification when the IODisplayWrangler is published.
1953 // When it's published we install a power state change handler.
1955 //*********************************************************************************
1957 bool IOPMrootDomain::displayWranglerPublished(
1960 IOService
* newService
)
1962 IOPMrootDomain
*rootDomain
=
1963 OSDynamicCast(IOPMrootDomain
, (IOService
*)target
);
1968 rootDomain
->wrangler
= newService
;
1970 // we found the display wrangler, now install a handler
1971 if( !rootDomain
->wrangler
->registerInterest( gIOGeneralInterest
,
1972 &displayWranglerNotification
, target
, 0) )
1981 //*********************************************************************************
1984 // Notification on battery class IOPowerSource appearance
1986 //******************************************************************************
1988 bool IOPMrootDomain::batteryPublished(
1991 IOService
* resourceService
)
1993 // rdar://2936060&4435589
1994 // All laptops have dimmable LCD displays
1995 // All laptops have batteries
1996 // So if this machine has a battery, publish the fact that the backlight
1997 // supports dimming.
1998 ((IOPMrootDomain
*)root_domain
)->publishFeature("DisplayDims");
2005 //*********************************************************************************
2008 // Some condition that affects our wake/sleep/doze decision has changed.
2010 // If the sleep slider is in the off position, we cannot sleep or doze.
2011 // If the enclosure is open, we cannot sleep or doze.
2012 // If the system is still booting, we cannot sleep or doze.
2014 // In those circumstances, we prevent sleep and doze by holding power on with
2015 // changePowerStateToPriv(ON).
2017 // If the above conditions do not exist, and also the sleep timer has expired, we
2018 // allow sleep or doze to occur with either changePowerStateToPriv(SLEEP) or
2019 // changePowerStateToPriv(DOZE) depending on whether or not we already know the
2020 // platform cannot sleep.
2022 // In this case, sleep or doze will either occur immediately or at the next time
2023 // that no children are holding the system out of idle sleep via the
2024 // kIOPMPreventIdleSleep flag in their power state arrays.
2025 //*********************************************************************************
2027 void IOPMrootDomain::adjustPowerState( void )
2029 if ( (sleepSlider
== 0) ||
2032 changePowerStateToPriv(ON_STATE
);
2037 if ( sleepIsSupported
)
2039 changePowerStateToPriv(SLEEP_STATE
);
2041 changePowerStateToPriv(DOZE_STATE
);
2047 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2052 #define super OSObject
2053 OSDefineMetaClassAndStructors(PMSettingObject
, OSObject
)
2055 void PMSettingObject::setPMSetting(const OSSymbol
*type
, OSObject
*obj
)
2057 (*func
)(target
, type
, obj
, refcon
);
2061 * Static constructor/initializer for PMSettingObject
2063 PMSettingObject
*PMSettingObject::pmSettingObject(
2064 IOPMrootDomain
*parent_arg
,
2065 IOPMSettingControllerCallback handler_arg
,
2066 OSObject
*target_arg
,
2067 uintptr_t refcon_arg
,
2068 uint32_t supportedPowerSources
,
2069 const OSSymbol
* settings
[])
2071 uint32_t objCount
= 0;
2072 PMSettingObject
*pmso
;
2074 if( !parent_arg
|| !handler_arg
|| !settings
) return NULL
;
2076 // count OSSymbol entries in NULL terminated settings array
2077 while( settings
[objCount
] ) {
2080 if(0 == objCount
) return NULL
;
2082 pmso
= new PMSettingObject
;
2083 if(!pmso
|| !pmso
->init()) return NULL
;
2085 pmso
->parent
= parent_arg
;
2086 pmso
->func
= handler_arg
;
2087 pmso
->target
= target_arg
;
2088 pmso
->refcon
= refcon_arg
;
2089 pmso
->releaseAtCount
= objCount
+ 1; // release when it has count+1 retains
2091 pmso
->publishedFeatureID
= (uint32_t *)IOMalloc(sizeof(uint32_t)*objCount
);
2092 if(pmso
->publishedFeatureID
) {
2093 for(unsigned int i
=0; i
<objCount
; i
++) {
2094 // Since there is now at least one listener to this setting, publish
2095 // PM root domain support for it.
2096 parent_arg
->publishFeature( settings
[i
]->getCStringNoCopy(),
2097 supportedPowerSources
, &pmso
->publishedFeatureID
[i
] );
2104 void PMSettingObject::free(void)
2106 OSCollectionIterator
*settings_iter
;
2111 int objCount
= releaseAtCount
- 1;
2113 if(publishedFeatureID
) {
2114 for(i
=0; i
<objCount
; i
++) {
2115 if(0 != publishedFeatureID
[i
]) {
2116 parent
->removePublishedFeature( publishedFeatureID
[i
] );
2120 IOFree(publishedFeatureID
, sizeof(uint32_t) * objCount
);
2123 IORecursiveLockLock(parent
->settingsCtrlLock
);
2125 // Search each PM settings array in the kernel.
2126 settings_iter
= OSCollectionIterator::withCollection(parent
->settingsCallbacks
);
2129 while(( sym
= OSDynamicCast(OSSymbol
, settings_iter
->getNextObject()) ))
2131 arr
= (OSArray
*)parent
->settingsCallbacks
->getObject(sym
);
2132 arr_idx
= arr
->getNextIndexOfObject(this, 0);
2134 // 'this' was found in the array; remove it
2135 arr
->removeObject(arr_idx
);
2139 settings_iter
->release();
2142 IORecursiveLockUnlock(parent
->settingsCtrlLock
);
2147 void PMSettingObject::taggedRelease(const void *tag
, const int when
) const
2149 // We have n+1 retains - 1 per array that this PMSettingObject is a member
2150 // of, and 1 retain to ourself. When we get a release with n+1 retains
2151 // remaining, we go ahead and free ourselves, cleaning up array pointers
2154 super::taggedRelease(tag
, releaseAtCount
);
2159 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2162 #define super IOService
2164 OSDefineMetaClassAndStructors(IORootParent
, IOService
)
2166 // This array exactly parallels the state array for the root domain.
2167 // Power state changes initiated by a device can be vetoed by a client of the device, and
2168 // power state changes initiated by the parent of a device cannot be vetoed by a client of the device,
2169 // so when the root domain wants a power state change that cannot be vetoed (e.g. demand sleep), it asks
2170 // its parent to make the change. That is the reason for this complexity.
2172 static IOPMPowerState patriarchPowerStates
[number_of_power_states
] = {
2173 {1,0,0,0,0,0,0,0,0,0,0,0}, // off
2174 {1,0,RESTART_POWER
,0,0,0,0,0,0,0,0,0}, // reset
2175 {1,0,SLEEP_POWER
,0,0,0,0,0,0,0,0,0}, // sleep
2176 {1,0,DOZE_POWER
,0,0,0,0,0,0,0,0,0}, // doze
2177 {1,0,ON_POWER
,0,0,0,0,0,0,0,0,0} // running
2180 bool IORootParent::start ( IOService
* nub
)
2182 mostRecentChange
= ON_STATE
;
2185 registerPowerDriver(this,patriarchPowerStates
,number_of_power_states
);
2186 powerOverrideOnPriv();
2191 void IORootParent::shutDownSystem ( void )
2193 mostRecentChange
= OFF_STATE
;
2194 changePowerStateToPriv(OFF_STATE
);
2198 void IORootParent::restartSystem ( void )
2200 mostRecentChange
= RESTART_STATE
;
2201 changePowerStateToPriv(RESTART_STATE
);
2205 void IORootParent::sleepSystem ( void )
2207 mostRecentChange
= SLEEP_STATE
;
2208 changePowerStateToPriv(SLEEP_STATE
);
2212 void IORootParent::dozeSystem ( void )
2214 mostRecentChange
= DOZE_STATE
;
2215 changePowerStateToPriv(DOZE_STATE
);
2218 // Called in demand sleep when sleep discovered to be impossible after actually attaining that state.
2219 // This brings the parent to doze, which allows the root to step up from sleep to doze.
2221 // In idle sleep, do nothing because the parent is still on and the root can freely change state.
2223 void IORootParent::sleepToDoze ( void )
2225 if ( mostRecentChange
== SLEEP_STATE
) {
2226 changePowerStateToPriv(DOZE_STATE
);
2231 void IORootParent::wakeSystem ( void )
2233 mostRecentChange
= ON_STATE
;
2234 changePowerStateToPriv(ON_STATE
);
2237 IOReturn
IORootParent::changePowerStateToPriv ( unsigned long ordinal
)
2241 if( SLEEP_STATE
== ordinal
&& sleepSupportedPEFunction
)
2244 // Determine if the machine supports sleep, or must doze.
2245 ret
= getPlatform()->callPlatformFunction(
2246 sleepSupportedPEFunction
, false,
2247 NULL
, NULL
, NULL
, NULL
);
2249 // If the machine only supports doze, the callPlatformFunction call
2250 // boils down toIOPMrootDomain::setSleepSupported(kPCICantSleep),
2251 // otherwise nothing.
2254 return super::changePowerStateToPriv(ordinal
);