2 * Copyright (c) 1998-2006 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>
38 #include "IOPMWorkArbiter.h"
45 IOReturn
OSMetaClassSystemSleepOrWake( UInt32
);
48 extern const IORegistryPlane
* gIOPowerPlane
;
50 IOReturn
broadcast_aggressiveness ( OSObject
*, void *, void *, void *, void * );
51 static void sleepTimerExpired(thread_call_param_t
);
52 static void wakeupClamshellTimerExpired ( thread_call_param_t us
);
54 // "IOPMSetSleepSupported" callPlatformFunction name
55 static const OSSymbol
*sleepSupportedPEFunction
= NULL
;
57 #define kIOSleepSupportedKey "IOSleepSupported"
59 #define kRD_AllPowerSources (kIOPMSupportedOnAC \
60 | kIOPMSupportedOnBatt \
61 | kIOPMSupportedOnUPS)
63 #define number_of_power_states 5
65 #define RESTART_STATE 1
70 #define ON_POWER kIOPMPowerOn
71 #define RESTART_POWER kIOPMRestart
72 #define SLEEP_POWER kIOPMAuxPowerOn
73 #define DOZE_POWER kIOPMDoze
75 #define kLocalEvalClamshellCommand (1 << 15)
77 static IOPMPowerState ourPowerStates
[number_of_power_states
] = {
79 {1,0, 0, 0,0,0,0,0,0,0,0,0},
81 {1,kIOPMRestartCapability
, kIOPMRestart
, RESTART_POWER
,0,0,0,0,0,0,0,0},
83 {1,kIOPMSleepCapability
, kIOPMSleep
, SLEEP_POWER
,0,0,0,0,0,0,0,0},
85 {1,kIOPMDoze
, kIOPMDoze
, DOZE_POWER
,0,0,0,0,0,0,0,0},
87 {1,kIOPMPowerOn
, kIOPMPowerOn
, ON_POWER
,0,0,0,0,0,0,0,0},
90 static IOPMrootDomain
* gRootDomain
;
91 static UInt32 gSleepOrShutdownPending
= 0;
94 class PMSettingObject
: public OSObject
96 OSDeclareDefaultStructors(PMSettingObject
)
98 IOPMrootDomain
*parent
;
99 IOPMSettingControllerCallback func
;
102 uint32_t *publishedFeatureID
;
105 static PMSettingObject
*pmSettingObject(
106 IOPMrootDomain
*parent_arg
,
107 IOPMSettingControllerCallback handler_arg
,
108 OSObject
*target_arg
,
109 uintptr_t refcon_arg
,
110 uint32_t supportedPowerSources
,
111 const OSSymbol
*settings
[]);
113 void setPMSetting(const OSSymbol
*type
, OSObject
*obj
);
115 void taggedRelease(const void *tag
, const int when
) const;
121 #define super IOService
122 OSDefineMetaClassAndStructors(IOPMrootDomain
,IOService
)
126 IONotifier
* registerSleepWakeInterest(IOServiceInterestHandler handler
, void * self
, void * ref
)
128 return gRootDomain
->registerInterest( gIOGeneralInterest
, handler
, self
, ref
);
131 IONotifier
* registerPrioritySleepWakeInterest(IOServiceInterestHandler handler
, void * self
, void * ref
)
133 return gRootDomain
->registerInterest( gIOPriorityPowerStateInterest
, handler
, self
, ref
);
136 IOReturn
acknowledgeSleepWakeNotification(void * PMrefcon
)
138 return gRootDomain
->allowPowerChange ( (unsigned long)PMrefcon
);
141 IOReturn
vetoSleepWakeNotification(void * PMrefcon
)
143 return gRootDomain
->cancelPowerChange ( (unsigned long)PMrefcon
);
146 IOReturn
rootDomainRestart ( void )
148 return gRootDomain
->restartSystem();
151 IOReturn
rootDomainShutdown ( void )
153 return gRootDomain
->shutdownSystem();
156 void IOSystemShutdownNotification ( void )
158 IOCatalogue::disableExternalLinker();
159 for ( int i
= 0; i
< 100; i
++ )
161 if ( OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending
) ) break;
166 int sync_internal(void);
170 A device is always in the highest power state which satisfies its driver, its policy-maker, and any power domain
171 children it has, but within the constraint of the power state provided by its parent. The driver expresses its desire by
172 calling changePowerStateTo(), the policy-maker expresses its desire by calling changePowerStateToPriv(), and the children
173 express their desires by calling requestPowerDomainState().
175 The Root Power Domain owns the policy for idle and demand sleep and doze for the system. It is a power-managed IOService just
176 like the others in the system. It implements several power states which correspond to what we see as Sleep, Doze, etc.
178 The sleep/doze policy is as follows:
179 Sleep and Doze are prevented if the case is open so that nobody will think the machine is off and plug/unplug cards.
180 Sleep and Doze are prevented if the sleep timeout slider in the preferences panel is at zero.
181 The system cannot Sleep, but can Doze if some object in the tree is in a power state marked kIOPMPreventSystemSleep.
183 These three conditions are enforced using the "driver clamp" by calling changePowerStateTo(). For example, if the case is
184 opened, changePowerStateTo(ON_STATE) is called to hold the system on regardless of the desires of the children of the root or
185 the state of the other clamp.
187 Demand Sleep/Doze is initiated by pressing the front panel power button, closing the clamshell, or selecting the menu item.
188 In this case the root's parent actually initiates the power state change so that the root has no choice and does not give
189 applications the opportunity to veto the change.
191 Idle Sleep/Doze occurs if no objects in the tree are in a state marked kIOPMPreventIdleSleep. When this is true, the root's
192 children are not holding the root on, so it sets the "policy-maker clamp" by calling changePowerStateToPriv(ON_STATE)
193 to hold itself on until the sleep timer expires. This timer is set for the difference between the sleep timeout slider and
194 the larger of the display dim timeout slider and the disk spindown timeout slider in the Preferences panel. For example, if
195 the system is set to sleep after thirty idle minutes, and the display and disk are set to sleep after five idle minutes,
196 when there is no longer an object in the tree holding the system out of Idle Sleep (via kIOPMPreventIdleSleep), the root
197 sets its timer for 25 minutes (30 - 5). When the timer expires, it releases its clamp and now nothing is holding it awake,
200 Demand sleep is prevented when the system is booting. When preferences are transmitted by the loginwindow at the end of
201 boot, a flag is cleared, and this allows subsequent Demand Sleep.
203 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
204 a clamp, but sets a flag which is noticed before actually sleeping the kernel. If the flag is set, the root steps up
205 one power state from Sleep to Doze, and any objects in the tree for which this is relevent will act appropriately (USB and
206 ADB will turn on again so that they can wake the system out of Doze (keyboard/mouse activity will cause the Display Wrangler
210 // **********************************************************************************
212 IOPMrootDomain
* IOPMrootDomain::construct( void )
214 IOPMrootDomain
*root
;
216 root
= new IOPMrootDomain
;
223 // **********************************************************************************
225 static void disk_sync_callout(thread_call_param_t p0
, thread_call_param_t p1
)
227 IOService
*rootDomain
= (IOService
*) p0
;
228 unsigned long pmRef
= (unsigned long) p1
;
230 IOHibernateSystemSleep();
232 rootDomain
->allowPowerChange(pmRef
);
235 // **********************************************************************************
236 IOPMWorkArbiter
*IOPMrootDomain::getPMArbiter(void)
242 // **********************************************************************************
245 // We don't do much here. The real initialization occurs when the platform
246 // expert informs us we are the root.
247 // **********************************************************************************
249 #define kRootDomainSettingsCount 13
251 bool IOPMrootDomain::start ( IOService
* nub
)
253 OSIterator
*psIterator
;
254 OSDictionary
*tmpDict
;
255 const OSSymbol
*settingsArr
[kRootDomainSettingsCount
] =
257 OSSymbol::withCString(kIOPMSettingSleepOnPowerButtonKey
),
258 OSSymbol::withCString(kIOPMSettingAutoWakeSecondsKey
),
259 OSSymbol::withCString(kIOPMSettingAutoPowerSecondsKey
),
260 OSSymbol::withCString(kIOPMSettingAutoWakeCalendarKey
),
261 OSSymbol::withCString(kIOPMSettingAutoPowerCalendarKey
),
262 OSSymbol::withCString(kIOPMSettingDebugWakeRelativeKey
),
263 OSSymbol::withCString(kIOPMSettingDebugPowerRelativeKey
),
264 OSSymbol::withCString(kIOPMSettingWakeOnRingKey
),
265 OSSymbol::withCString(kIOPMSettingRestartOnPowerLossKey
),
266 OSSymbol::withCString(kIOPMSettingWakeOnClamshellKey
),
267 OSSymbol::withCString(kIOPMSettingWakeOnACChangeKey
),
268 OSSymbol::withCString(kIOPMSettingTimeZoneOffsetKey
),
269 OSSymbol::withCString(kIOPMSettingMobileMotionModuleKey
)
273 pmPowerStateQueue
= 0;
275 _reserved
= (ExpansionData
*)IOMalloc(sizeof(ExpansionData
));
276 if(!_reserved
) return false;
284 sleepSupportedPEFunction
= OSSymbol::withCString("IOPMSetSleepSupported");
286 setProperty(kIOSleepSupportedKey
,true);
289 sleepIsSupported
= true;
290 systemBooting
= true;
292 idleSleepPending
= false;
295 clamshellIsClosed
= false;
296 clamshellExists
= false;
297 ignoringClamshell
= true;
298 ignoringClamshellDuringWakeup
= false;
299 acAdaptorConnect
= true;
301 tmpDict
= OSDictionary::withCapacity(1);
302 setProperty(kRootDomainSupportedFeatures
, tmpDict
);
305 settingsCallbacks
= OSDictionary::withCapacity(1);
307 // Create a list of the valid PM settings that we'll relay to
308 // interested clients in setProperties() => setPMSetting()
309 allowedPMSettings
= OSArray::withObjects(
310 (const OSObject
**)settingsArr
,
311 kRootDomainSettingsCount
,
314 fPMSettingsDict
= OSDictionary::withCapacity(5);
316 pm_vars
->PMworkloop
= IOWorkLoop::workLoop();
317 pmPowerStateQueue
= IOPMPowerStateQueue::PMPowerStateQueue(this);
318 pm_vars
->PMworkloop
->addEventSource(pmPowerStateQueue
);
320 /* Initialize PM arbiter */
321 pmArbiter
= IOPMWorkArbiter::pmWorkArbiter(this);
322 arbiterWorkLoop
= IOWorkLoop::workLoop();
323 arbiterWorkLoop
->addEventSource(pmArbiter
);
325 featuresDictLock
= IOLockAlloc();
326 settingsCtrlLock
= IORecursiveLockAlloc();
328 extraSleepTimer
= thread_call_allocate(
329 (thread_call_func_t
)sleepTimerExpired
,
330 (thread_call_param_t
) this);
331 clamshellWakeupIgnore
= thread_call_allocate(
332 (thread_call_func_t
)wakeupClamshellTimerExpired
,
333 (thread_call_param_t
) this);
334 diskSyncCalloutEntry
= thread_call_allocate(
336 (thread_call_param_t
) this);
339 patriarch
= new IORootParent
;
341 patriarch
->attach(this);
342 patriarch
->start(this);
343 patriarch
->youAreRoot();
344 patriarch
->wakeSystem();
345 patriarch
->addPowerChild(this);
347 registerPowerDriver(this,ourPowerStates
,number_of_power_states
);
349 setPMRootDomain(this);
350 // set a clamp until we sleep
351 changePowerStateToPriv(ON_STATE
);
353 // install power change handler
354 registerPrioritySleepWakeInterest( &sysPowerDownHandler
, this, 0);
356 // Register for a notification when IODisplayWrangler is published
357 _displayWranglerNotifier
= addNotification(
358 gIOPublishNotification
, serviceMatching("IODisplayWrangler"),
359 &displayWranglerPublished
, this, 0);
361 // Battery location published - ApplePMU support only
362 _batteryPublishNotifier
= addNotification(
363 gIOPublishNotification
, serviceMatching("IOPMPowerSource"),
364 &batteryPublished
, this, this);
367 const OSSymbol
*ucClassName
= OSSymbol::withCStringNoCopy("RootDomainUserClient");
368 setProperty(gIOUserClientClassKey
, (OSObject
*) ucClassName
);
369 ucClassName
->release();
371 // IOBacklightDisplay can take a long time to load at boot, or it may
372 // not load at all if you're booting with clamshell closed. We publish
373 // 'DisplayDims' here redundantly to get it published early and at all.
374 psIterator
= getMatchingServices( serviceMatching("IOPMPowerSource") );
375 if( psIterator
&& psIterator
->getNextObject() )
377 // There's at least one battery on the system, so we publish
378 // 'DisplayDims' support for the LCD.
379 publishFeature("DisplayDims");
382 psIterator
->release();
385 IOHibernateSystemInit(this);
387 registerService(); // let clients find us
392 // **********************************************************************************
395 // Receive a setProperty call
396 // The "System Boot" property means the system is completely booted.
397 // **********************************************************************************
398 IOReturn
IOPMrootDomain::setProperties ( OSObject
*props_obj
)
400 IOReturn return_value
= kIOReturnSuccess
;
401 OSDictionary
*dict
= OSDynamicCast(OSDictionary
, props_obj
);
409 const OSSymbol
*boot_complete_string
=
410 OSSymbol::withCString("System Boot Complete");
411 const OSSymbol
*sys_shutdown_string
=
412 OSSymbol::withCString("System Shutdown");
413 const OSSymbol
*stall_halt_string
=
414 OSSymbol::withCString("StallSystemAtHalt");
415 const OSSymbol
*hibernatemode_string
=
416 OSSymbol::withCString(kIOHibernateModeKey
);
417 const OSSymbol
*hibernatefile_string
=
418 OSSymbol::withCString(kIOHibernateFileKey
);
419 const OSSymbol
*hibernatefreeratio_string
=
420 OSSymbol::withCString(kIOHibernateFreeRatioKey
);
421 const OSSymbol
*hibernatefreetime_string
=
422 OSSymbol::withCString(kIOHibernateFreeTimeKey
);
426 return_value
= kIOReturnBadArgument
;
431 && boot_complete_string
432 && dict
->getObject(boot_complete_string
))
434 systemBooting
= false;
437 // If lid is closed, re-send lid closed notification
438 // now that booting is complete.
439 if( clamshellIsClosed
)
441 this->receivePowerNotification(kLocalEvalClamshellCommand
);
445 if( sys_shutdown_string
446 && (b
= OSDynamicCast(OSBoolean
, dict
->getObject(sys_shutdown_string
))))
449 if(kOSBooleanTrue
== b
)
451 /* We set systemShutdown = true during shutdown
452 to prevent sleep at unexpected times while loginwindow is trying
453 to shutdown apps and while the OS is trying to transition to
456 Set to true during shutdown, as soon as loginwindow shows
457 the "shutdown countdown dialog", through individual app
458 termination, and through black screen kernel shutdown.
460 kprintf("systemShutdown true\n");
461 systemShutdown
= true;
464 A shutdown was initiated, but then the shutdown
465 was cancelled, clearing systemShutdown to false here.
467 kprintf("systemShutdown false\n");
468 systemShutdown
= false;
472 if( stall_halt_string
473 && (b
= OSDynamicCast(OSBoolean
, dict
->getObject(stall_halt_string
))) )
475 setProperty(stall_halt_string
, b
);
478 if ( hibernatemode_string
479 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(hibernatemode_string
))))
481 setProperty(hibernatemode_string
, n
);
483 if ( hibernatefreeratio_string
484 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(hibernatefreeratio_string
))))
486 setProperty(hibernatefreeratio_string
, n
);
488 if ( hibernatefreetime_string
489 && (n
= OSDynamicCast(OSNumber
, dict
->getObject(hibernatefreetime_string
))))
491 setProperty(hibernatefreetime_string
, n
);
493 if ( hibernatefile_string
494 && (str
= OSDynamicCast(OSString
, dict
->getObject(hibernatefile_string
))))
496 setProperty(hibernatefile_string
, str
);
499 // Relay our allowed PM settings onto our registered PM clients
500 for(i
= 0; i
< allowedPMSettings
->getCount(); i
++) {
502 type
= (OSSymbol
*)allowedPMSettings
->getObject(i
);
505 obj
= dict
->getObject(type
);
508 return_value
= setPMSetting(type
, obj
);
510 if(kIOReturnSuccess
!= return_value
) goto exit
;
514 if(boot_complete_string
) boot_complete_string
->release();
515 if(stall_halt_string
) stall_halt_string
->release();
520 //*********************************************************************************
523 // Power Managment is informing us that we are the root power domain.
524 // We know we are not the root however, since we have just instantiated a parent
525 // for ourselves and made it the root. We override this method so it will have
527 //*********************************************************************************
528 IOReturn
IOPMrootDomain::youAreRoot ( void )
533 // **********************************************************************************
537 // **********************************************************************************
538 void IOPMrootDomain::command_received ( void * w
, void * x
, void * y
, void * z
)
540 super::command_received(w
,x
,y
,z
);
544 // **********************************************************************************
545 // broadcast_aggressiveness
547 // **********************************************************************************
548 IOReturn
broadcast_aggressiveness ( OSObject
* root
, void * x
, void * y
, void *, void * )
550 ((IOPMrootDomain
*)root
)->broadcast_it((unsigned long)x
,(unsigned long)y
);
555 // **********************************************************************************
558 // We are behind the command gate to broadcast an aggressiveness factor. We let the
559 // superclass do it, but we need to snoop on factors that affect idle sleep.
560 // **********************************************************************************
561 void IOPMrootDomain::broadcast_it (unsigned long type
, unsigned long value
)
563 super::setAggressiveness(type
,value
);
565 // Save user's spin down timer to restore after we replace it for idle sleep
566 if( type
== kPMMinutesToSpinDown
) user_spindown
= value
;
568 // Use longestNonSleepSlider to calculate dimming adjust idle sleep timer
569 longestNonSleepSlider
= pm_vars
->current_aggressiveness_values
[kPMMinutesToDim
];
572 if ( type
== kPMMinutesToSleep
) {
573 if ( (sleepSlider
== 0) && (value
!= 0) ) {
575 // idle sleep is now enabled, maybe sleep now
579 if ( sleepSlider
== 0 ) {
580 // idle sleep is now disabled
582 // make sure we're powered
583 patriarch
->wakeSystem();
586 if ( sleepSlider
> longestNonSleepSlider
) {
587 extraSleepDelay
= sleepSlider
- longestNonSleepSlider
;
595 // **********************************************************************************
598 // **********************************************************************************
599 static void sleepTimerExpired ( thread_call_param_t us
)
601 ((IOPMrootDomain
*)us
)->handleSleepTimerExpiration();
605 static void wakeupClamshellTimerExpired ( thread_call_param_t us
)
607 ((IOPMrootDomain
*)us
)->stopIgnoringClamshellEventsDuringWakeup();
611 // **********************************************************************************
612 // handleSleepTimerExpiration
614 // The time between the sleep idle timeout and the next longest one has elapsed.
615 // It's time to sleep. Start that by removing the clamp that's holding us awake.
616 // **********************************************************************************
617 void IOPMrootDomain::handleSleepTimerExpiration ( void )
619 // accelerate disk spin down if spin down timer is non-zero (zero = never spin down)
620 if(0 != user_spindown
)
621 setQuickSpinDownTimeout();
628 void IOPMrootDomain::stopIgnoringClamshellEventsDuringWakeup(void)
630 // Allow clamshell-induced sleep now
631 ignoringClamshellDuringWakeup
= false;
633 // Re-send clamshell event, in case it causes a sleep
634 if(clamshellIsClosed
)
635 this->receivePowerNotification( kLocalEvalClamshellCommand
);
638 //*********************************************************************************
641 // Some aggressiveness factor has changed. We broadcast it to the hierarchy while on
642 // the Power Mangement workloop thread. This enables objects in the
643 // hierarchy to successfully alter their idle timers, which are all on the
645 //*********************************************************************************
647 static int pmsallsetup
= 0;
649 IOReturn
IOPMrootDomain::setAggressiveness ( unsigned long type
, unsigned long newLevel
)
652 if(pmsExperimental
& 3) kprintf("setAggressiveness: type = %08X, newlevel = %08X\n", type
, newLevel
);
653 if(pmsExperimental
& 1) { /* Is experimental mode enabled? */
654 if(pmsInstalled
&& (type
== kPMSetProcessorSpeed
)) { /* We want to look at all processor speed changes if stepper is installed */
655 if(pmsallsetup
) return kIOReturnSuccess
; /* If already running, just eat this */
656 kprintf("setAggressiveness: starting stepper...\n");
657 pmsallsetup
= 1; /* Remember we did this */
659 pmsStart(); /* Get it all started up... */
660 return kIOReturnSuccess
; /* Leave now... */
665 if ( pm_vars
->PMcommandGate
) {
666 pm_vars
->PMcommandGate
->runAction(broadcast_aggressiveness
,(void *)type
,(void *)newLevel
);
669 return kIOReturnSuccess
;
673 // **********************************************************************************
676 // **********************************************************************************
677 IOReturn
IOPMrootDomain::sleepSystem ( void )
680 kprintf("Preventing system sleep on grounds of systemShutdown.\n");
683 if ( !systemBooting
&& !systemShutdown
&& allowSleep
) {
684 if ( !sleepIsSupported
)
685 setSleepSupported( kPCICantSleep
);
687 patriarch
->sleepSystem();
688 return kIOReturnSuccess
;
690 return kIOReturnError
;
694 // **********************************************************************************
697 // **********************************************************************************
698 IOReturn
IOPMrootDomain::shutdownSystem ( void )
700 //patriarch->shutDownSystem();
701 return kIOReturnUnsupported
;
705 // **********************************************************************************
708 // **********************************************************************************
709 IOReturn
IOPMrootDomain::restartSystem ( void )
711 //patriarch->restartSystem();
712 return kIOReturnUnsupported
;
716 // **********************************************************************************
719 // This overrides powerChangeDone in IOService.
721 // Finder sleep and idle sleep move us from the ON state to the SLEEP_STATE.
723 // If we just finished going to the SLEEP_STATE, and the platform is capable of true sleep,
724 // sleep the kernel. Otherwise switch up to the DOZE_STATE which will keep almost
725 // everything as off as it can get.
727 // **********************************************************************************
728 void IOPMrootDomain::powerChangeDone ( unsigned long previousState
)
730 OSNumber
* propertyPtr
;
731 unsigned short theProperty
;
732 AbsoluteTime deadline
;
734 switch ( pm_vars
->myCurrentState
) {
736 if ( canSleep
&& sleepIsSupported
)
738 // re-enable this timer for next sleep
739 idleSleepPending
= false;
741 IOLog("System %sSleep\n", gIOHibernateState
? "Safe" : "");
743 IOHibernateSystemHasSlept();
745 pm_vars
->thePlatform
->sleepKernel();
747 // The CPU(s) are off at this point. When they're awakened by CPU interrupt,
748 // code will resume execution here.
750 // Now we're waking...
751 IOHibernateSystemWake();
753 // stay awake for at least 30 seconds
754 clock_interval_to_deadline(30, kSecondScale
, &deadline
);
755 thread_call_enter_delayed(extraSleepTimer
, deadline
);
756 // this gets turned off when we sleep again
757 idleSleepPending
= true;
759 // Ignore closed clamshell during wakeup and for a few seconds
760 // after wakeup is complete
761 ignoringClamshellDuringWakeup
= true;
763 // sleep transition complete
764 gSleepOrShutdownPending
= 0;
766 // trip the reset of the calendar clock
767 clock_wakeup_calendar();
770 patriarch
->wakeSystem();
772 // early stage wake notification
773 tellClients(kIOMessageSystemWillPowerOn
);
775 // tell the tree we're waking
776 IOLog("System %sWake\n", gIOHibernateState
? "SafeSleep " : "");
779 // Allow drivers to request extra processing time before clamshell
780 // sleep if kIOREMSleepEnabledKey is present.
781 // Ignore clamshell events for at least 5 seconds
782 if(getProperty(kIOREMSleepEnabledKey
)) {
783 // clamshellWakeupIgnore callout clears ignoreClamshellDuringWakeup bit
784 clock_interval_to_deadline(5, kSecondScale
, &deadline
);
785 if(clamshellWakeupIgnore
) {
786 thread_call_enter_delayed(clamshellWakeupIgnore
, deadline
);
788 } else ignoringClamshellDuringWakeup
= false;
790 // Find out what woke us
791 propertyPtr
= OSDynamicCast(OSNumber
,getProperty("WakeEvent"));
793 theProperty
= propertyPtr
->unsigned16BitValue();
794 IOLog("Wake event %04x\n",theProperty
);
795 if ( (theProperty
& 0x0008) || //lid
796 (theProperty
& 0x0800) || // front panel button
797 (theProperty
& 0x0020) || // external keyboard
798 (theProperty
& 0x0001) ) { // internal keyboard
799 // We've identified the wakeup event as UI driven
803 // Since we can't identify the wakeup event, treat it as UI activity
807 // Wake for thirty seconds
808 changePowerStateToPriv(ON_STATE
);
809 powerOverrideOffPriv();
811 // allow us to step up a power state
812 patriarch
->sleepToDoze();
814 changePowerStateToPriv(DOZE_STATE
);
819 if ( previousState
!= DOZE_STATE
)
821 IOLog("System Doze\n");
823 // re-enable this timer for next sleep
824 idleSleepPending
= false;
825 gSleepOrShutdownPending
= 0;
829 IOLog("System Restart\n");
830 PEHaltRestart(kPERestartCPU
);
834 IOLog("System Halt\n");
835 PEHaltRestart(kPEHaltCPU
);
841 // **********************************************************************************
844 // The Display Wrangler calls here when it switches to its highest state. If the
845 // system is currently dozing, allow it to wake by making sure the parent is
847 // **********************************************************************************
848 void IOPMrootDomain::wakeFromDoze( void )
850 if ( pm_vars
->myCurrentState
== DOZE_STATE
)
852 // Reset sleep support till next sleep attempt.
853 // A machine's support of sleep vs. doze can change over the course of
854 // a running system, so we recalculate it before every sleep.
855 setSleepSupported(0);
857 powerOverrideOffPriv();
859 // early wake notification
860 tellClients(kIOMessageSystemWillPowerOn
);
862 // allow us to wake if children so desire
863 patriarch
->wakeSystem();
868 // *****************************************************************************
871 // Adds a new feature to the supported features dictionary
874 // *****************************************************************************
875 void IOPMrootDomain::publishFeature( const char * feature
)
877 publishFeature(feature
, kIOPMSupportedOnAC
878 | kIOPMSupportedOnBatt
879 | kIOPMSupportedOnUPS
,
885 // *****************************************************************************
886 // publishFeature (with supported power source specified)
888 // Adds a new feature to the supported features dictionary
891 // *****************************************************************************
892 void IOPMrootDomain::publishFeature(
894 uint32_t supportedWhere
,
895 uint32_t *uniqueFeatureID
)
897 static uint16_t next_feature_id
= 500;
899 OSNumber
*new_feature_data
= NULL
;
900 OSNumber
*existing_feature
= NULL
;
901 OSArray
*existing_feature_arr
= NULL
;
902 OSObject
*osObj
= NULL
;
903 uint32_t feature_value
= 0;
905 supportedWhere
&= kRD_AllPowerSources
; // mask off any craziness!
907 if(!supportedWhere
) {
908 // Feature isn't supported anywhere!
912 if(next_feature_id
> 5000) {
913 // Far, far too many features!
917 if(featuresDictLock
) IOLockLock(featuresDictLock
);
919 OSDictionary
*features
=
920 (OSDictionary
*) getProperty(kRootDomainSupportedFeatures
);
922 // Create new features dict if necessary
923 if ( features
&& OSDynamicCast(OSDictionary
, features
)) {
924 features
= OSDictionary::withDictionary(features
);
926 features
= OSDictionary::withCapacity(1);
929 // Create OSNumber to track new feature
931 next_feature_id
+= 1;
932 if( uniqueFeatureID
) {
933 // We don't really mind if the calling kext didn't give us a place
934 // to stash their unique id. Many kexts don't plan to unload, and thus
935 // have no need to remove themselves later.
936 *uniqueFeatureID
= next_feature_id
;
939 feature_value
= supportedWhere
+ (next_feature_id
<< 16);
940 new_feature_data
= OSNumber::withNumber(
941 (unsigned long long)feature_value
, 32);
943 // Does features object already exist?
944 if( (osObj
= features
->getObject(feature
)) )
946 if(( existing_feature
= OSDynamicCast(OSNumber
, osObj
) ))
948 // We need to create an OSArray to hold the now 2 elements.
949 existing_feature_arr
= OSArray::withObjects(
950 (const OSObject
**)&existing_feature
, 1, 2);
951 existing_feature_arr
->setObject(new_feature_data
);
952 features
->setObject(feature
, existing_feature_arr
);
953 } else if(( existing_feature_arr
= OSDynamicCast(OSArray
, osObj
) ))
955 // Add object to existing array
956 existing_feature_arr
->setObject(new_feature_data
);
959 // The easy case: no previously existing features listed. We simply
960 // set the OSNumber at key 'feature' and we're on our way.
961 features
->setObject(feature
, new_feature_data
);
964 new_feature_data
->release();
966 setProperty(kRootDomainSupportedFeatures
, features
);
970 // Notify EnergySaver and all those in user space so they might
971 // re-populate their feature specific UI
972 messageClients(kIOPMMessageFeatureChange
, this);
974 if(featuresDictLock
) IOLockUnlock(featuresDictLock
);
977 // *****************************************************************************
978 // removePublishedFeature
980 // Removes previously published feature
983 // *****************************************************************************
984 IOReturn
IOPMrootDomain::removePublishedFeature( uint32_t removeFeatureID
)
986 IOReturn ret
= kIOReturnError
;
987 uint32_t feature_value
= 0;
988 uint16_t feature_id
= 0;
989 bool madeAChange
= false;
991 OSSymbol
*dictKey
= NULL
;
992 OSCollectionIterator
*dictIterator
= NULL
;
993 OSArray
*arrayMember
= NULL
;
994 OSNumber
*numberMember
= NULL
;
995 OSObject
*osObj
= NULL
;
996 OSNumber
*osNum
= NULL
;
998 if(featuresDictLock
) IOLockLock(featuresDictLock
);
1000 OSDictionary
*features
=
1001 (OSDictionary
*) getProperty(kRootDomainSupportedFeatures
);
1003 if ( features
&& OSDynamicCast(OSDictionary
, features
) )
1005 // Any modifications to the dictionary are made to the copy to prevent
1006 // races & crashes with userland clients. Dictionary updated
1007 // automically later.
1008 features
= OSDictionary::withDictionary(features
);
1011 ret
= kIOReturnNotFound
;
1015 // We iterate 'features' dictionary looking for an entry tagged
1016 // with 'removeFeatureID'. If found, we remove it from our tracking
1017 // structures and notify the OS via a general interest message.
1019 dictIterator
= OSCollectionIterator::withCollection(features
);
1024 while( (dictKey
= OSDynamicCast(OSSymbol
, dictIterator
->getNextObject())) )
1026 osObj
= features
->getObject(dictKey
);
1028 // Each Feature is either tracked by an OSNumber
1029 if( osObj
&& (numberMember
= OSDynamicCast(OSNumber
, osObj
)) )
1031 feature_value
= numberMember
->unsigned32BitValue();
1032 feature_id
= (uint16_t)(feature_value
>> 16);
1034 if( feature_id
== (uint16_t)removeFeatureID
)
1037 features
->removeObject(dictKey
);
1042 // Or tracked by an OSArray of OSNumbers
1043 } else if( osObj
&& (arrayMember
= OSDynamicCast(OSArray
, osObj
)) )
1045 unsigned int arrayCount
= arrayMember
->getCount();
1047 for(unsigned int i
=0; i
<arrayCount
; i
++)
1049 osNum
= OSDynamicCast(OSNumber
, arrayMember
->getObject(i
));
1054 feature_value
= osNum
->unsigned32BitValue();
1055 feature_id
= (uint16_t)(feature_value
>> 16);
1057 if( feature_id
== (uint16_t)removeFeatureID
)
1060 if( 1 == arrayCount
) {
1061 // If the array only contains one element, remove
1063 features
->removeObject(dictKey
);
1065 // Otherwise just remove the element in question.
1066 arrayMember
->removeObject(i
);
1077 dictIterator
->release();
1081 ret
= kIOReturnSuccess
;
1083 setProperty(kRootDomainSupportedFeatures
, features
);
1085 // Notify EnergySaver and all those in user space so they might
1086 // re-populate their feature specific UI
1087 messageClients(kIOPMMessageFeatureChange
, this);
1089 ret
= kIOReturnNotFound
;
1093 if(features
) features
->release();
1094 if(featuresDictLock
) IOLockUnlock(featuresDictLock
);
1099 // **********************************************************************************
1102 // Enqueues unidle event to be performed later in a serialized context.
1104 // **********************************************************************************
1105 void IOPMrootDomain::unIdleDevice( IOService
*theDevice
, unsigned long theState
)
1107 if(pmPowerStateQueue
)
1108 pmPowerStateQueue
->unIdleOccurred(theDevice
, theState
);
1111 // **********************************************************************************
1112 // announcePowerSourceChange
1114 // Notifies "interested parties" that the batteries have changed state
1116 // **********************************************************************************
1117 void IOPMrootDomain::announcePowerSourceChange( void )
1119 IORegistryEntry
*_batteryRegEntry
= (IORegistryEntry
*) getProperty("BatteryEntry");
1121 // (if possible) re-publish power source state under IOPMrootDomain;
1122 // only do so if the battery controller publishes an IOResource
1123 // defining battery location. Called from ApplePMU battery driver.
1125 if(_batteryRegEntry
)
1128 batt_info
= (OSArray
*) _batteryRegEntry
->getProperty(kIOBatteryInfoKey
);
1130 setProperty(kIOBatteryInfoKey
, batt_info
);
1136 // *****************************************************************************
1137 // setPMSetting (private)
1139 // Internal helper to relay PM settings changes from user space to individual
1140 // drivers. Should be called only by IOPMrootDomain::setProperties.
1142 // *****************************************************************************
1143 IOReturn
IOPMrootDomain::setPMSetting(
1144 const OSSymbol
*type
,
1147 OSArray
*arr
= NULL
;
1148 PMSettingObject
*p_obj
= NULL
;
1152 if(NULL
== type
) return kIOReturnBadArgument
;
1154 IORecursiveLockLock(settingsCtrlLock
);
1156 fPMSettingsDict
->setObject(type
, obj
);
1158 arr
= (OSArray
*)settingsCallbacks
->getObject(type
);
1159 if(NULL
== arr
) goto exit
;
1160 count
= arr
->getCount();
1161 for(i
=0; i
<count
; i
++) {
1162 p_obj
= (PMSettingObject
*)OSDynamicCast(PMSettingObject
, arr
->getObject(i
));
1163 if(p_obj
) p_obj
->setPMSetting(type
, obj
);
1167 IORecursiveLockUnlock(settingsCtrlLock
);
1168 return kIOReturnSuccess
;
1171 // *****************************************************************************
1172 // copyPMSetting (public)
1174 // Allows kexts to safely read setting values, without being subscribed to
1177 // *****************************************************************************
1178 OSObject
* IOPMrootDomain::copyPMSetting(
1179 OSSymbol
*whichSetting
)
1181 OSObject
*obj
= NULL
;
1183 if(!whichSetting
) return NULL
;
1185 IORecursiveLockLock(settingsCtrlLock
);
1186 obj
= fPMSettingsDict
->getObject(whichSetting
);
1190 IORecursiveLockUnlock(settingsCtrlLock
);
1195 // *****************************************************************************
1196 // registerPMSettingController (public)
1198 // direct wrapper to registerPMSettingController with uint32_t power source arg
1199 // *****************************************************************************
1200 IOReturn
IOPMrootDomain::registerPMSettingController(
1201 const OSSymbol
* settings
[],
1202 IOPMSettingControllerCallback func
,
1207 return registerPMSettingController(
1209 (kIOPMSupportedOnAC
| kIOPMSupportedOnBatt
| kIOPMSupportedOnUPS
),
1210 func
, target
, refcon
, handle
);
1213 // *****************************************************************************
1214 // registerPMSettingController (public)
1216 // Kexts may register for notifications when a particular setting is changed.
1217 // A list of settings is available in IOPM.h.
1219 // * settings - An OSArray containing OSSymbols. Caller should populate this
1220 // array with a list of settings caller wants notifications from.
1221 // * func - A C function callback of the type IOPMSettingControllerCallback
1222 // * target - caller may provide an OSObject *, which PM will pass as an
1223 // target to calls to "func"
1224 // * refcon - caller may provide an void *, which PM will pass as an
1225 // argument to calls to "func"
1226 // * handle - This is a return argument. We will populate this pointer upon
1227 // call success. Hold onto this and pass this argument to
1228 // IOPMrootDomain::deRegisterPMSettingCallback when unloading your kext
1230 // kIOReturnSuccess on success
1231 // *****************************************************************************
1232 IOReturn
IOPMrootDomain::registerPMSettingController(
1233 const OSSymbol
* settings
[],
1234 uint32_t supportedPowerSources
,
1235 IOPMSettingControllerCallback func
,
1240 PMSettingObject
*pmso
= NULL
;
1241 OSArray
*list
= NULL
;
1242 IOReturn ret
= kIOReturnSuccess
;
1245 if( NULL
== settings
||
1249 return kIOReturnBadArgument
;
1253 pmso
= PMSettingObject::pmSettingObject(
1254 (IOPMrootDomain
*)this, func
, target
,
1255 refcon
, supportedPowerSources
, settings
);
1258 ret
= kIOReturnInternalError
;
1259 goto bail_no_unlock
;
1262 IORecursiveLockLock(settingsCtrlLock
);
1263 for(i
=0; settings
[i
]; i
++)
1265 list
= (OSArray
*)settingsCallbacks
->getObject(settings
[i
]);
1267 // New array of callbacks for this setting
1268 list
= OSArray::withCapacity(1);
1269 settingsCallbacks
->setObject(settings
[i
], list
);
1273 // Add caller to the callback list
1274 list
->setObject(pmso
);
1277 ret
= kIOReturnSuccess
;
1279 // Track this instance by its OSData ptr from now on
1282 IORecursiveLockUnlock(settingsCtrlLock
);
1285 if(kIOReturnSuccess
!= ret
)
1287 // Error return case
1288 if(pmso
) pmso
->release();
1289 if(handle
) *handle
= NULL
;
1294 //******************************************************************************
1295 // sleepOnClamshellClosed
1297 // contains the logic to determine if the system should sleep when the clamshell
1299 //******************************************************************************
1301 bool IOPMrootDomain::shouldSleepOnClamshellClosed ( void )
1303 return ( !ignoringClamshell
1304 && !ignoringClamshellDuringWakeup
1305 && !(desktopMode
&& acAdaptorConnect
) );
1308 void IOPMrootDomain::sendClientClamshellNotification ( void )
1310 /* Only broadcast clamshell alert if clamshell exists. */
1311 if(!clamshellExists
)
1314 setProperty(kAppleClamshellStateKey
,
1315 clamshellIsClosed
? kOSBooleanTrue
: kOSBooleanFalse
);
1317 setProperty(kAppleClamshellCausesSleepKey
,
1318 shouldSleepOnClamshellClosed() ? kOSBooleanTrue
: kOSBooleanFalse
);
1321 /* Argument to message is a bitfield of
1322 * ( kClamshellStateBit | kClamshellSleepBit )
1323 * Carry on the clamshell state change notification from an
1324 * independent thread.
1326 pmArbiter
->clamshellStateChangeOccurred(
1327 (uint32_t) ( (clamshellIsClosed
? kClamshellStateBit
: 0)
1328 | ( shouldSleepOnClamshellClosed() ? kClamshellSleepBit
: 0)));
1331 //******************************************************************************
1332 // receivePowerNotification
1334 // The power controller is notifying us of a hardware-related power management
1335 // event that we must handle. This is a result of an 'environment' interrupt from
1336 // the power mgt micro.
1337 //******************************************************************************
1339 IOReturn
IOPMrootDomain::receivePowerNotification (UInt32 msg
)
1341 bool eval_clamshell
= false;
1344 * Local (IOPMrootDomain only) eval clamshell command
1346 if (msg
& kLocalEvalClamshellCommand
)
1348 eval_clamshell
= true;
1354 if (msg
& kIOPMOverTemp
)
1356 IOLog("PowerManagement emergency overtemp signal. Going to sleep!");
1357 (void) sleepSystem ();
1361 * PMU Processor Speed Change
1363 if (msg
& kIOPMProcessorSpeedChange
)
1365 IOService
*pmu
= waitForService(serviceMatching("ApplePMU"));
1366 pmu
->callPlatformFunction("prepareForSleep", false, 0, 0, 0, 0);
1367 pm_vars
->thePlatform
->sleepKernel();
1368 pmu
->callPlatformFunction("recoverFromSleep", false, 0, 0, 0, 0);
1374 if (msg
& kIOPMSleepNow
)
1376 (void) sleepSystem ();
1382 if (msg
& kIOPMPowerEmergency
)
1384 (void) sleepSystem ();
1391 if (msg
& kIOPMClamshellOpened
)
1393 // Received clamshel open message from clamshell controlling driver
1394 // Update our internal state and tell general interest clients
1395 clamshellIsClosed
= false;
1396 clamshellExists
= true;
1398 sendClientClamshellNotification();
1403 * Send the clamshell interest notification since the lid is closing.
1405 if (msg
& kIOPMClamshellClosed
)
1407 // Received clamshel open message from clamshell controlling driver
1408 // Update our internal state and tell general interest clients
1409 clamshellIsClosed
= true;
1410 clamshellExists
= true;
1412 sendClientClamshellNotification();
1414 // And set eval_clamshell = so we can attempt
1415 eval_clamshell
= true;
1419 * Set Desktop mode (sent from graphics)
1421 * -> reevaluate lid state
1423 if (msg
& kIOPMSetDesktopMode
)
1425 desktopMode
= (0 != (msg
& kIOPMSetValue
));
1426 msg
&= ~(kIOPMSetDesktopMode
| kIOPMSetValue
);
1428 sendClientClamshellNotification();
1430 // Re-evaluate the lid state
1431 if( clamshellIsClosed
)
1433 eval_clamshell
= true;
1438 * AC Adaptor connected
1440 * -> reevaluate lid state
1442 if (msg
& kIOPMSetACAdaptorConnected
)
1444 acAdaptorConnect
= (0 != (msg
& kIOPMSetValue
));
1445 msg
&= ~(kIOPMSetACAdaptorConnected
| kIOPMSetValue
);
1447 sendClientClamshellNotification();
1449 // Re-evaluate the lid state
1450 if( clamshellIsClosed
)
1452 eval_clamshell
= true;
1458 * Enable Clamshell (external display disappear)
1460 * -> reevaluate lid state
1462 if (msg
& kIOPMEnableClamshell
)
1464 // Re-evaluate the lid state
1465 // System should sleep on external display disappearance
1466 // in lid closed operation.
1467 if( clamshellIsClosed
&& (true == ignoringClamshell
) )
1469 eval_clamshell
= true;
1472 ignoringClamshell
= false;
1474 sendClientClamshellNotification();
1478 * Disable Clamshell (external display appeared)
1479 * We don't bother re-evaluating clamshell state. If the system is awake,
1480 * the lid is probably open.
1482 if (msg
& kIOPMDisableClamshell
)
1484 ignoringClamshell
= true;
1486 sendClientClamshellNotification();
1490 * Evaluate clamshell and SLEEP if appropiate
1492 if ( eval_clamshell
&& shouldSleepOnClamshellClosed() )
1503 if (msg
& kIOPMPowerButton
)
1505 // toggle state of sleep/wake
1507 if ( pm_vars
->myCurrentState
== DOZE_STATE
)
1509 // yes, tell the tree we're waking
1511 // wake the Display Wrangler
1515 OSString
*pbs
= OSString::withCString("DisablePowerButtonSleep");
1516 // Check that power button sleep is enabled
1518 if( kOSBooleanTrue
!= getProperty(pbs
))
1528 if ( (msg
& kIOPMAllowSleep
) && !allowSleep
)
1538 if (msg
& kIOPMPreventSleep
) {
1541 if ( pm_vars
->myCurrentState
== DOZE_STATE
) {
1542 // yes, tell the tree we're waking
1545 // wake the Display Wrangler
1549 // make sure we have power to clamp
1550 patriarch
->wakeSystem();
1558 //*********************************************************************************
1561 //*********************************************************************************
1563 void IOPMrootDomain::setSleepSupported( IOOptionBits flags
)
1565 if ( flags
& kPCICantSleep
)
1570 platformSleepSupport
= flags
;
1573 setProperty(kIOSleepSupportedKey
, canSleep
);
1577 //*********************************************************************************
1578 // requestPowerDomainState
1580 // The root domain intercepts this call to the superclass.
1582 // If the clamp bit is not set in the desire, then the child doesn't need the power
1583 // state it's requesting; it just wants it. The root ignores desires but not needs.
1584 // If the clamp bit is not set, the root takes it that the child can tolerate no
1585 // power and interprets the request accordingly. If all children can thus tolerate
1586 // no power, we are on our way to idle sleep.
1587 //*********************************************************************************
1589 IOReturn
IOPMrootDomain::requestPowerDomainState ( IOPMPowerFlags desiredState
, IOPowerConnection
* whichChild
, unsigned long specification
)
1593 IOPowerConnection
*connection
;
1594 unsigned long powerRequestFlag
= 0;
1595 IOPMPowerFlags editedDesire
= desiredState
;
1597 // if they don't really need it, they don't get it
1598 if ( !(desiredState
& kIOPMPreventIdleSleep
) ) {
1603 IOLockLock(pm_vars
->childLock
);
1605 // recompute sleepIsSupported and see if all children are asleep
1606 iter
= getChildIterator(gIOPowerPlane
);
1607 sleepIsSupported
= true;
1610 while ( (next
= iter
->getNextObject()) )
1612 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1614 if ( connection
== whichChild
)
1616 powerRequestFlag
+= editedDesire
;
1617 if ( desiredState
& kIOPMPreventSystemSleep
)
1619 sleepIsSupported
= false;
1622 powerRequestFlag
+= connection
->getDesiredDomainState();
1623 if ( connection
->getPreventSystemSleepFlag() )
1625 sleepIsSupported
= false;
1633 if ( (extraSleepDelay
== 0) && (powerRequestFlag
== 0) )
1638 // this may put the system to sleep
1641 IOLockUnlock(pm_vars
->childLock
);
1643 editedDesire
|= desiredState
& kIOPMPreventSystemSleep
;
1645 return super::requestPowerDomainState(editedDesire
,whichChild
,specification
);
1649 //*********************************************************************************
1650 // getSleepSupported
1652 //*********************************************************************************
1654 IOOptionBits
IOPMrootDomain::getSleepSupported( void )
1656 return( platformSleepSupport
);
1660 //*********************************************************************************
1663 // We override the superclass implementation so we can send a different message
1664 // type to the client or application being notified.
1665 //*********************************************************************************
1667 bool IOPMrootDomain::tellChangeDown ( unsigned long stateNum
)
1669 switch ( stateNum
) {
1673 // Direct callout into OSMetaClass so it can disable kmod unloads
1674 // during sleep/wake to prevent deadlocks.
1675 OSMetaClassSystemSleepOrWake( kIOMessageSystemWillSleep
);
1677 return super::tellClientsWithResponse(kIOMessageSystemWillSleep
);
1679 // Unsupported shutdown ordering hack on RESTART only
1680 // For Bluetooth and USB (4368327)
1681 super::tellClients(iokit_common_msg(0x759));
1683 return super::tellClientsWithResponse(kIOMessageSystemWillRestart
);
1685 // Unsupported shutdown ordering hack on SHUTDOWN only
1686 // For Bluetooth and USB (4554440)
1687 super::tellClients(iokit_common_msg(0x749));
1689 return super::tellClientsWithResponse(kIOMessageSystemWillPowerOff
);
1691 // this shouldn't execute
1692 return super::tellChangeDown(stateNum
);
1696 //*********************************************************************************
1699 // We override the superclass implementation so we can send a different message
1700 // type to the client or application being notified.
1702 // This must be idle sleep since we don't ask apps during any other power change.
1703 //*********************************************************************************
1705 bool IOPMrootDomain::askChangeDown ( unsigned long )
1707 return super::tellClientsWithResponse(kIOMessageCanSystemSleep
);
1711 //*********************************************************************************
1714 // Notify registered applications and kernel clients that we are not
1717 // We override the superclass implementation so we can send a different message
1718 // type to the client or application being notified.
1720 // This must be a vetoed idle sleep, since no other power change can be vetoed.
1721 //*********************************************************************************
1723 void IOPMrootDomain::tellNoChangeDown ( unsigned long )
1725 return tellClients(kIOMessageSystemWillNotSleep
);
1729 //*********************************************************************************
1732 // Notify registered applications and kernel clients that we are raising power.
1734 // We override the superclass implementation so we can send a different message
1735 // type to the client or application being notified.
1736 //*********************************************************************************
1738 void IOPMrootDomain::tellChangeUp ( unsigned long stateNum
)
1740 if ( stateNum
== ON_STATE
)
1742 // Direct callout into OSMetaClass so it can disable kmod unloads
1743 // during sleep/wake to prevent deadlocks.
1744 OSMetaClassSystemSleepOrWake( kIOMessageSystemHasPoweredOn
);
1746 IOHibernateSystemPostWake();
1747 return tellClients(kIOMessageSystemHasPoweredOn
);
1751 //*********************************************************************************
1754 //*********************************************************************************
1756 void IOPMrootDomain::reportUserInput ( void )
1762 iter
= getMatchingServices(serviceMatching("IODisplayWrangler"));
1765 wrangler
= (IOService
*) iter
->getNextObject();
1771 wrangler
->activityTickle(0,0);
1774 //*********************************************************************************
1775 // setQuickSpinDownTimeout
1777 //*********************************************************************************
1779 void IOPMrootDomain::setQuickSpinDownTimeout ( void )
1781 super::setAggressiveness((unsigned long)kPMMinutesToSpinDown
,(unsigned long)1);
1784 //*********************************************************************************
1785 // restoreUserSpinDownTimeout
1787 //*********************************************************************************
1789 void IOPMrootDomain::restoreUserSpinDownTimeout ( void )
1791 super::setAggressiveness((unsigned long)kPMMinutesToSpinDown
,(unsigned long)user_spindown
);
1794 //*********************************************************************************
1795 // changePowerStateTo & changePowerStateToPriv
1797 // Override of these methods for logging purposes.
1798 //*********************************************************************************
1800 IOReturn
IOPMrootDomain::changePowerStateTo ( unsigned long ordinal
)
1802 return super::changePowerStateTo(ordinal
);
1805 IOReturn
IOPMrootDomain::changePowerStateToPriv ( unsigned long ordinal
)
1809 if( (systemBooting
|| systemShutdown
) && (ordinal
== SLEEP_STATE
) )
1811 kprintf("DANGER DANGER DANGER unexpected code path. aborting SLEEPSTATE change.\n");
1812 super::changePowerStateToPriv(ON_STATE
);
1815 if( (SLEEP_STATE
== ordinal
) && sleepSupportedPEFunction
)
1818 // Determine if the machine supports sleep, or must doze.
1819 ret
= getPlatform()->callPlatformFunction(
1820 sleepSupportedPEFunction
, false,
1821 NULL
, NULL
, NULL
, NULL
);
1823 // If the machine only supports doze, the callPlatformFunction call
1824 // boils down toIOPMrootDomain::setSleepSupported(kPCICantSleep),
1825 // otherwise nothing.
1828 return super::changePowerStateToPriv(ordinal
);
1832 //*********************************************************************************
1833 // sysPowerDownHandler
1835 // Receives a notification when the RootDomain changes state.
1837 // Allows us to take action on system sleep, power down, and restart after
1838 // applications have received their power change notifications and replied,
1839 // but before drivers have powered down. We perform a vfs sync on power down.
1840 //*********************************************************************************
1842 IOReturn
IOPMrootDomain::sysPowerDownHandler( void * target
, void * refCon
,
1843 UInt32 messageType
, IOService
* service
,
1844 void * messageArgument
, vm_size_t argSize
)
1847 IOPowerStateChangeNotification
*params
= (IOPowerStateChangeNotification
*) messageArgument
;
1848 IOPMrootDomain
*rootDomain
= OSDynamicCast(IOPMrootDomain
, service
);
1851 return kIOReturnUnsupported
;
1853 switch (messageType
) {
1854 case kIOMessageSystemWillSleep
:
1855 rootDomain
->powerOverrideOnPriv(); // start ignoring children's requests
1856 // (fall through to other cases)
1858 // Interested applications have been notified of an impending power
1859 // change and have acked (when applicable).
1860 // This is our chance to save whatever state we can before powering
1862 // We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c,
1865 // We will ack within 20 seconds
1866 params
->returnValue
= 20 * 1000 * 1000;
1867 if (gIOHibernateState
)
1868 params
->returnValue
+= gIOHibernateFreeTime
* 1000; //add in time we could spend freeing pages
1870 if ( ! OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending
) )
1872 // Purposely delay the ack and hope that shutdown occurs quickly.
1873 // Another option is not to schedule the thread and wait for
1875 AbsoluteTime deadline
;
1876 clock_interval_to_deadline( 30, kSecondScale
, &deadline
);
1877 thread_call_enter1_delayed( rootDomain
->diskSyncCalloutEntry
,
1878 (thread_call_param_t
)params
->powerRef
,
1882 thread_call_enter1(rootDomain
->diskSyncCalloutEntry
, (thread_call_param_t
)params
->powerRef
);
1883 ret
= kIOReturnSuccess
;
1886 case kIOMessageSystemWillPowerOff
:
1887 case kIOMessageSystemWillRestart
:
1888 ret
= kIOReturnUnsupported
;
1892 ret
= kIOReturnUnsupported
;
1898 //*********************************************************************************
1899 // displayWranglerNotification
1901 // Receives a notification when the IODisplayWrangler changes state.
1903 // Allows us to take action on display dim/undim.
1905 // When the display goes dim we:
1906 // - Start the idle sleep timer
1907 // - set the quick spin down timeout
1909 // On wake from display dim:
1910 // - Cancel the idle sleep timer
1911 // - restore the user's chosen spindown timer from the "quick" spin down value
1912 //*********************************************************************************
1914 IOReturn
IOPMrootDomain::displayWranglerNotification( void * target
, void * refCon
,
1915 UInt32 messageType
, IOService
* service
,
1916 void * messageArgument
, vm_size_t argSize
)
1918 IOPMrootDomain
* rootDomain
= OSDynamicCast(IOPMrootDomain
, (IOService
*)target
);
1919 AbsoluteTime deadline
;
1920 static bool deviceAlreadyPoweredOff
= false;
1923 return kIOReturnUnsupported
;
1925 switch (messageType
) {
1926 case kIOMessageDeviceWillPowerOff
:
1927 // The IODisplayWrangler has powered off either because of idle display sleep
1928 // or force system sleep.
1930 // The display wrangler will send the DeviceWillPowerOff message 4 times until
1931 // it gets into its lowest state. We only want to act on the first of those 4.
1932 if( deviceAlreadyPoweredOff
) return kIOReturnUnsupported
;
1934 deviceAlreadyPoweredOff
= true;
1936 if( rootDomain
->extraSleepDelay
)
1938 // start the extra sleep timer
1939 clock_interval_to_deadline(rootDomain
->extraSleepDelay
*60, kSecondScale
, &deadline
);
1940 thread_call_enter_delayed(rootDomain
->extraSleepTimer
, deadline
);
1941 rootDomain
->idleSleepPending
= true;
1943 // accelerate disk spin down if spin down timer is non-zero (zero = never spin down)
1944 // and if system sleep is non-Never
1945 if( (0 != rootDomain
->user_spindown
) && (0 != rootDomain
->sleepSlider
) )
1946 rootDomain
->setQuickSpinDownTimeout();
1951 case kIOMessageDeviceHasPoweredOn
:
1953 // The display has powered on either because of UI activity or wake from sleep/doze
1954 deviceAlreadyPoweredOff
= false;
1955 rootDomain
->adjustPowerState();
1958 // cancel any pending idle sleep
1959 if(rootDomain
->idleSleepPending
)
1961 thread_call_cancel(rootDomain
->extraSleepTimer
);
1962 rootDomain
->idleSleepPending
= false;
1965 // Change the spindown value back to the user's selection from our accelerated setting
1966 if(0 != rootDomain
->user_spindown
)
1967 rootDomain
->restoreUserSpinDownTimeout();
1969 // Put on the policy maker's on clamp.
1976 return kIOReturnUnsupported
;
1979 //*********************************************************************************
1980 // displayWranglerPublished
1982 // Receives a notification when the IODisplayWrangler is published.
1983 // When it's published we install a power state change handler.
1985 //*********************************************************************************
1987 bool IOPMrootDomain::displayWranglerPublished(
1990 IOService
* newService
)
1992 IOPMrootDomain
*rootDomain
=
1993 OSDynamicCast(IOPMrootDomain
, (IOService
*)target
);
1998 rootDomain
->wrangler
= newService
;
2000 // we found the display wrangler, now install a handler
2001 if( !rootDomain
->wrangler
->registerInterest( gIOGeneralInterest
,
2002 &displayWranglerNotification
, target
, 0) )
2011 //*********************************************************************************
2014 // Notification on battery class IOPowerSource appearance
2016 //******************************************************************************
2018 bool IOPMrootDomain::batteryPublished(
2021 IOService
* resourceService
)
2023 // rdar://2936060&4435589
2024 // All laptops have dimmable LCD displays
2025 // All laptops have batteries
2026 // So if this machine has a battery, publish the fact that the backlight
2027 // supports dimming.
2028 ((IOPMrootDomain
*)root_domain
)->publishFeature("DisplayDims");
2035 //*********************************************************************************
2038 // Some condition that affects our wake/sleep/doze decision has changed.
2040 // If the sleep slider is in the off position, we cannot sleep or doze.
2041 // If the enclosure is open, we cannot sleep or doze.
2042 // If the system is still booting, we cannot sleep or doze.
2044 // In those circumstances, we prevent sleep and doze by holding power on with
2045 // changePowerStateToPriv(ON).
2047 // If the above conditions do not exist, and also the sleep timer has expired, we
2048 // allow sleep or doze to occur with either changePowerStateToPriv(SLEEP) or
2049 // changePowerStateToPriv(DOZE) depending on whether or not we already know the
2050 // platform cannot sleep.
2052 // In this case, sleep or doze will either occur immediately or at the next time
2053 // that no children are holding the system out of idle sleep via the
2054 // kIOPMPreventIdleSleep flag in their power state arrays.
2055 //*********************************************************************************
2057 void IOPMrootDomain::adjustPowerState( void )
2059 if ( (sleepSlider
== 0)
2064 if(systemBooting
|| systemShutdown
) {
2065 kprintf("adjusting power state to ON_STATE [2063] on grounds of systemBooting.\n");
2068 changePowerStateToPriv(ON_STATE
);
2073 if ( !sleepIsSupported
)
2074 setSleepSupported( kPCICantSleep
);
2075 changePowerStateToPriv(SLEEP_STATE
);
2080 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2085 #define super OSObject
2086 OSDefineMetaClassAndStructors(PMSettingObject
, OSObject
)
2088 void PMSettingObject::setPMSetting(const OSSymbol
*type
, OSObject
*obj
)
2090 (*func
)(target
, type
, obj
, refcon
);
2094 * Static constructor/initializer for PMSettingObject
2096 PMSettingObject
*PMSettingObject::pmSettingObject(
2097 IOPMrootDomain
*parent_arg
,
2098 IOPMSettingControllerCallback handler_arg
,
2099 OSObject
*target_arg
,
2100 uintptr_t refcon_arg
,
2101 uint32_t supportedPowerSources
,
2102 const OSSymbol
* settings
[])
2104 uint32_t objCount
= 0;
2105 PMSettingObject
*pmso
;
2107 if( !parent_arg
|| !handler_arg
|| !settings
) return NULL
;
2109 // count OSSymbol entries in NULL terminated settings array
2110 while( settings
[objCount
] ) {
2113 if(0 == objCount
) return NULL
;
2115 pmso
= new PMSettingObject
;
2116 if(!pmso
|| !pmso
->init()) return NULL
;
2118 pmso
->parent
= parent_arg
;
2119 pmso
->func
= handler_arg
;
2120 pmso
->target
= target_arg
;
2121 pmso
->refcon
= refcon_arg
;
2122 pmso
->releaseAtCount
= objCount
+ 1; // release when it has count+1 retains
2124 pmso
->publishedFeatureID
= (uint32_t *)IOMalloc(sizeof(uint32_t)*objCount
);
2125 if(pmso
->publishedFeatureID
) {
2126 for(unsigned int i
=0; i
<objCount
; i
++) {
2127 // Since there is now at least one listener to this setting, publish
2128 // PM root domain support for it.
2129 parent_arg
->publishFeature( settings
[i
]->getCStringNoCopy(),
2130 supportedPowerSources
, &pmso
->publishedFeatureID
[i
] );
2137 void PMSettingObject::free(void)
2139 OSCollectionIterator
*settings_iter
;
2144 int objCount
= releaseAtCount
- 1;
2146 if(publishedFeatureID
) {
2147 for(i
=0; i
<objCount
; i
++) {
2148 if(0 != publishedFeatureID
[i
]) {
2149 parent
->removePublishedFeature( publishedFeatureID
[i
] );
2153 IOFree(publishedFeatureID
, sizeof(uint32_t) * objCount
);
2156 IORecursiveLockLock(parent
->settingsCtrlLock
);
2158 // Search each PM settings array in the kernel.
2159 settings_iter
= OSCollectionIterator::withCollection(parent
->settingsCallbacks
);
2162 while(( sym
= OSDynamicCast(OSSymbol
, settings_iter
->getNextObject()) ))
2164 arr
= (OSArray
*)parent
->settingsCallbacks
->getObject(sym
);
2165 arr_idx
= arr
->getNextIndexOfObject(this, 0);
2167 // 'this' was found in the array; remove it
2168 arr
->removeObject(arr_idx
);
2172 settings_iter
->release();
2175 IORecursiveLockUnlock(parent
->settingsCtrlLock
);
2180 void PMSettingObject::taggedRelease(const void *tag
, const int when
) const
2182 // We have n+1 retains - 1 per array that this PMSettingObject is a member
2183 // of, and 1 retain to ourself. When we get a release with n+1 retains
2184 // remaining, we go ahead and free ourselves, cleaning up array pointers
2187 super::taggedRelease(tag
, releaseAtCount
);
2192 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2195 #define super IOService
2197 OSDefineMetaClassAndStructors(IORootParent
, IOService
)
2199 // This array exactly parallels the state array for the root domain.
2200 // Power state changes initiated by a device can be vetoed by a client of the device, and
2201 // power state changes initiated by the parent of a device cannot be vetoed by a client of the device,
2202 // so when the root domain wants a power state change that cannot be vetoed (e.g. demand sleep), it asks
2203 // its parent to make the change. That is the reason for this complexity.
2205 static IOPMPowerState patriarchPowerStates
[number_of_power_states
] = {
2206 {1,0,0,0,0,0,0,0,0,0,0,0}, // off
2207 {1,0,RESTART_POWER
,0,0,0,0,0,0,0,0,0}, // reset
2208 {1,0,SLEEP_POWER
,0,0,0,0,0,0,0,0,0}, // sleep
2209 {1,0,DOZE_POWER
,0,0,0,0,0,0,0,0,0}, // doze
2210 {1,0,ON_POWER
,0,0,0,0,0,0,0,0,0} // running
2213 bool IORootParent::start ( IOService
* nub
)
2215 mostRecentChange
= ON_STATE
;
2218 registerPowerDriver(this,patriarchPowerStates
,number_of_power_states
);
2219 powerOverrideOnPriv();
2224 void IORootParent::shutDownSystem ( void )
2226 mostRecentChange
= OFF_STATE
;
2227 changePowerStateToPriv(OFF_STATE
);
2231 void IORootParent::restartSystem ( void )
2233 mostRecentChange
= RESTART_STATE
;
2234 changePowerStateToPriv(RESTART_STATE
);
2238 void IORootParent::sleepSystem ( void )
2240 mostRecentChange
= SLEEP_STATE
;
2241 changePowerStateToPriv(SLEEP_STATE
);
2245 void IORootParent::dozeSystem ( void )
2247 mostRecentChange
= DOZE_STATE
;
2248 changePowerStateToPriv(DOZE_STATE
);
2251 // Called in demand sleep when sleep discovered to be impossible after actually attaining that state.
2252 // This brings the parent to doze, which allows the root to step up from sleep to doze.
2254 // In idle sleep, do nothing because the parent is still on and the root can freely change state.
2256 void IORootParent::sleepToDoze ( void )
2258 if ( mostRecentChange
== SLEEP_STATE
) {
2259 changePowerStateToPriv(DOZE_STATE
);
2264 void IORootParent::wakeSystem ( void )
2266 mostRecentChange
= ON_STATE
;
2267 changePowerStateToPriv(ON_STATE
);
2270 IOReturn
IORootParent::changePowerStateToPriv ( unsigned long ordinal
)
2274 if( (SLEEP_STATE
== ordinal
) && sleepSupportedPEFunction
)
2277 // Determine if the machine supports sleep, or must doze.
2278 ret
= getPlatform()->callPlatformFunction(
2279 sleepSupportedPEFunction
, false,
2280 NULL
, NULL
, NULL
, NULL
);
2282 // If the machine only supports doze, the callPlatformFunction call
2283 // boils down toIOPMrootDomain::setSleepSupported(kPCICantSleep),
2284 // otherwise nothing.
2287 return super::changePowerStateToPriv(ordinal
);