]> git.saurik.com Git - apple/xnu.git/blame - iokit/Kernel/IOPMrootDomain.cpp
xnu-517.3.15.tar.gz
[apple/xnu.git] / iokit / Kernel / IOPMrootDomain.cpp
CommitLineData
9bccf70c 1 /*
1c79356b
A
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
43866e37 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
1c79356b 7 *
43866e37
A
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
13 * file.
14 *
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
1c79356b
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
43866e37
A
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.
1c79356b
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25#include <IOKit/IOWorkLoop.h>
9bccf70c 26#include <IOKit/IOCommandGate.h>
1c79356b
A
27#include <IOKit/IOTimerEventSource.h>
28#include <IOKit/IOPlatformExpert.h>
9bccf70c
A
29#include <IOKit/IOKitDebug.h>
30#include <IOKit/IOTimeStamp.h>
1c79356b 31#include <IOKit/pwr_mgt/RootDomain.h>
d52fe63f 32#include <IOKit/pwr_mgt/IOPMPrivate.h>
1c79356b
A
33#include <IOKit/IOMessage.h>
34#include "RootDomainUserClient.h"
0b4e3aa0 35#include "IOKit/pwr_mgt/IOPowerConnection.h"
55e303ae 36#include "IOPMPowerStateQueue.h"
1c79356b 37
d52fe63f 38extern "C" void kprintf(const char *, ...);
1c79356b
A
39
40extern const IORegistryPlane * gIOPowerPlane;
41
9bccf70c
A
42// debug trace function
43static inline void
44ioSPMTrace(unsigned int csc,
45 unsigned int a = 0, unsigned int b = 0,
46 unsigned int c = 0, unsigned int d = 0)
47{
48 if (gIOKitDebug & kIOLogTracePower)
49 IOTimeStampConstant(IODBG_POWER(csc), a, b, c, d);
50}
51
52IOReturn broadcast_aggressiveness ( OSObject *, void *, void *, void *, void * );
0b4e3aa0 53static void sleepTimerExpired(thread_call_param_t);
d52fe63f 54static void wakeupClamshellTimerExpired ( thread_call_param_t us);
1c79356b
A
55
56
0b4e3aa0 57#define number_of_power_states 5
1c79356b 58#define OFF_STATE 0
0b4e3aa0
A
59#define RESTART_STATE 1
60#define SLEEP_STATE 2
61#define DOZE_STATE 3
62#define ON_STATE 4
1c79356b 63
0b4e3aa0
A
64#define ON_POWER kIOPMPowerOn
65#define RESTART_POWER kIOPMRestart
66#define SLEEP_POWER kIOPMAuxPowerOn
67#define DOZE_POWER kIOPMDoze
1c79356b
A
68
69static IOPMPowerState ourPowerStates[number_of_power_states] = {
0b4e3aa0
A
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
1c79356b
A
75};
76
77static IOPMrootDomain * gRootDomain;
0b4e3aa0
A
78static UInt32 gSleepOrShutdownPending = 0;
79
1c79356b
A
80
81#define super IOService
82OSDefineMetaClassAndStructors(IOPMrootDomain,IOService)
83
84extern "C"
85{
86 IONotifier * registerSleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref = 0)
87 {
88 return gRootDomain->registerInterest( gIOGeneralInterest, handler, self, ref );
89 }
90
0b4e3aa0
A
91 IONotifier * registerPrioritySleepWakeInterest(IOServiceInterestHandler handler, void * self, void * ref = 0)
92 {
93 return gRootDomain->registerInterest( gIOPriorityPowerStateInterest, handler, self, ref );
94 }
95
1c79356b
A
96 IOReturn acknowledgeSleepWakeNotification(void * PMrefcon)
97 {
98 return gRootDomain->allowPowerChange ( (unsigned long)PMrefcon );
99 }
100
0b4e3aa0
A
101 IOReturn vetoSleepWakeNotification(void * PMrefcon)
102 {
103 return gRootDomain->cancelPowerChange ( (unsigned long)PMrefcon );
104 }
105
106 IOReturn rootDomainRestart ( void )
107 {
108 return gRootDomain->restartSystem();
109 }
110
111 IOReturn rootDomainShutdown ( void )
112 {
113 return gRootDomain->shutdownSystem();
114 }
115
116 void IOSystemShutdownNotification ( void )
117 {
118 for ( int i = 0; i < 100; i++ )
119 {
120 if ( OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending ) ) break;
121 IOSleep( 100 );
122 }
123 }
124
125 int sync_internal(void);
1c79356b
A
126}
127
0b4e3aa0
A
128/*
129A device is always in the highest power state which satisfies its driver, its policy-maker, and any power domain
130children it has, but within the constraint of the power state provided by its parent. The driver expresses its desire by
131calling changePowerStateTo(), the policy-maker expresses its desire by calling changePowerStateToPriv(), and the children
132express their desires by calling requestPowerDomainState().
133
134The Root Power Domain owns the policy for idle and demand sleep and doze for the system. It is a power-managed IOService just
135like the others in the system. It implements several power states which correspond to what we see as Sleep, Doze, etc.
136
137The sleep/doze policy is as follows:
138Sleep and Doze are prevented if the case is open so that nobody will think the machine is off and plug/unplug cards.
139Sleep and Doze are prevented if the sleep timeout slider in the preferences panel is at zero.
140The system cannot Sleep, but can Doze if some object in the tree is in a power state marked kIOPMPreventSystemSleep.
141
142These three conditions are enforced using the "driver clamp" by calling changePowerStateTo(). For example, if the case is
143opened, changePowerStateTo(ON_STATE) is called to hold the system on regardless of the desires of the children of the root or
144the state of the other clamp.
145
146Demand Sleep/Doze is initiated by pressing the front panel power button, closing the clamshell, or selecting the menu item.
147In this case the root's parent actually initiates the power state change so that the root has no choice and does not give
148applications the opportunity to veto the change.
149
150Idle Sleep/Doze occurs if no objects in the tree are in a state marked kIOPMPreventIdleSleep. When this is true, the root's
151children are not holding the root on, so it sets the "policy-maker clamp" by calling changePowerStateToPriv(ON_STATE)
152to hold itself on until the sleep timer expires. This timer is set for the difference between the sleep timeout slider and
153the larger of the display dim timeout slider and the disk spindown timeout slider in the Preferences panel. For example, if
154the system is set to sleep after thirty idle minutes, and the display and disk are set to sleep after five idle minutes,
155when there is no longer an object in the tree holding the system out of Idle Sleep (via kIOPMPreventIdleSleep), the root
156sets its timer for 25 minutes (30 - 5). When the timer expires, it releases its clamp and now nothing is holding it awake,
157so it falls asleep.
158
159Demand sleep is prevented when the system is booting. When preferences are transmitted by the loginwindow at the end of
160boot, a flag is cleared, and this allows subsequent Demand Sleep.
161
162The 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
163a clamp, but sets a flag which is noticed before actually sleeping the kernel. If the flag is set, the root steps up
164one power state from Sleep to Doze, and any objects in the tree for which this is relevent will act appropriately (USB and
165ADB will turn on again so that they can wake the system out of Doze (keyboard/mouse activity will cause the Display Wrangler
166to be tickled)).
167*/
168
169
170// **********************************************************************************
171
172IOPMrootDomain * IOPMrootDomain::construct( void )
173{
55e303ae 174 IOPMrootDomain *root;
0b4e3aa0
A
175
176 root = new IOPMrootDomain;
177 if( root)
178 root->init();
179
180 return( root );
181}
182
183// **********************************************************************************
184
185static void disk_sync_callout(thread_call_param_t p0, thread_call_param_t p1)
186{
55e303ae
A
187 IOService *rootDomain = (IOService *) p0;
188 unsigned long pmRef = (unsigned long) p1;
0b4e3aa0
A
189
190 sync_internal();
191 rootDomain->allowPowerChange(pmRef);
192}
1c79356b
A
193
194// **********************************************************************************
195// start
196//
197// We don't do much here. The real initialization occurs when the platform
198// expert informs us we are the root.
199// **********************************************************************************
0b4e3aa0
A
200
201
1c79356b
A
202bool IOPMrootDomain::start ( IOService * nub )
203{
55e303ae
A
204 OSDictionary *tmpDict;
205
206 pmPowerStateQueue = 0;
d52fe63f 207
1c79356b
A
208 super::start(nub);
209
210 gRootDomain = this;
211
212 PMinit();
0b4e3aa0 213 setProperty("IOSleepSupported","");
1c79356b 214 allowSleep = true;
0b4e3aa0 215 sleepIsSupported = true;
1c79356b 216 systemBooting = true;
0b4e3aa0
A
217 ignoringClamshell = true;
218 sleepSlider = 0;
219 idleSleepPending = false;
220 canSleep = true;
221 wrangler = NULL;
222 sleepASAP = false;
d52fe63f 223 ignoringClamshellDuringWakeup = false;
0b4e3aa0 224
d52fe63f
A
225 tmpDict = OSDictionary::withCapacity(1);
226 setProperty(kRootDomainSupportedFeatures, tmpDict);
227 tmpDict->release();
228
55e303ae
A
229 pm_vars->PMworkloop = IOWorkLoop::workLoop();
230 pmPowerStateQueue = IOPMPowerStateQueue::PMPowerStateQueue(this);
231 pm_vars->PMworkloop->addEventSource(pmPowerStateQueue);
232
0b4e3aa0 233 extraSleepTimer = thread_call_allocate((thread_call_func_t)sleepTimerExpired, (thread_call_param_t) this);
d52fe63f 234 clamshellWakeupIgnore = thread_call_allocate((thread_call_func_t)wakeupClamshellTimerExpired, (thread_call_param_t) this);
0b4e3aa0 235 diskSyncCalloutEntry = thread_call_allocate(&disk_sync_callout, (thread_call_param_t) this);
1c79356b 236
55e303ae
A
237 // create our parent
238 patriarch = new IORootParent;
1c79356b
A
239 patriarch->init();
240 patriarch->attach(this);
241 patriarch->start(this);
242 patriarch->youAreRoot();
243 patriarch->wakeSystem();
244 patriarch->addPowerChild(this);
245
246 registerPowerDriver(this,ourPowerStates,number_of_power_states);
247
0b4e3aa0 248 setPMRootDomain(this);
55e303ae
A
249 // set a clamp until we sleep
250 changePowerStateToPriv(ON_STATE);
0b4e3aa0 251
55e303ae
A
252 // install power change handler
253 registerPrioritySleepWakeInterest( &sysPowerDownHandler, this, 0);
0b4e3aa0
A
254
255 // Register for a notification when IODisplayWrangler is published
256 addNotification( gIOPublishNotification, serviceMatching("IODisplayWrangler"), &displayWranglerPublished, this, 0);
1c79356b 257
55e303ae
A
258 const OSSymbol *ucClassName = OSSymbol::withCStringNoCopy("RootDomainUserClient");
259 setProperty(gIOUserClientClassKey, (OSMetaClassBase *) ucClassName);
260 ucClassName->release();
261
1c79356b
A
262 registerService(); // let clients find us
263
264 return true;
265}
266
9bccf70c
A
267// **********************************************************************************
268// setProperties
269//
270// Receive a setProperty call
271// The "System Boot" property means the system is completely booted.
272// **********************************************************************************
273IOReturn IOPMrootDomain::setProperties ( OSObject *props_obj)
274{
55e303ae
A
275 OSDictionary *dict = OSDynamicCast(OSDictionary, props_obj);
276 OSBoolean *b;
4a249263
A
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");
9bccf70c
A
280
281 if(!dict) return kIOReturnBadArgument;
282
4a249263
A
283
284
285 if(systemBooting && dict->getObject(boot_complete_string))
55e303ae 286 {
9bccf70c 287 systemBooting = false;
55e303ae 288 //kprintf("IOPM: received System Boot Complete property\n");
9bccf70c
A
289 adjustPowerState();
290 }
291
4a249263
A
292 if(b = dict->getObject(power_button_string))
293 {
294 setProperty(power_button_string, b);
295 }
296
297 if(b = dict->getObject(stall_halt_string))
55e303ae 298 {
4a249263 299 setProperty(stall_halt_string, b);
55e303ae 300 }
4a249263
A
301
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();
55e303ae 305
9bccf70c
A
306 return kIOReturnSuccess;
307}
308
1c79356b
A
309
310//*********************************************************************************
311// youAreRoot
312//
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
316// no effect
317//*********************************************************************************
318IOReturn IOPMrootDomain::youAreRoot ( void )
319{
320 return IOPMNoErr;
321}
322
1c79356b
A
323// **********************************************************************************
324// command_received
325//
9bccf70c 326// No longer used
1c79356b 327// **********************************************************************************
9bccf70c 328void IOPMrootDomain::command_received ( void * w, void * x, void * y, void * z )
1c79356b 329{
9bccf70c
A
330 super::command_received(w,x,y,z);
331}
0b4e3aa0 332
0b4e3aa0 333
9bccf70c
A
334// **********************************************************************************
335// broadcast_aggressiveness
336//
337// **********************************************************************************
338IOReturn broadcast_aggressiveness ( OSObject * root, void * x, void * y, void *, void * )
339{
340 ((IOPMrootDomain *)root)->broadcast_it((unsigned long)x,(unsigned long)y);
341 return IOPMNoErr;
342}
0b4e3aa0
A
343
344
9bccf70c
A
345// **********************************************************************************
346// broadcast_it
347//
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// **********************************************************************************
351void IOPMrootDomain::broadcast_it (unsigned long type, unsigned long value)
352{
353 super::setAggressiveness(type,value);
354
355 // Save user's spin down timer to restore after we replace it for idle sleep
356 if( type == kPMMinutesToSpinDown ) user_spindown = value;
357
358 // Use longestNonSleepSlider to calculate dimming adjust idle sleep timer
359 longestNonSleepSlider = pm_vars->current_aggressiveness_values[kPMMinutesToDim];
360
361
362 if ( type == kPMMinutesToSleep ) {
363 if ( (sleepSlider == 0) && (value != 0) ) {
364 sleepSlider = value;
55e303ae
A
365 // idle sleep is now enabled, maybe sleep now
366 adjustPowerState();
9bccf70c
A
367 }
368 sleepSlider = value;
369 if ( sleepSlider == 0 ) {
55e303ae
A
370 // idle sleep is now disabled
371 adjustPowerState();
372 // make sure we're powered
373 patriarch->wakeSystem();
9bccf70c
A
374 }
375 }
376 if ( sleepSlider > longestNonSleepSlider ) {
377 extraSleepDelay = sleepSlider - longestNonSleepSlider ;
378 }
379 else {
380 extraSleepDelay = 0;
1c79356b
A
381 }
382}
383
384
0b4e3aa0
A
385// **********************************************************************************
386// sleepTimerExpired
387//
388// **********************************************************************************
389static void sleepTimerExpired ( thread_call_param_t us)
390{
391 ((IOPMrootDomain *)us)->handleSleepTimerExpiration();
392 }
393
d52fe63f
A
394
395static void wakeupClamshellTimerExpired ( thread_call_param_t us)
396{
397 ((IOPMrootDomain *)us)->stopIgnoringClamshellEventsDuringWakeup();
398}
399
0b4e3aa0
A
400
401// **********************************************************************************
402// handleSleepTimerExpiration
403//
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// **********************************************************************************
407void IOPMrootDomain::handleSleepTimerExpiration ( void )
408{
409 // accelerate disk spin down if spin down timer is non-zero (zero = never spin down)
410 if(0 != user_spindown)
411 setQuickSpinDownTimeout();
412
413 sleepASAP = true;
414 adjustPowerState();
415}
416
417
d52fe63f
A
418void IOPMrootDomain::stopIgnoringClamshellEventsDuringWakeup(void)
419{
420 OSObject * state;
421
422 // Allow clamshell-induced sleep now
423 ignoringClamshellDuringWakeup = false;
424
425 if ((state = getProperty(kAppleClamshellStateKey)))
426 publishResource(kAppleClamshellStateKey, state);
427}
428
1c79356b
A
429//*********************************************************************************
430// setAggressiveness
431//
9bccf70c 432// Some aggressiveness factor has changed. We broadcast it to the hierarchy while on
1c79356b
A
433// the Power Mangement workloop thread. This enables objects in the
434// hierarchy to successfully alter their idle timers, which are all on the
435// same thread.
436//*********************************************************************************
437
438IOReturn IOPMrootDomain::setAggressiveness ( unsigned long type, unsigned long newLevel )
439{
9bccf70c
A
440 if ( pm_vars->PMcommandGate ) {
441 pm_vars->PMcommandGate->runAction(broadcast_aggressiveness,(void *)type,(void *)newLevel);
0b4e3aa0 442 }
1c79356b
A
443
444 return kIOReturnSuccess;
445}
446
447
448// **********************************************************************************
449// sleepSystem
450//
451// **********************************************************************************
452IOReturn IOPMrootDomain::sleepSystem ( void )
453{
55e303ae 454 //kprintf("sleep demand received\n");
1c79356b
A
455 if ( !systemBooting && allowSleep && sleepIsSupported ) {
456 patriarch->sleepSystem();
0b4e3aa0 457 return kIOReturnSuccess;
1c79356b 458 }
0b4e3aa0
A
459 if ( !systemBooting && allowSleep && !sleepIsSupported ) {
460 patriarch->dozeSystem();
461 return kIOReturnSuccess;
462 }
463 return kIOReturnSuccess;
464}
465
466
467// **********************************************************************************
468// shutdownSystem
469//
470// **********************************************************************************
471IOReturn IOPMrootDomain::shutdownSystem ( void )
472{
55e303ae
A
473 //patriarch->shutDownSystem();
474 return kIOReturnUnsupported;
0b4e3aa0
A
475}
476
477
478// **********************************************************************************
479// restartSystem
480//
481// **********************************************************************************
482IOReturn IOPMrootDomain::restartSystem ( void )
483{
55e303ae
A
484 //patriarch->restartSystem();
485 return kIOReturnUnsupported;
1c79356b
A
486}
487
488
489// **********************************************************************************
490// powerChangeDone
491//
492// This overrides powerChangeDone in IOService.
0b4e3aa0
A
493//
494// Finder sleep and idle sleep move us from the ON state to the SLEEP_STATE.
495// In this case:
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.
499//
500// **********************************************************************************
501void IOPMrootDomain::powerChangeDone ( unsigned long previousState )
502{
503 OSNumber * propertyPtr;
504 unsigned short theProperty;
505 AbsoluteTime deadline;
506
507 switch ( pm_vars->myCurrentState ) {
508 case SLEEP_STATE:
55e303ae
A
509 if ( canSleep && sleepIsSupported )
510 {
511 // re-enable this timer for next sleep
512 idleSleepPending = false;
0b4e3aa0 513 IOLog("System Sleep\n");
55e303ae 514 pm_vars->thePlatform->sleepKernel();
9bccf70c 515
55e303ae
A
516 // The CPU(s) are off at this point. When they're awakened by CPU interrupt,
517 // code will resume exeuction here.
518
519 // Now we're waking...
520 ioSPMTrace(IOPOWER_WAKE, * (int *) this);
9bccf70c 521
55e303ae
A
522 // stay awake for at least 30 seconds
523 clock_interval_to_deadline(30, kSecondScale, &deadline);
0b4e3aa0 524 thread_call_enter_delayed(extraSleepTimer, deadline);
55e303ae
A
525 // this gets turned off when we sleep again
526 idleSleepPending = true;
d52fe63f
A
527
528 // Ignore closed clamshell during wakeup and for a few seconds
529 // after wakeup is complete
530 ignoringClamshellDuringWakeup = true;
531
55e303ae
A
532 // sleep transition complete
533 gSleepOrShutdownPending = 0;
534
535 // trip the reset of the calendar clock
536 clock_wakeup_calendar();
537
538 // get us some power
539 patriarch->wakeSystem();
0b4e3aa0 540
55e303ae
A
541 // early stage wake notification
542 tellClients(kIOMessageSystemWillPowerOn);
543
544 // tell the tree we're waking
0b4e3aa0 545 IOLog("System Wake\n");
55e303ae 546 systemWake();
d52fe63f
A
547
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;
55e303ae
A
556
557 // Find out what woke us
0b4e3aa0 558 propertyPtr = OSDynamicCast(OSNumber,getProperty("WakeEvent"));
55e303ae 559 if ( propertyPtr ) {
0b4e3aa0
A
560 theProperty = propertyPtr->unsigned16BitValue();
561 IOLog("Wake event %04x\n",theProperty);
43866e37
A
562 if ( (theProperty & 0x0008) || //lid
563 (theProperty & 0x0800) || // front panel button
564 (theProperty & 0x0020) || // external keyboard
565 (theProperty & 0x0001) ) { // internal keyboard
55e303ae
A
566 // We've identified the wakeup event as UI driven
567 reportUserInput();
0b4e3aa0 568 }
55e303ae
A
569 } else {
570 // Since we can't identify the wakeup event, treat it as UI activity
571 reportUserInput();
0b4e3aa0 572 }
55e303ae
A
573
574 // Wake for thirty seconds
575 changePowerStateToPriv(ON_STATE);
0b4e3aa0 576 powerOverrideOffPriv();
55e303ae
A
577 } else {
578 // allow us to step up a power state
579 patriarch->sleepToDoze();
580 // and do it
581 changePowerStateToPriv(DOZE_STATE);
0b4e3aa0
A
582 }
583 break;
584
585 case DOZE_STATE:
55e303ae
A
586 if ( previousState != DOZE_STATE )
587 {
0b4e3aa0
A
588 IOLog("System Doze\n");
589 }
55e303ae
A
590 // re-enable this timer for next sleep
591 idleSleepPending = false;
0b4e3aa0
A
592 gSleepOrShutdownPending = 0;
593 break;
594
595 case RESTART_STATE:
596 IOLog("System Restart\n");
597 PEHaltRestart(kPERestartCPU);
598 break;
599
600 case OFF_STATE:
601 IOLog("System Halt\n");
602 PEHaltRestart(kPEHaltCPU);
603 break;
604 }
605}
606
607
608// **********************************************************************************
609// wakeFromDoze
610//
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
613// providing power.
1c79356b 614// **********************************************************************************
0b4e3aa0 615void IOPMrootDomain::wakeFromDoze( void )
1c79356b 616{
55e303ae
A
617 if ( pm_vars->myCurrentState == DOZE_STATE )
618 {
619 // reset this till next attempt
620 canSleep = true;
0b4e3aa0 621 powerOverrideOffPriv();
55e303ae
A
622
623 // early wake notification
624 tellClients(kIOMessageSystemWillPowerOn);
625
626 // allow us to wake if children so desire
627 patriarch->wakeSystem();
1c79356b
A
628 }
629}
630
631
d52fe63f
A
632// **********************************************************************************
633// publishFeature
634//
635// Adds a new feature to the supported features dictionary
636//
637//
638// **********************************************************************************
639void IOPMrootDomain::publishFeature( const char * feature )
640{
641 OSDictionary *features = (OSDictionary *)getProperty(kRootDomainSupportedFeatures);
642
643 features->setObject(feature, kOSBooleanTrue);
644}
645
55e303ae 646void IOPMrootDomain::unIdleDevice( IOService *theDevice, unsigned long theState )
1c79356b 647{
55e303ae
A
648 if(pmPowerStateQueue)
649 pmPowerStateQueue->unIdleOccurred(theDevice, theState);
650}
1c79356b 651
55e303ae
A
652void IOPMrootDomain::announcePowerSourceChange( void )
653{
654 messageClients(kIOPMMessageBatteryStatusHasChanged);
1c79356b
A
655}
656
657//*********************************************************************************
658// receivePowerNotification
659//
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//*********************************************************************************
664
665IOReturn IOPMrootDomain::receivePowerNotification (UInt32 msg)
666{
55e303ae
A
667 if (msg & kIOPMOverTemp)
668 {
9bccf70c
A
669 IOLog("Power Management received emergency overtemp signal. Going to sleep.");
670 (void) sleepSystem ();
671 }
55e303ae
A
672 if (msg & kIOPMSetDesktopMode)
673 {
d52fe63f
A
674 desktopMode = (0 != (msg & kIOPMSetValue));
675 msg &= ~(kIOPMSetDesktopMode | kIOPMSetValue);
676 }
55e303ae
A
677 if (msg & kIOPMSetACAdaptorConnected)
678 {
d52fe63f
A
679 acAdaptorConnect = (0 != (msg & kIOPMSetValue));
680 msg &= ~(kIOPMSetACAdaptorConnected | kIOPMSetValue);
681 }
55e303ae
A
682 if (msg & kIOPMEnableClamshell)
683 {
d52fe63f
A
684 ignoringClamshell = false;
685 }
55e303ae
A
686 if (msg & kIOPMDisableClamshell)
687 {
d52fe63f
A
688 ignoringClamshell = true;
689 }
690
55e303ae
A
691 if (msg & kIOPMProcessorSpeedChange)
692 {
693 IOService *pmu = waitForService(serviceMatching("ApplePMU"));
694 pmu->callPlatformFunction("prepareForSleep", false, 0, 0, 0, 0);
d52fe63f 695 pm_vars->thePlatform->sleepKernel();
55e303ae 696 pmu->callPlatformFunction("recoverFromSleep", false, 0, 0, 0, 0);
d52fe63f
A
697 }
698
55e303ae
A
699 if (msg & kIOPMSleepNow)
700 {
1c79356b
A
701 (void) sleepSystem ();
702 }
703
55e303ae
A
704 if (msg & kIOPMPowerEmergency)
705 {
1c79356b
A
706 (void) sleepSystem ();
707 }
708
55e303ae
A
709 if (msg & kIOPMClamshellClosed)
710 {
d52fe63f 711 if ( !ignoringClamshell && !ignoringClamshellDuringWakeup
55e303ae
A
712 && (!desktopMode || !acAdaptorConnect) )
713 {
d52fe63f
A
714
715 (void) sleepSystem ();
716 }
1c79356b
A
717 }
718
55e303ae
A
719 if (msg & kIOPMPowerButton)
720 {
721 // toggle state of sleep/wake
722 // are we dozing?
723 if ( pm_vars->myCurrentState == DOZE_STATE )
724 {
725 // yes, tell the tree we're waking
726 systemWake();
727 // wake the Display Wrangler
728 reportUserInput();
0b4e3aa0
A
729 }
730 else {
55e303ae
A
731 // Check that power button sleep is enabled
732 if(kOSBooleanTrue != getProperty(OSString::withCString("DisablePowerButtonSleep")))
733 sleepSystem();
1c79356b 734 }
0b4e3aa0
A
735 }
736
737 // if the case has been closed, we allow
738 // the machine to be put to sleep or to idle sleep
739
55e303ae
A
740 if ( (msg & kIOPMAllowSleep) && !allowSleep )
741 {
742 allowSleep = true;
0b4e3aa0 743 adjustPowerState();
1c79356b
A
744 }
745
0b4e3aa0 746 // if the case has been opened, we disallow sleep/doze
1c79356b
A
747
748 if (msg & kIOPMPreventSleep) {
55e303ae
A
749 allowSleep = false;
750 // are we dozing?
751 if ( pm_vars->myCurrentState == DOZE_STATE ) {
752 // yes, tell the tree we're waking
753 systemWake();
0b4e3aa0 754 adjustPowerState();
55e303ae
A
755 // wake the Display Wrangler
756 reportUserInput();
757 } else {
0b4e3aa0 758 adjustPowerState();
55e303ae
A
759 // make sure we have power to clamp
760 patriarch->wakeSystem();
0b4e3aa0 761 }
1c79356b
A
762 }
763
764 return 0;
765}
766
767
768//*********************************************************************************
769// sleepSupported
770//
771//*********************************************************************************
772
773void IOPMrootDomain::setSleepSupported( IOOptionBits flags )
774{
55e303ae
A
775 if ( flags & kPCICantSleep )
776 {
0b4e3aa0 777 canSleep = false;
55e303ae 778 } else {
0b4e3aa0
A
779 platformSleepSupport = flags;
780 }
781
782}
783
784//*********************************************************************************
785// requestPowerDomainState
786//
787// The root domain intercepts this call to the superclass.
788//
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//*********************************************************************************
795
796IOReturn IOPMrootDomain::requestPowerDomainState ( IOPMPowerFlags desiredState, IOPowerConnection * whichChild, unsigned long specification )
797{
55e303ae
A
798 OSIterator *iter;
799 OSObject *next;
800 IOPowerConnection *connection;
801 unsigned long powerRequestFlag = 0;
802 IOPMPowerFlags editedDesire = desiredState;
803
804 // if they don't really need it, they don't get it
805 if ( !(desiredState & kIOPMPreventIdleSleep) ) {
0b4e3aa0
A
806 editedDesire = 0;
807 }
808
809
55e303ae
A
810 IOLockLock(pm_vars->childLock);
811
812 // recompute sleepIsSupported and see if all children are asleep
0b4e3aa0
A
813 iter = getChildIterator(gIOPowerPlane);
814 sleepIsSupported = true;
55e303ae
A
815 if ( iter )
816 {
817 while ( (next = iter->getNextObject()) )
818 {
819 if ( (connection = OSDynamicCast(IOPowerConnection,next)) )
820 {
821 if ( connection == whichChild )
822 {
0b4e3aa0 823 powerRequestFlag += editedDesire;
55e303ae
A
824 if ( desiredState & kIOPMPreventSystemSleep )
825 {
0b4e3aa0
A
826 sleepIsSupported = false;
827 }
55e303ae 828 } else {
0b4e3aa0 829 powerRequestFlag += connection->getDesiredDomainState();
55e303ae
A
830 if ( connection->getPreventSystemSleepFlag() )
831 {
0b4e3aa0
A
832 sleepIsSupported = false;
833 }
834 }
835 }
836 }
837 iter->release();
838 }
9bccf70c 839
55e303ae
A
840 if ( (extraSleepDelay == 0) && (powerRequestFlag == 0) )
841 {
0b4e3aa0 842 sleepASAP = true;
1c79356b 843 }
0b4e3aa0 844
55e303ae
A
845 // this may put the system to sleep
846 adjustPowerState();
0b4e3aa0
A
847
848 IOLockUnlock(pm_vars->childLock);
849
850 editedDesire |= desiredState & kIOPMPreventSystemSleep;
1c79356b 851
0b4e3aa0 852 return super::requestPowerDomainState(editedDesire,whichChild,specification);
1c79356b
A
853}
854
0b4e3aa0 855
1c79356b
A
856//*********************************************************************************
857// getSleepSupported
858//
859//*********************************************************************************
860
861IOOptionBits IOPMrootDomain::getSleepSupported( void )
862{
863 return( platformSleepSupport );
864}
865
866
867//*********************************************************************************
868// tellChangeDown
869//
870// We override the superclass implementation so we can send a different message
871// type to the client or application being notified.
872//*********************************************************************************
873
874bool IOPMrootDomain::tellChangeDown ( unsigned long stateNum )
875{
0b4e3aa0
A
876 switch ( stateNum ) {
877 case DOZE_STATE:
878 case SLEEP_STATE:
879 return super::tellClientsWithResponse(kIOMessageSystemWillSleep);
880 case RESTART_STATE:
881 return super::tellClientsWithResponse(kIOMessageSystemWillRestart);
882 case OFF_STATE:
883 return super::tellClientsWithResponse(kIOMessageSystemWillPowerOff);
1c79356b 884 }
55e303ae
A
885 // this shouldn't execute
886 return super::tellChangeDown(stateNum);
1c79356b
A
887}
888
889
890//*********************************************************************************
891// askChangeDown
892//
893// We override the superclass implementation so we can send a different message
894// type to the client or application being notified.
0b4e3aa0
A
895//
896// This must be idle sleep since we don't ask apps during any other power change.
1c79356b
A
897//*********************************************************************************
898
0b4e3aa0 899bool IOPMrootDomain::askChangeDown ( unsigned long )
1c79356b 900{
0b4e3aa0 901 return super::tellClientsWithResponse(kIOMessageCanSystemSleep);
1c79356b
A
902}
903
904
905//*********************************************************************************
906// tellNoChangeDown
907//
908// Notify registered applications and kernel clients that we are not
909// dropping power.
910//
911// We override the superclass implementation so we can send a different message
912// type to the client or application being notified.
0b4e3aa0
A
913//
914// This must be a vetoed idle sleep, since no other power change can be vetoed.
1c79356b
A
915//*********************************************************************************
916
917void IOPMrootDomain::tellNoChangeDown ( unsigned long )
918{
919 return tellClients(kIOMessageSystemWillNotSleep);
920}
921
922
923//*********************************************************************************
924// tellChangeUp
925//
926// Notify registered applications and kernel clients that we are raising power.
927//
928// We override the superclass implementation so we can send a different message
929// type to the client or application being notified.
930//*********************************************************************************
931
7b1edb79 932void IOPMrootDomain::tellChangeUp ( unsigned long stateNum)
1c79356b 933{
55e303ae
A
934 if ( stateNum == ON_STATE )
935 {
7b1edb79
A
936 return tellClients(kIOMessageSystemHasPoweredOn);
937 }
1c79356b
A
938}
939
0b4e3aa0
A
940//*********************************************************************************
941// reportUserInput
942//
943//*********************************************************************************
944
945void IOPMrootDomain::reportUserInput ( void )
946{
947 OSIterator * iter;
1c79356b 948
55e303ae
A
949 if(!wrangler)
950 {
0b4e3aa0 951 iter = getMatchingServices(serviceMatching("IODisplayWrangler"));
55e303ae
A
952 if(iter)
953 {
0b4e3aa0
A
954 wrangler = (IOService *) iter->getNextObject();
955 iter->release();
956 }
957 }
958
959 if(wrangler)
960 wrangler->activityTickle(0,0);
961}
962
963//*********************************************************************************
964// setQuickSpinDownTimeout
1c79356b 965//
0b4e3aa0
A
966//*********************************************************************************
967
968void IOPMrootDomain::setQuickSpinDownTimeout ( void )
969{
0b4e3aa0
A
970 super::setAggressiveness((unsigned long)kPMMinutesToSpinDown,(unsigned long)1);
971}
972
973//*********************************************************************************
974// restoreUserSpinDownTimeout
975//
976//*********************************************************************************
977
978void IOPMrootDomain::restoreUserSpinDownTimeout ( void )
979{
0b4e3aa0
A
980 super::setAggressiveness((unsigned long)kPMMinutesToSpinDown,(unsigned long)user_spindown);
981}
982
9bccf70c
A
983//*********************************************************************************
984// changePowerStateTo & changePowerStateToPriv
985//
986// Override of these methods for logging purposes.
987//*********************************************************************************
988
989IOReturn IOPMrootDomain::changePowerStateTo ( unsigned long ordinal )
990{
991 ioSPMTrace(IOPOWER_ROOT, * (int *) this, (int) true, (int) ordinal);
992
993 return super::changePowerStateTo(ordinal);
994}
995
996IOReturn IOPMrootDomain::changePowerStateToPriv ( unsigned long ordinal )
997{
998 ioSPMTrace(IOPOWER_ROOT, * (int *) this, (int) false, (int) ordinal);
999
1000 return super::changePowerStateToPriv(ordinal);
1001}
1002
0b4e3aa0
A
1003
1004//*********************************************************************************
1005// sysPowerDownHandler
1006//
1007// Receives a notification when the RootDomain changes state.
1008//
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//*********************************************************************************
1013
1014IOReturn IOPMrootDomain::sysPowerDownHandler( void * target, void * refCon,
1015 UInt32 messageType, IOService * service,
1016 void * messageArgument, vm_size_t argSize )
1017{
55e303ae
A
1018 IOReturn ret;
1019 IOPowerStateChangeNotification *params = (IOPowerStateChangeNotification *) messageArgument;
1020 IOPMrootDomain *rootDomain = OSDynamicCast(IOPMrootDomain, service);
0b4e3aa0
A
1021
1022 if(!rootDomain)
1023 return kIOReturnUnsupported;
1024
1025 switch (messageType) {
1026 case kIOMessageSystemWillSleep:
1027 rootDomain->powerOverrideOnPriv(); // start ignoring children's requests
1028 // (fall through to other cases)
0b4e3aa0
A
1029
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
1033 // down.
1034 // We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c,
1035 // via callout
1036
1037 // We will ack within 20 seconds
1038 params->returnValue = 20 * 1000 * 1000;
1039
1040 if ( ! OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending ) )
1041 {
1042 // Purposely delay the ack and hope that shutdown occurs quickly.
1043 // Another option is not to schedule the thread and wait for
1044 // ack timeout...
1045 AbsoluteTime deadline;
9bccf70c 1046 clock_interval_to_deadline( 30, kSecondScale, &deadline );
0b4e3aa0
A
1047 thread_call_enter1_delayed( rootDomain->diskSyncCalloutEntry,
1048 (thread_call_param_t)params->powerRef,
1049 deadline );
1050 }
1051 else
1052 thread_call_enter1(rootDomain->diskSyncCalloutEntry, (thread_call_param_t)params->powerRef);
1053 ret = kIOReturnSuccess;
1054 break;
fa4905b1
A
1055
1056 case kIOMessageSystemWillPowerOff:
1057 case kIOMessageSystemWillRestart:
d52fe63f 1058 ret = kIOReturnUnsupported;
fa4905b1
A
1059 break;
1060
0b4e3aa0
A
1061 default:
1062 ret = kIOReturnUnsupported;
1063 break;
1064 }
1065 return ret;
1066}
1067
1068//*********************************************************************************
1069// displayWranglerNotification
1070//
1071// Receives a notification when the IODisplayWrangler changes state.
1072//
1073// Allows us to take action on display dim/undim.
1074//
1075// When the display goes dim we:
1076// - Start the idle sleep timer
1077// - set the quick spin down timeout
1078//
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//*********************************************************************************
1c79356b 1083
0b4e3aa0
A
1084IOReturn IOPMrootDomain::displayWranglerNotification( void * target, void * refCon,
1085 UInt32 messageType, IOService * service,
1086 void * messageArgument, vm_size_t argSize )
1c79356b 1087{
0b4e3aa0
A
1088 IOPMrootDomain * rootDomain = OSDynamicCast(IOPMrootDomain, (IOService *)target);
1089 AbsoluteTime deadline;
1090 static bool deviceAlreadyPoweredOff = false;
1091
1092 if(!rootDomain)
1093 return kIOReturnUnsupported;
1094
1095 switch (messageType) {
1096 case kIOMessageDeviceWillPowerOff:
1097 // The IODisplayWrangler has powered off either because of idle display sleep
1098 // or force system sleep.
1099
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;
1103
1104 deviceAlreadyPoweredOff = true;
1105
55e303ae
A
1106 if( rootDomain->extraSleepDelay )
1107 {
0b4e3aa0
A
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;
0b4e3aa0 1112 } else {
0b4e3aa0 1113 // accelerate disk spin down if spin down timer is non-zero (zero = never spin down)
9bccf70c
A
1114 // and if system sleep is non-Never
1115 if( (0 != rootDomain->user_spindown) && (0 != rootDomain->sleepSlider) )
0b4e3aa0
A
1116 rootDomain->setQuickSpinDownTimeout();
1117 }
1118
1119 break;
1120
1121 case kIOMessageDeviceHasPoweredOn:
1122
1123 // The display has powered on either because of UI activity or wake from sleep/doze
1124 deviceAlreadyPoweredOff = false;
1125 rootDomain->adjustPowerState();
1126
1127
1128 // cancel any pending idle sleep
55e303ae
A
1129 if(rootDomain->idleSleepPending)
1130 {
0b4e3aa0
A
1131 thread_call_cancel(rootDomain->extraSleepTimer);
1132 rootDomain->idleSleepPending = false;
1133 }
1134
1135 // Change the spindown value back to the user's selection from our accelerated setting
1136 if(0 != rootDomain->user_spindown)
1137 rootDomain->restoreUserSpinDownTimeout();
1138
1139 // Put on the policy maker's on clamp.
1140
1141 break;
1142
1143 default:
1144 break;
1145 }
1146 return kIOReturnUnsupported;
1147 }
1148
1149//*********************************************************************************
1150// displayWranglerPublished
1151//
1152// Receives a notification when the IODisplayWrangler is published.
1153// When it's published we install a power state change handler.
1154//
1155//*********************************************************************************
1156
1157bool IOPMrootDomain::displayWranglerPublished( void * target, void * refCon,
1158 IOService * newService)
1159{
1160 IOPMrootDomain * rootDomain = OSDynamicCast(IOPMrootDomain, (IOService *)target);
1161
1162 if(!rootDomain)
1163 return false;
1164
55e303ae
A
1165 rootDomain->wrangler = newService;
1166
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");
1170 return false;
1171 }
1172
1173 return true;
1c79356b
A
1174}
1175
1176
0b4e3aa0
A
1177//*********************************************************************************
1178// adjustPowerState
1179//
1180// Some condition that affects our wake/sleep/doze decision has changed.
1181//
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.
1185//
1186// In those circumstances, we prevent sleep and doze by holding power on with
1187// changePowerStateToPriv(ON).
1188//
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.
1193//
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//*********************************************************************************
1198
1199void IOPMrootDomain::adjustPowerState( void )
1200{
1201 if ( (sleepSlider == 0) ||
1202 ! allowSleep ||
1203 systemBooting ) {
1204 changePowerStateToPriv(ON_STATE);
55e303ae
A
1205 } else {
1206 if ( sleepASAP )
1207 {
0b4e3aa0 1208 sleepASAP = false;
55e303ae
A
1209 if ( sleepIsSupported )
1210 {
0b4e3aa0 1211 changePowerStateToPriv(SLEEP_STATE);
55e303ae 1212 } else {
0b4e3aa0
A
1213 changePowerStateToPriv(DOZE_STATE);
1214 }
1215 }
1216 }
1217}
1c79356b
A
1218
1219
1220/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1221
1222#undef super
1223#define super IOService
1224
1225OSDefineMetaClassAndStructors(IORootParent, IOService)
1226
0b4e3aa0
A
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.
1c79356b 1232
0b4e3aa0 1233static IOPMPowerState patriarchPowerStates[number_of_power_states] = {
1c79356b 1234 {1,0,0,0,0,0,0,0,0,0,0,0}, // off
0b4e3aa0 1235 {1,0,RESTART_POWER,0,0,0,0,0,0,0,0,0}, // reset
1c79356b 1236 {1,0,SLEEP_POWER,0,0,0,0,0,0,0,0,0}, // sleep
0b4e3aa0 1237 {1,0,DOZE_POWER,0,0,0,0,0,0,0,0,0}, // doze
1c79356b
A
1238 {1,0,ON_POWER,0,0,0,0,0,0,0,0,0} // running
1239};
1240
1c79356b
A
1241bool IORootParent::start ( IOService * nub )
1242{
0b4e3aa0 1243 mostRecentChange = ON_STATE;
1c79356b
A
1244 super::start(nub);
1245 PMinit();
0b4e3aa0 1246 registerPowerDriver(this,patriarchPowerStates,number_of_power_states);
1c79356b
A
1247 powerOverrideOnPriv();
1248 return true;
1249}
1250
1251
1252void IORootParent::shutDownSystem ( void )
1253{
0b4e3aa0
A
1254 mostRecentChange = OFF_STATE;
1255 changePowerStateToPriv(OFF_STATE);
1256}
1257
1258
1259void IORootParent::restartSystem ( void )
1260{
1261 mostRecentChange = RESTART_STATE;
1262 changePowerStateToPriv(RESTART_STATE);
1c79356b
A
1263}
1264
1265
1266void IORootParent::sleepSystem ( void )
1267{
0b4e3aa0
A
1268 mostRecentChange = SLEEP_STATE;
1269 changePowerStateToPriv(SLEEP_STATE);
1270}
1271
1272
1273void IORootParent::dozeSystem ( void )
1274{
1275 mostRecentChange = DOZE_STATE;
1276 changePowerStateToPriv(DOZE_STATE);
1277}
1278
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.
1281
1282// In idle sleep, do nothing because the parent is still on and the root can freely change state.
1283
1284void IORootParent::sleepToDoze ( void )
1285{
1286 if ( mostRecentChange == SLEEP_STATE ) {
1287 changePowerStateToPriv(DOZE_STATE);
1288 }
1c79356b
A
1289}
1290
1291
1292void IORootParent::wakeSystem ( void )
1293{
0b4e3aa0
A
1294 mostRecentChange = ON_STATE;
1295 changePowerStateToPriv(ON_STATE);
1c79356b
A
1296}
1297