2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
25 #include <IOKit/IOWorkLoop.h>
26 #include <IOKit/IOCommandGate.h>
27 #include <IOKit/IOTimerEventSource.h>
28 #include <IOKit/IOPlatformExpert.h>
29 #include <IOKit/IOKitDebug.h>
30 #include <IOKit/IOTimeStamp.h>
31 #include <IOKit/pwr_mgt/RootDomain.h>
32 #include <IOKit/pwr_mgt/IOPMPrivate.h>
33 #include <IOKit/IOMessage.h>
34 #include "RootDomainUserClient.h"
35 #include "IOKit/pwr_mgt/IOPowerConnection.h"
36 #include "IOPMPowerStateQueue.h"
38 extern "C" void kprintf(const char *, ...);
40 extern const IORegistryPlane
* gIOPowerPlane
;
42 // debug trace function
44 ioSPMTrace(unsigned int csc
,
45 unsigned int a
= 0, unsigned int b
= 0,
46 unsigned int c
= 0, unsigned int d
= 0)
48 if (gIOKitDebug
& kIOLogTracePower
)
49 IOTimeStampConstant(IODBG_POWER(csc
), a
, b
, c
, d
);
52 IOReturn
broadcast_aggressiveness ( OSObject
*, void *, void *, void *, void * );
53 static void sleepTimerExpired(thread_call_param_t
);
54 static void wakeupClamshellTimerExpired ( thread_call_param_t us
);
57 #define number_of_power_states 5
59 #define RESTART_STATE 1
64 #define ON_POWER kIOPMPowerOn
65 #define RESTART_POWER kIOPMRestart
66 #define SLEEP_POWER kIOPMAuxPowerOn
67 #define DOZE_POWER kIOPMDoze
69 static IOPMPowerState ourPowerStates
[number_of_power_states
] = {
70 {1,0, 0, 0,0,0,0,0,0,0,0,0}, // state 0, off
71 {1,kIOPMRestartCapability
, kIOPMRestart
, RESTART_POWER
,0,0,0,0,0,0,0,0}, // state 1, restart
72 {1,kIOPMSleepCapability
, kIOPMSleep
, SLEEP_POWER
,0,0,0,0,0,0,0,0}, // state 2, sleep
73 {1,kIOPMDoze
, kIOPMDoze
, DOZE_POWER
,0,0,0,0,0,0,0,0}, // state 3, doze
74 {1,kIOPMPowerOn
, kIOPMPowerOn
, ON_POWER
,0,0,0,0,0,0,0,0}, // state 4, on
77 static IOPMrootDomain
* gRootDomain
;
78 static UInt32 gSleepOrShutdownPending
= 0;
81 #define super IOService
82 OSDefineMetaClassAndStructors(IOPMrootDomain
,IOService
)
86 IONotifier
* registerSleepWakeInterest(IOServiceInterestHandler handler
, void * self
, void * ref
= 0)
88 return gRootDomain
->registerInterest( gIOGeneralInterest
, handler
, self
, ref
);
91 IONotifier
* registerPrioritySleepWakeInterest(IOServiceInterestHandler handler
, void * self
, void * ref
= 0)
93 return gRootDomain
->registerInterest( gIOPriorityPowerStateInterest
, handler
, self
, ref
);
96 IOReturn
acknowledgeSleepWakeNotification(void * PMrefcon
)
98 return gRootDomain
->allowPowerChange ( (unsigned long)PMrefcon
);
101 IOReturn
vetoSleepWakeNotification(void * PMrefcon
)
103 return gRootDomain
->cancelPowerChange ( (unsigned long)PMrefcon
);
106 IOReturn
rootDomainRestart ( void )
108 return gRootDomain
->restartSystem();
111 IOReturn
rootDomainShutdown ( void )
113 return gRootDomain
->shutdownSystem();
116 void IOSystemShutdownNotification ( void )
118 for ( int i
= 0; i
< 100; i
++ )
120 if ( OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending
) ) break;
125 int sync_internal(void);
129 A device is always in the highest power state which satisfies its driver, its policy-maker, and any power domain
130 children it has, but within the constraint of the power state provided by its parent. The driver expresses its desire by
131 calling changePowerStateTo(), the policy-maker expresses its desire by calling changePowerStateToPriv(), and the children
132 express their desires by calling requestPowerDomainState().
134 The Root Power Domain owns the policy for idle and demand sleep and doze for the system. It is a power-managed IOService just
135 like the others in the system. It implements several power states which correspond to what we see as Sleep, Doze, etc.
137 The sleep/doze policy is as follows:
138 Sleep and Doze are prevented if the case is open so that nobody will think the machine is off and plug/unplug cards.
139 Sleep and Doze are prevented if the sleep timeout slider in the preferences panel is at zero.
140 The system cannot Sleep, but can Doze if some object in the tree is in a power state marked kIOPMPreventSystemSleep.
142 These three conditions are enforced using the "driver clamp" by calling changePowerStateTo(). For example, if the case is
143 opened, changePowerStateTo(ON_STATE) is called to hold the system on regardless of the desires of the children of the root or
144 the state of the other clamp.
146 Demand Sleep/Doze is initiated by pressing the front panel power button, closing the clamshell, or selecting the menu item.
147 In this case the root's parent actually initiates the power state change so that the root has no choice and does not give
148 applications the opportunity to veto the change.
150 Idle Sleep/Doze occurs if no objects in the tree are in a state marked kIOPMPreventIdleSleep. When this is true, the root's
151 children are not holding the root on, so it sets the "policy-maker clamp" by calling changePowerStateToPriv(ON_STATE)
152 to hold itself on until the sleep timer expires. This timer is set for the difference between the sleep timeout slider and
153 the larger of the display dim timeout slider and the disk spindown timeout slider in the Preferences panel. For example, if
154 the system is set to sleep after thirty idle minutes, and the display and disk are set to sleep after five idle minutes,
155 when there is no longer an object in the tree holding the system out of Idle Sleep (via kIOPMPreventIdleSleep), the root
156 sets its timer for 25 minutes (30 - 5). When the timer expires, it releases its clamp and now nothing is holding it awake,
159 Demand sleep is prevented when the system is booting. When preferences are transmitted by the loginwindow at the end of
160 boot, a flag is cleared, and this allows subsequent Demand Sleep.
162 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
163 a clamp, but sets a flag which is noticed before actually sleeping the kernel. If the flag is set, the root steps up
164 one power state from Sleep to Doze, and any objects in the tree for which this is relevent will act appropriately (USB and
165 ADB will turn on again so that they can wake the system out of Doze (keyboard/mouse activity will cause the Display Wrangler
170 // **********************************************************************************
172 IOPMrootDomain
* IOPMrootDomain::construct( void )
174 IOPMrootDomain
*root
;
176 root
= new IOPMrootDomain
;
183 // **********************************************************************************
185 static void disk_sync_callout(thread_call_param_t p0
, thread_call_param_t p1
)
187 IOService
*rootDomain
= (IOService
*) p0
;
188 unsigned long pmRef
= (unsigned long) p1
;
191 rootDomain
->allowPowerChange(pmRef
);
194 // **********************************************************************************
197 // We don't do much here. The real initialization occurs when the platform
198 // expert informs us we are the root.
199 // **********************************************************************************
202 bool IOPMrootDomain::start ( IOService
* nub
)
204 OSDictionary
*tmpDict
;
206 pmPowerStateQueue
= 0;
213 setProperty("IOSleepSupported","");
215 sleepIsSupported
= true;
216 systemBooting
= true;
217 ignoringClamshell
= true;
219 idleSleepPending
= false;
223 ignoringClamshellDuringWakeup
= false;
225 tmpDict
= OSDictionary::withCapacity(1);
226 setProperty(kRootDomainSupportedFeatures
, tmpDict
);
229 pm_vars
->PMworkloop
= IOWorkLoop::workLoop();
230 pmPowerStateQueue
= IOPMPowerStateQueue::PMPowerStateQueue(this);
231 pm_vars
->PMworkloop
->addEventSource(pmPowerStateQueue
);
233 extraSleepTimer
= thread_call_allocate((thread_call_func_t
)sleepTimerExpired
, (thread_call_param_t
) this);
234 clamshellWakeupIgnore
= thread_call_allocate((thread_call_func_t
)wakeupClamshellTimerExpired
, (thread_call_param_t
) this);
235 diskSyncCalloutEntry
= thread_call_allocate(&disk_sync_callout
, (thread_call_param_t
) this);
238 patriarch
= new IORootParent
;
240 patriarch
->attach(this);
241 patriarch
->start(this);
242 patriarch
->youAreRoot();
243 patriarch
->wakeSystem();
244 patriarch
->addPowerChild(this);
246 registerPowerDriver(this,ourPowerStates
,number_of_power_states
);
248 setPMRootDomain(this);
249 // set a clamp until we sleep
250 changePowerStateToPriv(ON_STATE
);
252 // install power change handler
253 registerPrioritySleepWakeInterest( &sysPowerDownHandler
, this, 0);
255 // Register for a notification when IODisplayWrangler is published
256 addNotification( gIOPublishNotification
, serviceMatching("IODisplayWrangler"), &displayWranglerPublished
, this, 0);
258 const OSSymbol
*ucClassName
= OSSymbol::withCStringNoCopy("RootDomainUserClient");
259 setProperty(gIOUserClientClassKey
, (OSMetaClassBase
*) ucClassName
);
260 ucClassName
->release();
262 registerService(); // let clients find us
267 // **********************************************************************************
270 // Receive a setProperty call
271 // The "System Boot" property means the system is completely booted.
272 // **********************************************************************************
273 IOReturn
IOPMrootDomain::setProperties ( OSObject
*props_obj
)
275 OSDictionary
*dict
= OSDynamicCast(OSDictionary
, props_obj
);
277 OSString
*boot_complete_string
= OSString::withCString("System Boot Complete");
278 OSString
*power_button_string
= OSString::withCString("DisablePowerButtonSleep");
279 OSString
*stall_halt_string
= OSString::withCString("StallSystemAtHalt");
281 if(!dict
) return kIOReturnBadArgument
;
285 if(systemBooting
&& dict
->getObject(boot_complete_string
))
287 systemBooting
= false;
288 //kprintf("IOPM: received System Boot Complete property\n");
292 if(b
= dict
->getObject(power_button_string
))
294 setProperty(power_button_string
, b
);
297 if(b
= dict
->getObject(stall_halt_string
))
299 setProperty(stall_halt_string
, b
);
302 if(boot_complete_string
) boot_complete_string
->release();
303 if(power_button_string
) power_button_string
->release();
304 if(stall_halt_string
) stall_halt_string
->release();
306 return kIOReturnSuccess
;
310 //*********************************************************************************
313 // Power Managment is informing us that we are the root power domain.
314 // We know we are not the root however, since we have just instantiated a parent
315 // for ourselves and made it the root. We override this method so it will have
317 //*********************************************************************************
318 IOReturn
IOPMrootDomain::youAreRoot ( void )
323 // **********************************************************************************
327 // **********************************************************************************
328 void IOPMrootDomain::command_received ( void * w
, void * x
, void * y
, void * z
)
330 super::command_received(w
,x
,y
,z
);
334 // **********************************************************************************
335 // broadcast_aggressiveness
337 // **********************************************************************************
338 IOReturn
broadcast_aggressiveness ( OSObject
* root
, void * x
, void * y
, void *, void * )
340 ((IOPMrootDomain
*)root
)->broadcast_it((unsigned long)x
,(unsigned long)y
);
345 // **********************************************************************************
348 // We are behind the command gate to broadcast an aggressiveness factor. We let the
349 // superclass do it, but we need to snoop on factors that affect idle sleep.
350 // **********************************************************************************
351 void IOPMrootDomain::broadcast_it (unsigned long type
, unsigned long value
)
353 super::setAggressiveness(type
,value
);
355 // Save user's spin down timer to restore after we replace it for idle sleep
356 if( type
== kPMMinutesToSpinDown
) user_spindown
= value
;
358 // Use longestNonSleepSlider to calculate dimming adjust idle sleep timer
359 longestNonSleepSlider
= pm_vars
->current_aggressiveness_values
[kPMMinutesToDim
];
362 if ( type
== kPMMinutesToSleep
) {
363 if ( (sleepSlider
== 0) && (value
!= 0) ) {
365 // idle sleep is now enabled, maybe sleep now
369 if ( sleepSlider
== 0 ) {
370 // idle sleep is now disabled
372 // make sure we're powered
373 patriarch
->wakeSystem();
376 if ( sleepSlider
> longestNonSleepSlider
) {
377 extraSleepDelay
= sleepSlider
- longestNonSleepSlider
;
385 // **********************************************************************************
388 // **********************************************************************************
389 static void sleepTimerExpired ( thread_call_param_t us
)
391 ((IOPMrootDomain
*)us
)->handleSleepTimerExpiration();
395 static void wakeupClamshellTimerExpired ( thread_call_param_t us
)
397 ((IOPMrootDomain
*)us
)->stopIgnoringClamshellEventsDuringWakeup();
401 // **********************************************************************************
402 // handleSleepTimerExpiration
404 // The time between the sleep idle timeout and the next longest one has elapsed.
405 // It's time to sleep. Start that by removing the clamp that's holding us awake.
406 // **********************************************************************************
407 void IOPMrootDomain::handleSleepTimerExpiration ( void )
409 // accelerate disk spin down if spin down timer is non-zero (zero = never spin down)
410 if(0 != user_spindown
)
411 setQuickSpinDownTimeout();
418 void IOPMrootDomain::stopIgnoringClamshellEventsDuringWakeup(void)
422 // Allow clamshell-induced sleep now
423 ignoringClamshellDuringWakeup
= false;
425 if ((state
= getProperty(kAppleClamshellStateKey
)))
426 publishResource(kAppleClamshellStateKey
, state
);
429 //*********************************************************************************
432 // Some aggressiveness factor has changed. We broadcast it to the hierarchy while on
433 // the Power Mangement workloop thread. This enables objects in the
434 // hierarchy to successfully alter their idle timers, which are all on the
436 //*********************************************************************************
438 IOReturn
IOPMrootDomain::setAggressiveness ( unsigned long type
, unsigned long newLevel
)
440 if ( pm_vars
->PMcommandGate
) {
441 pm_vars
->PMcommandGate
->runAction(broadcast_aggressiveness
,(void *)type
,(void *)newLevel
);
444 return kIOReturnSuccess
;
448 // **********************************************************************************
451 // **********************************************************************************
452 IOReturn
IOPMrootDomain::sleepSystem ( void )
454 //kprintf("sleep demand received\n");
455 if ( !systemBooting
&& allowSleep
&& sleepIsSupported
) {
456 patriarch
->sleepSystem();
457 return kIOReturnSuccess
;
459 if ( !systemBooting
&& allowSleep
&& !sleepIsSupported
) {
460 patriarch
->dozeSystem();
461 return kIOReturnSuccess
;
463 return kIOReturnSuccess
;
467 // **********************************************************************************
470 // **********************************************************************************
471 IOReturn
IOPMrootDomain::shutdownSystem ( void )
473 //patriarch->shutDownSystem();
474 return kIOReturnUnsupported
;
478 // **********************************************************************************
481 // **********************************************************************************
482 IOReturn
IOPMrootDomain::restartSystem ( void )
484 //patriarch->restartSystem();
485 return kIOReturnUnsupported
;
489 // **********************************************************************************
492 // This overrides powerChangeDone in IOService.
494 // Finder sleep and idle sleep move us from the ON state to the SLEEP_STATE.
496 // If we just finished going to the SLEEP_STATE, and the platform is capable of true sleep,
497 // sleep the kernel. Otherwise switch up to the DOZE_STATE which will keep almost
498 // everything as off as it can get.
500 // **********************************************************************************
501 void IOPMrootDomain::powerChangeDone ( unsigned long previousState
)
503 OSNumber
* propertyPtr
;
504 unsigned short theProperty
;
505 AbsoluteTime deadline
;
507 switch ( pm_vars
->myCurrentState
) {
509 if ( canSleep
&& sleepIsSupported
)
511 // re-enable this timer for next sleep
512 idleSleepPending
= false;
513 IOLog("System Sleep\n");
514 pm_vars
->thePlatform
->sleepKernel();
516 // The CPU(s) are off at this point. When they're awakened by CPU interrupt,
517 // code will resume exeuction here.
519 // Now we're waking...
520 ioSPMTrace(IOPOWER_WAKE
, * (int *) this);
522 // stay awake for at least 30 seconds
523 clock_interval_to_deadline(30, kSecondScale
, &deadline
);
524 thread_call_enter_delayed(extraSleepTimer
, deadline
);
525 // this gets turned off when we sleep again
526 idleSleepPending
= true;
528 // Ignore closed clamshell during wakeup and for a few seconds
529 // after wakeup is complete
530 ignoringClamshellDuringWakeup
= true;
532 // sleep transition complete
533 gSleepOrShutdownPending
= 0;
535 // trip the reset of the calendar clock
536 clock_wakeup_calendar();
539 patriarch
->wakeSystem();
541 // early stage wake notification
542 tellClients(kIOMessageSystemWillPowerOn
);
544 // tell the tree we're waking
545 IOLog("System Wake\n");
548 // Allow drivers to request extra processing time before clamshell
549 // sleep if kIOREMSleepEnabledKey is present.
550 // Ignore clamshell events for at least 5 seconds
551 if(getProperty(kIOREMSleepEnabledKey
)) {
552 // clamshellWakeupIgnore callout clears ignoreClamshellDuringWakeup bit
553 clock_interval_to_deadline(5, kSecondScale
, &deadline
);
554 if(clamshellWakeupIgnore
) thread_call_enter_delayed(clamshellWakeupIgnore
, deadline
);
555 } else ignoringClamshellDuringWakeup
= false;
557 // Find out what woke us
558 propertyPtr
= OSDynamicCast(OSNumber
,getProperty("WakeEvent"));
560 theProperty
= propertyPtr
->unsigned16BitValue();
561 IOLog("Wake event %04x\n",theProperty
);
562 if ( (theProperty
& 0x0008) || //lid
563 (theProperty
& 0x0800) || // front panel button
564 (theProperty
& 0x0020) || // external keyboard
565 (theProperty
& 0x0001) ) { // internal keyboard
566 // We've identified the wakeup event as UI driven
570 // Since we can't identify the wakeup event, treat it as UI activity
574 // Wake for thirty seconds
575 changePowerStateToPriv(ON_STATE
);
576 powerOverrideOffPriv();
578 // allow us to step up a power state
579 patriarch
->sleepToDoze();
581 changePowerStateToPriv(DOZE_STATE
);
586 if ( previousState
!= DOZE_STATE
)
588 IOLog("System Doze\n");
590 // re-enable this timer for next sleep
591 idleSleepPending
= false;
592 gSleepOrShutdownPending
= 0;
596 IOLog("System Restart\n");
597 PEHaltRestart(kPERestartCPU
);
601 IOLog("System Halt\n");
602 PEHaltRestart(kPEHaltCPU
);
608 // **********************************************************************************
611 // The Display Wrangler calls here when it switches to its highest state. If the
612 // system is currently dozing, allow it to wake by making sure the parent is
614 // **********************************************************************************
615 void IOPMrootDomain::wakeFromDoze( void )
617 if ( pm_vars
->myCurrentState
== DOZE_STATE
)
619 // reset this till next attempt
621 powerOverrideOffPriv();
623 // early wake notification
624 tellClients(kIOMessageSystemWillPowerOn
);
626 // allow us to wake if children so desire
627 patriarch
->wakeSystem();
632 // **********************************************************************************
635 // Adds a new feature to the supported features dictionary
638 // **********************************************************************************
639 void IOPMrootDomain::publishFeature( const char * feature
)
641 OSDictionary
*features
= (OSDictionary
*)getProperty(kRootDomainSupportedFeatures
);
643 features
->setObject(feature
, kOSBooleanTrue
);
646 void IOPMrootDomain::unIdleDevice( IOService
*theDevice
, unsigned long theState
)
648 if(pmPowerStateQueue
)
649 pmPowerStateQueue
->unIdleOccurred(theDevice
, theState
);
652 void IOPMrootDomain::announcePowerSourceChange( void )
654 messageClients(kIOPMMessageBatteryStatusHasChanged
);
657 //*********************************************************************************
658 // receivePowerNotification
660 // The power controller is notifying us of a hardware-related power management
661 // event that we must handle. This is a result of an 'environment' interrupt from
662 // the power mgt micro.
663 //*********************************************************************************
665 IOReturn
IOPMrootDomain::receivePowerNotification (UInt32 msg
)
667 if (msg
& kIOPMOverTemp
)
669 IOLog("Power Management received emergency overtemp signal. Going to sleep.");
670 (void) sleepSystem ();
672 if (msg
& kIOPMSetDesktopMode
)
674 desktopMode
= (0 != (msg
& kIOPMSetValue
));
675 msg
&= ~(kIOPMSetDesktopMode
| kIOPMSetValue
);
677 if (msg
& kIOPMSetACAdaptorConnected
)
679 acAdaptorConnect
= (0 != (msg
& kIOPMSetValue
));
680 msg
&= ~(kIOPMSetACAdaptorConnected
| kIOPMSetValue
);
682 if (msg
& kIOPMEnableClamshell
)
684 ignoringClamshell
= false;
686 if (msg
& kIOPMDisableClamshell
)
688 ignoringClamshell
= true;
691 if (msg
& kIOPMProcessorSpeedChange
)
693 IOService
*pmu
= waitForService(serviceMatching("ApplePMU"));
694 pmu
->callPlatformFunction("prepareForSleep", false, 0, 0, 0, 0);
695 pm_vars
->thePlatform
->sleepKernel();
696 pmu
->callPlatformFunction("recoverFromSleep", false, 0, 0, 0, 0);
699 if (msg
& kIOPMSleepNow
)
701 (void) sleepSystem ();
704 if (msg
& kIOPMPowerEmergency
)
706 (void) sleepSystem ();
709 if (msg
& kIOPMClamshellClosed
)
711 if ( !ignoringClamshell
&& !ignoringClamshellDuringWakeup
712 && (!desktopMode
|| !acAdaptorConnect
) )
715 (void) sleepSystem ();
719 if (msg
& kIOPMPowerButton
)
721 // toggle state of sleep/wake
723 if ( pm_vars
->myCurrentState
== DOZE_STATE
)
725 // yes, tell the tree we're waking
727 // wake the Display Wrangler
731 // Check that power button sleep is enabled
732 if(kOSBooleanTrue
!= getProperty(OSString::withCString("DisablePowerButtonSleep")))
737 // if the case has been closed, we allow
738 // the machine to be put to sleep or to idle sleep
740 if ( (msg
& kIOPMAllowSleep
) && !allowSleep
)
746 // if the case has been opened, we disallow sleep/doze
748 if (msg
& kIOPMPreventSleep
) {
751 if ( pm_vars
->myCurrentState
== DOZE_STATE
) {
752 // yes, tell the tree we're waking
755 // wake the Display Wrangler
759 // make sure we have power to clamp
760 patriarch
->wakeSystem();
768 //*********************************************************************************
771 //*********************************************************************************
773 void IOPMrootDomain::setSleepSupported( IOOptionBits flags
)
775 if ( flags
& kPCICantSleep
)
779 platformSleepSupport
= flags
;
784 //*********************************************************************************
785 // requestPowerDomainState
787 // The root domain intercepts this call to the superclass.
789 // If the clamp bit is not set in the desire, then the child doesn't need the power
790 // state it's requesting; it just wants it. The root ignores desires but not needs.
791 // If the clamp bit is not set, the root takes it that the child can tolerate no
792 // power and interprets the request accordingly. If all children can thus tolerate
793 // no power, we are on our way to idle sleep.
794 //*********************************************************************************
796 IOReturn
IOPMrootDomain::requestPowerDomainState ( IOPMPowerFlags desiredState
, IOPowerConnection
* whichChild
, unsigned long specification
)
800 IOPowerConnection
*connection
;
801 unsigned long powerRequestFlag
= 0;
802 IOPMPowerFlags editedDesire
= desiredState
;
804 // if they don't really need it, they don't get it
805 if ( !(desiredState
& kIOPMPreventIdleSleep
) ) {
810 IOLockLock(pm_vars
->childLock
);
812 // recompute sleepIsSupported and see if all children are asleep
813 iter
= getChildIterator(gIOPowerPlane
);
814 sleepIsSupported
= true;
817 while ( (next
= iter
->getNextObject()) )
819 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
821 if ( connection
== whichChild
)
823 powerRequestFlag
+= editedDesire
;
824 if ( desiredState
& kIOPMPreventSystemSleep
)
826 sleepIsSupported
= false;
829 powerRequestFlag
+= connection
->getDesiredDomainState();
830 if ( connection
->getPreventSystemSleepFlag() )
832 sleepIsSupported
= false;
840 if ( (extraSleepDelay
== 0) && (powerRequestFlag
== 0) )
845 // this may put the system to sleep
848 IOLockUnlock(pm_vars
->childLock
);
850 editedDesire
|= desiredState
& kIOPMPreventSystemSleep
;
852 return super::requestPowerDomainState(editedDesire
,whichChild
,specification
);
856 //*********************************************************************************
859 //*********************************************************************************
861 IOOptionBits
IOPMrootDomain::getSleepSupported( void )
863 return( platformSleepSupport
);
867 //*********************************************************************************
870 // We override the superclass implementation so we can send a different message
871 // type to the client or application being notified.
872 //*********************************************************************************
874 bool IOPMrootDomain::tellChangeDown ( unsigned long stateNum
)
876 switch ( stateNum
) {
879 return super::tellClientsWithResponse(kIOMessageSystemWillSleep
);
881 return super::tellClientsWithResponse(kIOMessageSystemWillRestart
);
883 return super::tellClientsWithResponse(kIOMessageSystemWillPowerOff
);
885 // this shouldn't execute
886 return super::tellChangeDown(stateNum
);
890 //*********************************************************************************
893 // We override the superclass implementation so we can send a different message
894 // type to the client or application being notified.
896 // This must be idle sleep since we don't ask apps during any other power change.
897 //*********************************************************************************
899 bool IOPMrootDomain::askChangeDown ( unsigned long )
901 return super::tellClientsWithResponse(kIOMessageCanSystemSleep
);
905 //*********************************************************************************
908 // Notify registered applications and kernel clients that we are not
911 // We override the superclass implementation so we can send a different message
912 // type to the client or application being notified.
914 // This must be a vetoed idle sleep, since no other power change can be vetoed.
915 //*********************************************************************************
917 void IOPMrootDomain::tellNoChangeDown ( unsigned long )
919 return tellClients(kIOMessageSystemWillNotSleep
);
923 //*********************************************************************************
926 // Notify registered applications and kernel clients that we are raising power.
928 // We override the superclass implementation so we can send a different message
929 // type to the client or application being notified.
930 //*********************************************************************************
932 void IOPMrootDomain::tellChangeUp ( unsigned long stateNum
)
934 if ( stateNum
== ON_STATE
)
936 return tellClients(kIOMessageSystemHasPoweredOn
);
940 //*********************************************************************************
943 //*********************************************************************************
945 void IOPMrootDomain::reportUserInput ( void )
951 iter
= getMatchingServices(serviceMatching("IODisplayWrangler"));
954 wrangler
= (IOService
*) iter
->getNextObject();
960 wrangler
->activityTickle(0,0);
963 //*********************************************************************************
964 // setQuickSpinDownTimeout
966 //*********************************************************************************
968 void IOPMrootDomain::setQuickSpinDownTimeout ( void )
970 super::setAggressiveness((unsigned long)kPMMinutesToSpinDown
,(unsigned long)1);
973 //*********************************************************************************
974 // restoreUserSpinDownTimeout
976 //*********************************************************************************
978 void IOPMrootDomain::restoreUserSpinDownTimeout ( void )
980 super::setAggressiveness((unsigned long)kPMMinutesToSpinDown
,(unsigned long)user_spindown
);
983 //*********************************************************************************
984 // changePowerStateTo & changePowerStateToPriv
986 // Override of these methods for logging purposes.
987 //*********************************************************************************
989 IOReturn
IOPMrootDomain::changePowerStateTo ( unsigned long ordinal
)
991 ioSPMTrace(IOPOWER_ROOT
, * (int *) this, (int) true, (int) ordinal
);
993 return super::changePowerStateTo(ordinal
);
996 IOReturn
IOPMrootDomain::changePowerStateToPriv ( unsigned long ordinal
)
998 ioSPMTrace(IOPOWER_ROOT
, * (int *) this, (int) false, (int) ordinal
);
1000 return super::changePowerStateToPriv(ordinal
);
1004 //*********************************************************************************
1005 // sysPowerDownHandler
1007 // Receives a notification when the RootDomain changes state.
1009 // Allows us to take action on system sleep, power down, and restart after
1010 // applications have received their power change notifications and replied,
1011 // but before drivers have powered down. We perform a vfs sync on power down.
1012 //*********************************************************************************
1014 IOReturn
IOPMrootDomain::sysPowerDownHandler( void * target
, void * refCon
,
1015 UInt32 messageType
, IOService
* service
,
1016 void * messageArgument
, vm_size_t argSize
)
1019 IOPowerStateChangeNotification
*params
= (IOPowerStateChangeNotification
*) messageArgument
;
1020 IOPMrootDomain
*rootDomain
= OSDynamicCast(IOPMrootDomain
, service
);
1023 return kIOReturnUnsupported
;
1025 switch (messageType
) {
1026 case kIOMessageSystemWillSleep
:
1027 rootDomain
->powerOverrideOnPriv(); // start ignoring children's requests
1028 // (fall through to other cases)
1030 // Interested applications have been notified of an impending power
1031 // change and have acked (when applicable).
1032 // This is our chance to save whatever state we can before powering
1034 // We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c,
1037 // We will ack within 20 seconds
1038 params
->returnValue
= 20 * 1000 * 1000;
1040 if ( ! OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending
) )
1042 // Purposely delay the ack and hope that shutdown occurs quickly.
1043 // Another option is not to schedule the thread and wait for
1045 AbsoluteTime deadline
;
1046 clock_interval_to_deadline( 30, kSecondScale
, &deadline
);
1047 thread_call_enter1_delayed( rootDomain
->diskSyncCalloutEntry
,
1048 (thread_call_param_t
)params
->powerRef
,
1052 thread_call_enter1(rootDomain
->diskSyncCalloutEntry
, (thread_call_param_t
)params
->powerRef
);
1053 ret
= kIOReturnSuccess
;
1056 case kIOMessageSystemWillPowerOff
:
1057 case kIOMessageSystemWillRestart
:
1058 ret
= kIOReturnUnsupported
;
1062 ret
= kIOReturnUnsupported
;
1068 //*********************************************************************************
1069 // displayWranglerNotification
1071 // Receives a notification when the IODisplayWrangler changes state.
1073 // Allows us to take action on display dim/undim.
1075 // When the display goes dim we:
1076 // - Start the idle sleep timer
1077 // - set the quick spin down timeout
1079 // On wake from display dim:
1080 // - Cancel the idle sleep timer
1081 // - restore the user's chosen spindown timer from the "quick" spin down value
1082 //*********************************************************************************
1084 IOReturn
IOPMrootDomain::displayWranglerNotification( void * target
, void * refCon
,
1085 UInt32 messageType
, IOService
* service
,
1086 void * messageArgument
, vm_size_t argSize
)
1088 IOPMrootDomain
* rootDomain
= OSDynamicCast(IOPMrootDomain
, (IOService
*)target
);
1089 AbsoluteTime deadline
;
1090 static bool deviceAlreadyPoweredOff
= false;
1093 return kIOReturnUnsupported
;
1095 switch (messageType
) {
1096 case kIOMessageDeviceWillPowerOff
:
1097 // The IODisplayWrangler has powered off either because of idle display sleep
1098 // or force system sleep.
1100 // The display wrangler will send the DeviceWillPowerOff message 4 times until
1101 // it gets into its lowest state. We only want to act on the first of those 4.
1102 if( deviceAlreadyPoweredOff
) return kIOReturnUnsupported
;
1104 deviceAlreadyPoweredOff
= true;
1106 if( rootDomain
->extraSleepDelay
)
1108 // start the extra sleep timer
1109 clock_interval_to_deadline(rootDomain
->extraSleepDelay
*60, kSecondScale
, &deadline
);
1110 thread_call_enter_delayed(rootDomain
->extraSleepTimer
, deadline
);
1111 rootDomain
->idleSleepPending
= true;
1113 // accelerate disk spin down if spin down timer is non-zero (zero = never spin down)
1114 // and if system sleep is non-Never
1115 if( (0 != rootDomain
->user_spindown
) && (0 != rootDomain
->sleepSlider
) )
1116 rootDomain
->setQuickSpinDownTimeout();
1121 case kIOMessageDeviceHasPoweredOn
:
1123 // The display has powered on either because of UI activity or wake from sleep/doze
1124 deviceAlreadyPoweredOff
= false;
1125 rootDomain
->adjustPowerState();
1128 // cancel any pending idle sleep
1129 if(rootDomain
->idleSleepPending
)
1131 thread_call_cancel(rootDomain
->extraSleepTimer
);
1132 rootDomain
->idleSleepPending
= false;
1135 // Change the spindown value back to the user's selection from our accelerated setting
1136 if(0 != rootDomain
->user_spindown
)
1137 rootDomain
->restoreUserSpinDownTimeout();
1139 // Put on the policy maker's on clamp.
1146 return kIOReturnUnsupported
;
1149 //*********************************************************************************
1150 // displayWranglerPublished
1152 // Receives a notification when the IODisplayWrangler is published.
1153 // When it's published we install a power state change handler.
1155 //*********************************************************************************
1157 bool IOPMrootDomain::displayWranglerPublished( void * target
, void * refCon
,
1158 IOService
* newService
)
1160 IOPMrootDomain
* rootDomain
= OSDynamicCast(IOPMrootDomain
, (IOService
*)target
);
1165 rootDomain
->wrangler
= newService
;
1167 // we found the display wrangler, now install a handler
1168 if( !rootDomain
->wrangler
->registerInterest( gIOGeneralInterest
, &displayWranglerNotification
, target
, 0) ) {
1169 IOLog("IOPMrootDomain::displayWranglerPublished registerInterest failed\n");
1177 //*********************************************************************************
1180 // Some condition that affects our wake/sleep/doze decision has changed.
1182 // If the sleep slider is in the off position, we cannot sleep or doze.
1183 // If the enclosure is open, we cannot sleep or doze.
1184 // If the system is still booting, we cannot sleep or doze.
1186 // In those circumstances, we prevent sleep and doze by holding power on with
1187 // changePowerStateToPriv(ON).
1189 // If the above conditions do not exist, and also the sleep timer has expired, we
1190 // allow sleep or doze to occur with either changePowerStateToPriv(SLEEP) or
1191 // changePowerStateToPriv(DOZE) depending on whether or not we already know the
1192 // platform cannot sleep.
1194 // In this case, sleep or doze will either occur immediately or at the next time
1195 // that no children are holding the system out of idle sleep via the
1196 // kIOPMPreventIdleSleep flag in their power state arrays.
1197 //*********************************************************************************
1199 void IOPMrootDomain::adjustPowerState( void )
1201 if ( (sleepSlider
== 0) ||
1204 changePowerStateToPriv(ON_STATE
);
1209 if ( sleepIsSupported
)
1211 changePowerStateToPriv(SLEEP_STATE
);
1213 changePowerStateToPriv(DOZE_STATE
);
1220 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1223 #define super IOService
1225 OSDefineMetaClassAndStructors(IORootParent
, IOService
)
1227 // This array exactly parallels the state array for the root domain.
1228 // Power state changes initiated by a device can be vetoed by a client of the device, and
1229 // power state changes initiated by the parent of a device cannot be vetoed by a client of the device,
1230 // so when the root domain wants a power state change that cannot be vetoed (e.g. demand sleep), it asks
1231 // its parent to make the change. That is the reason for this complexity.
1233 static IOPMPowerState patriarchPowerStates
[number_of_power_states
] = {
1234 {1,0,0,0,0,0,0,0,0,0,0,0}, // off
1235 {1,0,RESTART_POWER
,0,0,0,0,0,0,0,0,0}, // reset
1236 {1,0,SLEEP_POWER
,0,0,0,0,0,0,0,0,0}, // sleep
1237 {1,0,DOZE_POWER
,0,0,0,0,0,0,0,0,0}, // doze
1238 {1,0,ON_POWER
,0,0,0,0,0,0,0,0,0} // running
1241 bool IORootParent::start ( IOService
* nub
)
1243 mostRecentChange
= ON_STATE
;
1246 registerPowerDriver(this,patriarchPowerStates
,number_of_power_states
);
1247 powerOverrideOnPriv();
1252 void IORootParent::shutDownSystem ( void )
1254 mostRecentChange
= OFF_STATE
;
1255 changePowerStateToPriv(OFF_STATE
);
1259 void IORootParent::restartSystem ( void )
1261 mostRecentChange
= RESTART_STATE
;
1262 changePowerStateToPriv(RESTART_STATE
);
1266 void IORootParent::sleepSystem ( void )
1268 mostRecentChange
= SLEEP_STATE
;
1269 changePowerStateToPriv(SLEEP_STATE
);
1273 void IORootParent::dozeSystem ( void )
1275 mostRecentChange
= DOZE_STATE
;
1276 changePowerStateToPriv(DOZE_STATE
);
1279 // Called in demand sleep when sleep discovered to be impossible after actually attaining that state.
1280 // This brings the parent to doze, which allows the root to step up from sleep to doze.
1282 // In idle sleep, do nothing because the parent is still on and the root can freely change state.
1284 void IORootParent::sleepToDoze ( void )
1286 if ( mostRecentChange
== SLEEP_STATE
) {
1287 changePowerStateToPriv(DOZE_STATE
);
1292 void IORootParent::wakeSystem ( void )
1294 mostRecentChange
= ON_STATE
;
1295 changePowerStateToPriv(ON_STATE
);