]> git.saurik.com Git - apple/xnu.git/blame - iokit/Kernel/IOPMrootDomain.cpp
xnu-517.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;
9bccf70c
A
277
278 if(!dict) return kIOReturnBadArgument;
279
55e303ae
A
280 if(systemBooting && dict->getObject(OSString::withCString("System Boot Complete")))
281 {
9bccf70c 282 systemBooting = false;
55e303ae 283 //kprintf("IOPM: received System Boot Complete property\n");
9bccf70c
A
284 adjustPowerState();
285 }
286
55e303ae
A
287 if(b = dict->getObject(OSString::withCString("DisablePowerButtonSleep")))
288 {
289 setProperty(OSString::withCString("DisablePowerButtonSleep"), b);
290 }
291
9bccf70c
A
292 return kIOReturnSuccess;
293}
294
1c79356b
A
295
296//*********************************************************************************
297// youAreRoot
298//
299// Power Managment is informing us that we are the root power domain.
300// We know we are not the root however, since we have just instantiated a parent
301// for ourselves and made it the root. We override this method so it will have
302// no effect
303//*********************************************************************************
304IOReturn IOPMrootDomain::youAreRoot ( void )
305{
306 return IOPMNoErr;
307}
308
1c79356b
A
309// **********************************************************************************
310// command_received
311//
9bccf70c 312// No longer used
1c79356b 313// **********************************************************************************
9bccf70c 314void IOPMrootDomain::command_received ( void * w, void * x, void * y, void * z )
1c79356b 315{
9bccf70c
A
316 super::command_received(w,x,y,z);
317}
0b4e3aa0 318
0b4e3aa0 319
9bccf70c
A
320// **********************************************************************************
321// broadcast_aggressiveness
322//
323// **********************************************************************************
324IOReturn broadcast_aggressiveness ( OSObject * root, void * x, void * y, void *, void * )
325{
326 ((IOPMrootDomain *)root)->broadcast_it((unsigned long)x,(unsigned long)y);
327 return IOPMNoErr;
328}
0b4e3aa0
A
329
330
9bccf70c
A
331// **********************************************************************************
332// broadcast_it
333//
334// We are behind the command gate to broadcast an aggressiveness factor. We let the
335// superclass do it, but we need to snoop on factors that affect idle sleep.
336// **********************************************************************************
337void IOPMrootDomain::broadcast_it (unsigned long type, unsigned long value)
338{
339 super::setAggressiveness(type,value);
340
341 // Save user's spin down timer to restore after we replace it for idle sleep
342 if( type == kPMMinutesToSpinDown ) user_spindown = value;
343
344 // Use longestNonSleepSlider to calculate dimming adjust idle sleep timer
345 longestNonSleepSlider = pm_vars->current_aggressiveness_values[kPMMinutesToDim];
346
347
348 if ( type == kPMMinutesToSleep ) {
349 if ( (sleepSlider == 0) && (value != 0) ) {
350 sleepSlider = value;
55e303ae
A
351 // idle sleep is now enabled, maybe sleep now
352 adjustPowerState();
9bccf70c
A
353 }
354 sleepSlider = value;
355 if ( sleepSlider == 0 ) {
55e303ae
A
356 // idle sleep is now disabled
357 adjustPowerState();
358 // make sure we're powered
359 patriarch->wakeSystem();
9bccf70c
A
360 }
361 }
362 if ( sleepSlider > longestNonSleepSlider ) {
363 extraSleepDelay = sleepSlider - longestNonSleepSlider ;
364 }
365 else {
366 extraSleepDelay = 0;
1c79356b
A
367 }
368}
369
370
0b4e3aa0
A
371// **********************************************************************************
372// sleepTimerExpired
373//
374// **********************************************************************************
375static void sleepTimerExpired ( thread_call_param_t us)
376{
377 ((IOPMrootDomain *)us)->handleSleepTimerExpiration();
378 }
379
d52fe63f
A
380
381static void wakeupClamshellTimerExpired ( thread_call_param_t us)
382{
383 ((IOPMrootDomain *)us)->stopIgnoringClamshellEventsDuringWakeup();
384}
385
0b4e3aa0
A
386
387// **********************************************************************************
388// handleSleepTimerExpiration
389//
390// The time between the sleep idle timeout and the next longest one has elapsed.
391// It's time to sleep. Start that by removing the clamp that's holding us awake.
392// **********************************************************************************
393void IOPMrootDomain::handleSleepTimerExpiration ( void )
394{
395 // accelerate disk spin down if spin down timer is non-zero (zero = never spin down)
396 if(0 != user_spindown)
397 setQuickSpinDownTimeout();
398
399 sleepASAP = true;
400 adjustPowerState();
401}
402
403
d52fe63f
A
404void IOPMrootDomain::stopIgnoringClamshellEventsDuringWakeup(void)
405{
406 OSObject * state;
407
408 // Allow clamshell-induced sleep now
409 ignoringClamshellDuringWakeup = false;
410
411 if ((state = getProperty(kAppleClamshellStateKey)))
412 publishResource(kAppleClamshellStateKey, state);
413}
414
1c79356b
A
415//*********************************************************************************
416// setAggressiveness
417//
9bccf70c 418// Some aggressiveness factor has changed. We broadcast it to the hierarchy while on
1c79356b
A
419// the Power Mangement workloop thread. This enables objects in the
420// hierarchy to successfully alter their idle timers, which are all on the
421// same thread.
422//*********************************************************************************
423
424IOReturn IOPMrootDomain::setAggressiveness ( unsigned long type, unsigned long newLevel )
425{
9bccf70c
A
426 if ( pm_vars->PMcommandGate ) {
427 pm_vars->PMcommandGate->runAction(broadcast_aggressiveness,(void *)type,(void *)newLevel);
0b4e3aa0 428 }
1c79356b
A
429
430 return kIOReturnSuccess;
431}
432
433
434// **********************************************************************************
435// sleepSystem
436//
437// **********************************************************************************
438IOReturn IOPMrootDomain::sleepSystem ( void )
439{
55e303ae 440 //kprintf("sleep demand received\n");
1c79356b
A
441 if ( !systemBooting && allowSleep && sleepIsSupported ) {
442 patriarch->sleepSystem();
0b4e3aa0 443 return kIOReturnSuccess;
1c79356b 444 }
0b4e3aa0
A
445 if ( !systemBooting && allowSleep && !sleepIsSupported ) {
446 patriarch->dozeSystem();
447 return kIOReturnSuccess;
448 }
449 return kIOReturnSuccess;
450}
451
452
453// **********************************************************************************
454// shutdownSystem
455//
456// **********************************************************************************
457IOReturn IOPMrootDomain::shutdownSystem ( void )
458{
55e303ae
A
459 //patriarch->shutDownSystem();
460 return kIOReturnUnsupported;
0b4e3aa0
A
461}
462
463
464// **********************************************************************************
465// restartSystem
466//
467// **********************************************************************************
468IOReturn IOPMrootDomain::restartSystem ( void )
469{
55e303ae
A
470 //patriarch->restartSystem();
471 return kIOReturnUnsupported;
1c79356b
A
472}
473
474
475// **********************************************************************************
476// powerChangeDone
477//
478// This overrides powerChangeDone in IOService.
0b4e3aa0
A
479//
480// Finder sleep and idle sleep move us from the ON state to the SLEEP_STATE.
481// In this case:
482// If we just finished going to the SLEEP_STATE, and the platform is capable of true sleep,
483// sleep the kernel. Otherwise switch up to the DOZE_STATE which will keep almost
484// everything as off as it can get.
485//
486// **********************************************************************************
487void IOPMrootDomain::powerChangeDone ( unsigned long previousState )
488{
489 OSNumber * propertyPtr;
490 unsigned short theProperty;
491 AbsoluteTime deadline;
492
493 switch ( pm_vars->myCurrentState ) {
494 case SLEEP_STATE:
55e303ae
A
495 if ( canSleep && sleepIsSupported )
496 {
497 // re-enable this timer for next sleep
498 idleSleepPending = false;
0b4e3aa0 499 IOLog("System Sleep\n");
55e303ae 500 pm_vars->thePlatform->sleepKernel();
9bccf70c 501
55e303ae
A
502 // The CPU(s) are off at this point. When they're awakened by CPU interrupt,
503 // code will resume exeuction here.
504
505 // Now we're waking...
506 ioSPMTrace(IOPOWER_WAKE, * (int *) this);
9bccf70c 507
55e303ae
A
508 // stay awake for at least 30 seconds
509 clock_interval_to_deadline(30, kSecondScale, &deadline);
0b4e3aa0 510 thread_call_enter_delayed(extraSleepTimer, deadline);
55e303ae
A
511 // this gets turned off when we sleep again
512 idleSleepPending = true;
d52fe63f
A
513
514 // Ignore closed clamshell during wakeup and for a few seconds
515 // after wakeup is complete
516 ignoringClamshellDuringWakeup = true;
517
55e303ae
A
518 // sleep transition complete
519 gSleepOrShutdownPending = 0;
520
521 // trip the reset of the calendar clock
522 clock_wakeup_calendar();
523
524 // get us some power
525 patriarch->wakeSystem();
0b4e3aa0 526
55e303ae
A
527 // early stage wake notification
528 tellClients(kIOMessageSystemWillPowerOn);
529
530 // tell the tree we're waking
0b4e3aa0 531 IOLog("System Wake\n");
55e303ae 532 systemWake();
d52fe63f
A
533
534 // Allow drivers to request extra processing time before clamshell
535 // sleep if kIOREMSleepEnabledKey is present.
536 // Ignore clamshell events for at least 5 seconds
537 if(getProperty(kIOREMSleepEnabledKey)) {
538 // clamshellWakeupIgnore callout clears ignoreClamshellDuringWakeup bit
539 clock_interval_to_deadline(5, kSecondScale, &deadline);
540 if(clamshellWakeupIgnore) thread_call_enter_delayed(clamshellWakeupIgnore, deadline);
541 } else ignoringClamshellDuringWakeup = false;
55e303ae
A
542
543 // Find out what woke us
0b4e3aa0 544 propertyPtr = OSDynamicCast(OSNumber,getProperty("WakeEvent"));
55e303ae 545 if ( propertyPtr ) {
0b4e3aa0
A
546 theProperty = propertyPtr->unsigned16BitValue();
547 IOLog("Wake event %04x\n",theProperty);
43866e37
A
548 if ( (theProperty & 0x0008) || //lid
549 (theProperty & 0x0800) || // front panel button
550 (theProperty & 0x0020) || // external keyboard
551 (theProperty & 0x0001) ) { // internal keyboard
55e303ae
A
552 // We've identified the wakeup event as UI driven
553 reportUserInput();
0b4e3aa0 554 }
55e303ae
A
555 } else {
556 // Since we can't identify the wakeup event, treat it as UI activity
557 reportUserInput();
0b4e3aa0 558 }
55e303ae
A
559
560 // Wake for thirty seconds
561 changePowerStateToPriv(ON_STATE);
0b4e3aa0 562 powerOverrideOffPriv();
55e303ae
A
563 } else {
564 // allow us to step up a power state
565 patriarch->sleepToDoze();
566 // and do it
567 changePowerStateToPriv(DOZE_STATE);
0b4e3aa0
A
568 }
569 break;
570
571 case DOZE_STATE:
55e303ae
A
572 if ( previousState != DOZE_STATE )
573 {
0b4e3aa0
A
574 IOLog("System Doze\n");
575 }
55e303ae
A
576 // re-enable this timer for next sleep
577 idleSleepPending = false;
0b4e3aa0
A
578 gSleepOrShutdownPending = 0;
579 break;
580
581 case RESTART_STATE:
582 IOLog("System Restart\n");
583 PEHaltRestart(kPERestartCPU);
584 break;
585
586 case OFF_STATE:
587 IOLog("System Halt\n");
588 PEHaltRestart(kPEHaltCPU);
589 break;
590 }
591}
592
593
594// **********************************************************************************
595// wakeFromDoze
596//
597// The Display Wrangler calls here when it switches to its highest state. If the
598// system is currently dozing, allow it to wake by making sure the parent is
599// providing power.
1c79356b 600// **********************************************************************************
0b4e3aa0 601void IOPMrootDomain::wakeFromDoze( void )
1c79356b 602{
55e303ae
A
603 if ( pm_vars->myCurrentState == DOZE_STATE )
604 {
605 // reset this till next attempt
606 canSleep = true;
0b4e3aa0 607 powerOverrideOffPriv();
55e303ae
A
608
609 // early wake notification
610 tellClients(kIOMessageSystemWillPowerOn);
611
612 // allow us to wake if children so desire
613 patriarch->wakeSystem();
1c79356b
A
614 }
615}
616
617
d52fe63f
A
618// **********************************************************************************
619// publishFeature
620//
621// Adds a new feature to the supported features dictionary
622//
623//
624// **********************************************************************************
625void IOPMrootDomain::publishFeature( const char * feature )
626{
627 OSDictionary *features = (OSDictionary *)getProperty(kRootDomainSupportedFeatures);
628
629 features->setObject(feature, kOSBooleanTrue);
630}
631
55e303ae 632void IOPMrootDomain::unIdleDevice( IOService *theDevice, unsigned long theState )
1c79356b 633{
55e303ae
A
634 if(pmPowerStateQueue)
635 pmPowerStateQueue->unIdleOccurred(theDevice, theState);
636}
1c79356b 637
55e303ae
A
638void IOPMrootDomain::announcePowerSourceChange( void )
639{
640 messageClients(kIOPMMessageBatteryStatusHasChanged);
1c79356b
A
641}
642
643//*********************************************************************************
644// receivePowerNotification
645//
646// The power controller is notifying us of a hardware-related power management
647// event that we must handle. This is a result of an 'environment' interrupt from
648// the power mgt micro.
649//*********************************************************************************
650
651IOReturn IOPMrootDomain::receivePowerNotification (UInt32 msg)
652{
55e303ae
A
653 if (msg & kIOPMOverTemp)
654 {
9bccf70c
A
655 IOLog("Power Management received emergency overtemp signal. Going to sleep.");
656 (void) sleepSystem ();
657 }
55e303ae
A
658 if (msg & kIOPMSetDesktopMode)
659 {
d52fe63f
A
660 desktopMode = (0 != (msg & kIOPMSetValue));
661 msg &= ~(kIOPMSetDesktopMode | kIOPMSetValue);
662 }
55e303ae
A
663 if (msg & kIOPMSetACAdaptorConnected)
664 {
d52fe63f
A
665 acAdaptorConnect = (0 != (msg & kIOPMSetValue));
666 msg &= ~(kIOPMSetACAdaptorConnected | kIOPMSetValue);
667 }
55e303ae
A
668 if (msg & kIOPMEnableClamshell)
669 {
d52fe63f
A
670 ignoringClamshell = false;
671 }
55e303ae
A
672 if (msg & kIOPMDisableClamshell)
673 {
d52fe63f
A
674 ignoringClamshell = true;
675 }
676
55e303ae
A
677 if (msg & kIOPMProcessorSpeedChange)
678 {
679 IOService *pmu = waitForService(serviceMatching("ApplePMU"));
680 pmu->callPlatformFunction("prepareForSleep", false, 0, 0, 0, 0);
d52fe63f 681 pm_vars->thePlatform->sleepKernel();
55e303ae 682 pmu->callPlatformFunction("recoverFromSleep", false, 0, 0, 0, 0);
d52fe63f
A
683 }
684
55e303ae
A
685 if (msg & kIOPMSleepNow)
686 {
1c79356b
A
687 (void) sleepSystem ();
688 }
689
55e303ae
A
690 if (msg & kIOPMPowerEmergency)
691 {
1c79356b
A
692 (void) sleepSystem ();
693 }
694
55e303ae
A
695 if (msg & kIOPMClamshellClosed)
696 {
d52fe63f 697 if ( !ignoringClamshell && !ignoringClamshellDuringWakeup
55e303ae
A
698 && (!desktopMode || !acAdaptorConnect) )
699 {
d52fe63f
A
700
701 (void) sleepSystem ();
702 }
1c79356b
A
703 }
704
55e303ae
A
705 if (msg & kIOPMPowerButton)
706 {
707 // toggle state of sleep/wake
708 // are we dozing?
709 if ( pm_vars->myCurrentState == DOZE_STATE )
710 {
711 // yes, tell the tree we're waking
712 systemWake();
713 // wake the Display Wrangler
714 reportUserInput();
0b4e3aa0
A
715 }
716 else {
55e303ae
A
717 // Check that power button sleep is enabled
718 if(kOSBooleanTrue != getProperty(OSString::withCString("DisablePowerButtonSleep")))
719 sleepSystem();
1c79356b 720 }
0b4e3aa0
A
721 }
722
723 // if the case has been closed, we allow
724 // the machine to be put to sleep or to idle sleep
725
55e303ae
A
726 if ( (msg & kIOPMAllowSleep) && !allowSleep )
727 {
728 allowSleep = true;
0b4e3aa0 729 adjustPowerState();
1c79356b
A
730 }
731
0b4e3aa0 732 // if the case has been opened, we disallow sleep/doze
1c79356b
A
733
734 if (msg & kIOPMPreventSleep) {
55e303ae
A
735 allowSleep = false;
736 // are we dozing?
737 if ( pm_vars->myCurrentState == DOZE_STATE ) {
738 // yes, tell the tree we're waking
739 systemWake();
0b4e3aa0 740 adjustPowerState();
55e303ae
A
741 // wake the Display Wrangler
742 reportUserInput();
743 } else {
0b4e3aa0 744 adjustPowerState();
55e303ae
A
745 // make sure we have power to clamp
746 patriarch->wakeSystem();
0b4e3aa0 747 }
1c79356b
A
748 }
749
750 return 0;
751}
752
753
754//*********************************************************************************
755// sleepSupported
756//
757//*********************************************************************************
758
759void IOPMrootDomain::setSleepSupported( IOOptionBits flags )
760{
55e303ae
A
761 if ( flags & kPCICantSleep )
762 {
0b4e3aa0 763 canSleep = false;
55e303ae 764 } else {
0b4e3aa0
A
765 platformSleepSupport = flags;
766 }
767
768}
769
770//*********************************************************************************
771// requestPowerDomainState
772//
773// The root domain intercepts this call to the superclass.
774//
775// If the clamp bit is not set in the desire, then the child doesn't need the power
776// state it's requesting; it just wants it. The root ignores desires but not needs.
777// If the clamp bit is not set, the root takes it that the child can tolerate no
778// power and interprets the request accordingly. If all children can thus tolerate
779// no power, we are on our way to idle sleep.
780//*********************************************************************************
781
782IOReturn IOPMrootDomain::requestPowerDomainState ( IOPMPowerFlags desiredState, IOPowerConnection * whichChild, unsigned long specification )
783{
55e303ae
A
784 OSIterator *iter;
785 OSObject *next;
786 IOPowerConnection *connection;
787 unsigned long powerRequestFlag = 0;
788 IOPMPowerFlags editedDesire = desiredState;
789
790 // if they don't really need it, they don't get it
791 if ( !(desiredState & kIOPMPreventIdleSleep) ) {
0b4e3aa0
A
792 editedDesire = 0;
793 }
794
795
55e303ae
A
796 IOLockLock(pm_vars->childLock);
797
798 // recompute sleepIsSupported and see if all children are asleep
0b4e3aa0
A
799 iter = getChildIterator(gIOPowerPlane);
800 sleepIsSupported = true;
55e303ae
A
801 if ( iter )
802 {
803 while ( (next = iter->getNextObject()) )
804 {
805 if ( (connection = OSDynamicCast(IOPowerConnection,next)) )
806 {
807 if ( connection == whichChild )
808 {
0b4e3aa0 809 powerRequestFlag += editedDesire;
55e303ae
A
810 if ( desiredState & kIOPMPreventSystemSleep )
811 {
0b4e3aa0
A
812 sleepIsSupported = false;
813 }
55e303ae 814 } else {
0b4e3aa0 815 powerRequestFlag += connection->getDesiredDomainState();
55e303ae
A
816 if ( connection->getPreventSystemSleepFlag() )
817 {
0b4e3aa0
A
818 sleepIsSupported = false;
819 }
820 }
821 }
822 }
823 iter->release();
824 }
9bccf70c 825
55e303ae
A
826 if ( (extraSleepDelay == 0) && (powerRequestFlag == 0) )
827 {
0b4e3aa0 828 sleepASAP = true;
1c79356b 829 }
0b4e3aa0 830
55e303ae
A
831 // this may put the system to sleep
832 adjustPowerState();
0b4e3aa0
A
833
834 IOLockUnlock(pm_vars->childLock);
835
836 editedDesire |= desiredState & kIOPMPreventSystemSleep;
1c79356b 837
0b4e3aa0 838 return super::requestPowerDomainState(editedDesire,whichChild,specification);
1c79356b
A
839}
840
0b4e3aa0 841
1c79356b
A
842//*********************************************************************************
843// getSleepSupported
844//
845//*********************************************************************************
846
847IOOptionBits IOPMrootDomain::getSleepSupported( void )
848{
849 return( platformSleepSupport );
850}
851
852
853//*********************************************************************************
854// tellChangeDown
855//
856// We override the superclass implementation so we can send a different message
857// type to the client or application being notified.
858//*********************************************************************************
859
860bool IOPMrootDomain::tellChangeDown ( unsigned long stateNum )
861{
0b4e3aa0
A
862 switch ( stateNum ) {
863 case DOZE_STATE:
864 case SLEEP_STATE:
865 return super::tellClientsWithResponse(kIOMessageSystemWillSleep);
866 case RESTART_STATE:
867 return super::tellClientsWithResponse(kIOMessageSystemWillRestart);
868 case OFF_STATE:
869 return super::tellClientsWithResponse(kIOMessageSystemWillPowerOff);
1c79356b 870 }
55e303ae
A
871 // this shouldn't execute
872 return super::tellChangeDown(stateNum);
1c79356b
A
873}
874
875
876//*********************************************************************************
877// askChangeDown
878//
879// We override the superclass implementation so we can send a different message
880// type to the client or application being notified.
0b4e3aa0
A
881//
882// This must be idle sleep since we don't ask apps during any other power change.
1c79356b
A
883//*********************************************************************************
884
0b4e3aa0 885bool IOPMrootDomain::askChangeDown ( unsigned long )
1c79356b 886{
0b4e3aa0 887 return super::tellClientsWithResponse(kIOMessageCanSystemSleep);
1c79356b
A
888}
889
890
891//*********************************************************************************
892// tellNoChangeDown
893//
894// Notify registered applications and kernel clients that we are not
895// dropping power.
896//
897// We override the superclass implementation so we can send a different message
898// type to the client or application being notified.
0b4e3aa0
A
899//
900// This must be a vetoed idle sleep, since no other power change can be vetoed.
1c79356b
A
901//*********************************************************************************
902
903void IOPMrootDomain::tellNoChangeDown ( unsigned long )
904{
905 return tellClients(kIOMessageSystemWillNotSleep);
906}
907
908
909//*********************************************************************************
910// tellChangeUp
911//
912// Notify registered applications and kernel clients that we are raising power.
913//
914// We override the superclass implementation so we can send a different message
915// type to the client or application being notified.
916//*********************************************************************************
917
7b1edb79 918void IOPMrootDomain::tellChangeUp ( unsigned long stateNum)
1c79356b 919{
55e303ae
A
920 if ( stateNum == ON_STATE )
921 {
7b1edb79
A
922 return tellClients(kIOMessageSystemHasPoweredOn);
923 }
1c79356b
A
924}
925
0b4e3aa0
A
926//*********************************************************************************
927// reportUserInput
928//
929//*********************************************************************************
930
931void IOPMrootDomain::reportUserInput ( void )
932{
933 OSIterator * iter;
1c79356b 934
55e303ae
A
935 if(!wrangler)
936 {
0b4e3aa0 937 iter = getMatchingServices(serviceMatching("IODisplayWrangler"));
55e303ae
A
938 if(iter)
939 {
0b4e3aa0
A
940 wrangler = (IOService *) iter->getNextObject();
941 iter->release();
942 }
943 }
944
945 if(wrangler)
946 wrangler->activityTickle(0,0);
947}
948
949//*********************************************************************************
950// setQuickSpinDownTimeout
1c79356b 951//
0b4e3aa0
A
952//*********************************************************************************
953
954void IOPMrootDomain::setQuickSpinDownTimeout ( void )
955{
0b4e3aa0
A
956 super::setAggressiveness((unsigned long)kPMMinutesToSpinDown,(unsigned long)1);
957}
958
959//*********************************************************************************
960// restoreUserSpinDownTimeout
961//
962//*********************************************************************************
963
964void IOPMrootDomain::restoreUserSpinDownTimeout ( void )
965{
0b4e3aa0
A
966 super::setAggressiveness((unsigned long)kPMMinutesToSpinDown,(unsigned long)user_spindown);
967}
968
9bccf70c
A
969//*********************************************************************************
970// changePowerStateTo & changePowerStateToPriv
971//
972// Override of these methods for logging purposes.
973//*********************************************************************************
974
975IOReturn IOPMrootDomain::changePowerStateTo ( unsigned long ordinal )
976{
977 ioSPMTrace(IOPOWER_ROOT, * (int *) this, (int) true, (int) ordinal);
978
979 return super::changePowerStateTo(ordinal);
980}
981
982IOReturn IOPMrootDomain::changePowerStateToPriv ( unsigned long ordinal )
983{
984 ioSPMTrace(IOPOWER_ROOT, * (int *) this, (int) false, (int) ordinal);
985
986 return super::changePowerStateToPriv(ordinal);
987}
988
0b4e3aa0
A
989
990//*********************************************************************************
991// sysPowerDownHandler
992//
993// Receives a notification when the RootDomain changes state.
994//
995// Allows us to take action on system sleep, power down, and restart after
996// applications have received their power change notifications and replied,
997// but before drivers have powered down. We perform a vfs sync on power down.
998//*********************************************************************************
999
1000IOReturn IOPMrootDomain::sysPowerDownHandler( void * target, void * refCon,
1001 UInt32 messageType, IOService * service,
1002 void * messageArgument, vm_size_t argSize )
1003{
55e303ae
A
1004 IOReturn ret;
1005 IOPowerStateChangeNotification *params = (IOPowerStateChangeNotification *) messageArgument;
1006 IOPMrootDomain *rootDomain = OSDynamicCast(IOPMrootDomain, service);
0b4e3aa0
A
1007
1008 if(!rootDomain)
1009 return kIOReturnUnsupported;
1010
1011 switch (messageType) {
1012 case kIOMessageSystemWillSleep:
1013 rootDomain->powerOverrideOnPriv(); // start ignoring children's requests
1014 // (fall through to other cases)
0b4e3aa0
A
1015
1016 // Interested applications have been notified of an impending power
1017 // change and have acked (when applicable).
1018 // This is our chance to save whatever state we can before powering
1019 // down.
1020 // We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c,
1021 // via callout
1022
1023 // We will ack within 20 seconds
1024 params->returnValue = 20 * 1000 * 1000;
1025
1026 if ( ! OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending ) )
1027 {
1028 // Purposely delay the ack and hope that shutdown occurs quickly.
1029 // Another option is not to schedule the thread and wait for
1030 // ack timeout...
1031 AbsoluteTime deadline;
9bccf70c 1032 clock_interval_to_deadline( 30, kSecondScale, &deadline );
0b4e3aa0
A
1033 thread_call_enter1_delayed( rootDomain->diskSyncCalloutEntry,
1034 (thread_call_param_t)params->powerRef,
1035 deadline );
1036 }
1037 else
1038 thread_call_enter1(rootDomain->diskSyncCalloutEntry, (thread_call_param_t)params->powerRef);
1039 ret = kIOReturnSuccess;
1040 break;
fa4905b1
A
1041
1042 case kIOMessageSystemWillPowerOff:
1043 case kIOMessageSystemWillRestart:
d52fe63f 1044 ret = kIOReturnUnsupported;
fa4905b1
A
1045 break;
1046
0b4e3aa0
A
1047 default:
1048 ret = kIOReturnUnsupported;
1049 break;
1050 }
1051 return ret;
1052}
1053
1054//*********************************************************************************
1055// displayWranglerNotification
1056//
1057// Receives a notification when the IODisplayWrangler changes state.
1058//
1059// Allows us to take action on display dim/undim.
1060//
1061// When the display goes dim we:
1062// - Start the idle sleep timer
1063// - set the quick spin down timeout
1064//
1065// On wake from display dim:
1066// - Cancel the idle sleep timer
1067// - restore the user's chosen spindown timer from the "quick" spin down value
1068//*********************************************************************************
1c79356b 1069
0b4e3aa0
A
1070IOReturn IOPMrootDomain::displayWranglerNotification( void * target, void * refCon,
1071 UInt32 messageType, IOService * service,
1072 void * messageArgument, vm_size_t argSize )
1c79356b 1073{
0b4e3aa0
A
1074 IOPMrootDomain * rootDomain = OSDynamicCast(IOPMrootDomain, (IOService *)target);
1075 AbsoluteTime deadline;
1076 static bool deviceAlreadyPoweredOff = false;
1077
1078 if(!rootDomain)
1079 return kIOReturnUnsupported;
1080
1081 switch (messageType) {
1082 case kIOMessageDeviceWillPowerOff:
1083 // The IODisplayWrangler has powered off either because of idle display sleep
1084 // or force system sleep.
1085
1086 // The display wrangler will send the DeviceWillPowerOff message 4 times until
1087 // it gets into its lowest state. We only want to act on the first of those 4.
1088 if( deviceAlreadyPoweredOff ) return kIOReturnUnsupported;
1089
1090 deviceAlreadyPoweredOff = true;
1091
55e303ae
A
1092 if( rootDomain->extraSleepDelay )
1093 {
0b4e3aa0
A
1094 // start the extra sleep timer
1095 clock_interval_to_deadline(rootDomain->extraSleepDelay*60, kSecondScale, &deadline );
1096 thread_call_enter_delayed(rootDomain->extraSleepTimer, deadline);
1097 rootDomain->idleSleepPending = true;
0b4e3aa0 1098 } else {
0b4e3aa0 1099 // accelerate disk spin down if spin down timer is non-zero (zero = never spin down)
9bccf70c
A
1100 // and if system sleep is non-Never
1101 if( (0 != rootDomain->user_spindown) && (0 != rootDomain->sleepSlider) )
0b4e3aa0
A
1102 rootDomain->setQuickSpinDownTimeout();
1103 }
1104
1105 break;
1106
1107 case kIOMessageDeviceHasPoweredOn:
1108
1109 // The display has powered on either because of UI activity or wake from sleep/doze
1110 deviceAlreadyPoweredOff = false;
1111 rootDomain->adjustPowerState();
1112
1113
1114 // cancel any pending idle sleep
55e303ae
A
1115 if(rootDomain->idleSleepPending)
1116 {
0b4e3aa0
A
1117 thread_call_cancel(rootDomain->extraSleepTimer);
1118 rootDomain->idleSleepPending = false;
1119 }
1120
1121 // Change the spindown value back to the user's selection from our accelerated setting
1122 if(0 != rootDomain->user_spindown)
1123 rootDomain->restoreUserSpinDownTimeout();
1124
1125 // Put on the policy maker's on clamp.
1126
1127 break;
1128
1129 default:
1130 break;
1131 }
1132 return kIOReturnUnsupported;
1133 }
1134
1135//*********************************************************************************
1136// displayWranglerPublished
1137//
1138// Receives a notification when the IODisplayWrangler is published.
1139// When it's published we install a power state change handler.
1140//
1141//*********************************************************************************
1142
1143bool IOPMrootDomain::displayWranglerPublished( void * target, void * refCon,
1144 IOService * newService)
1145{
1146 IOPMrootDomain * rootDomain = OSDynamicCast(IOPMrootDomain, (IOService *)target);
1147
1148 if(!rootDomain)
1149 return false;
1150
55e303ae
A
1151 rootDomain->wrangler = newService;
1152
1153 // we found the display wrangler, now install a handler
1154 if( !rootDomain->wrangler->registerInterest( gIOGeneralInterest, &displayWranglerNotification, target, 0) ) {
1155 IOLog("IOPMrootDomain::displayWranglerPublished registerInterest failed\n");
1156 return false;
1157 }
1158
1159 return true;
1c79356b
A
1160}
1161
1162
0b4e3aa0
A
1163//*********************************************************************************
1164// adjustPowerState
1165//
1166// Some condition that affects our wake/sleep/doze decision has changed.
1167//
1168// If the sleep slider is in the off position, we cannot sleep or doze.
1169// If the enclosure is open, we cannot sleep or doze.
1170// If the system is still booting, we cannot sleep or doze.
1171//
1172// In those circumstances, we prevent sleep and doze by holding power on with
1173// changePowerStateToPriv(ON).
1174//
1175// If the above conditions do not exist, and also the sleep timer has expired, we
1176// allow sleep or doze to occur with either changePowerStateToPriv(SLEEP) or
1177// changePowerStateToPriv(DOZE) depending on whether or not we already know the
1178// platform cannot sleep.
1179//
1180// In this case, sleep or doze will either occur immediately or at the next time
1181// that no children are holding the system out of idle sleep via the
1182// kIOPMPreventIdleSleep flag in their power state arrays.
1183//*********************************************************************************
1184
1185void IOPMrootDomain::adjustPowerState( void )
1186{
1187 if ( (sleepSlider == 0) ||
1188 ! allowSleep ||
1189 systemBooting ) {
1190 changePowerStateToPriv(ON_STATE);
55e303ae
A
1191 } else {
1192 if ( sleepASAP )
1193 {
0b4e3aa0 1194 sleepASAP = false;
55e303ae
A
1195 if ( sleepIsSupported )
1196 {
0b4e3aa0 1197 changePowerStateToPriv(SLEEP_STATE);
55e303ae 1198 } else {
0b4e3aa0
A
1199 changePowerStateToPriv(DOZE_STATE);
1200 }
1201 }
1202 }
1203}
1c79356b
A
1204
1205
1206/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1207
1208#undef super
1209#define super IOService
1210
1211OSDefineMetaClassAndStructors(IORootParent, IOService)
1212
0b4e3aa0
A
1213// This array exactly parallels the state array for the root domain.
1214// Power state changes initiated by a device can be vetoed by a client of the device, and
1215// power state changes initiated by the parent of a device cannot be vetoed by a client of the device,
1216// so when the root domain wants a power state change that cannot be vetoed (e.g. demand sleep), it asks
1217// its parent to make the change. That is the reason for this complexity.
1c79356b 1218
0b4e3aa0 1219static IOPMPowerState patriarchPowerStates[number_of_power_states] = {
1c79356b 1220 {1,0,0,0,0,0,0,0,0,0,0,0}, // off
0b4e3aa0 1221 {1,0,RESTART_POWER,0,0,0,0,0,0,0,0,0}, // reset
1c79356b 1222 {1,0,SLEEP_POWER,0,0,0,0,0,0,0,0,0}, // sleep
0b4e3aa0 1223 {1,0,DOZE_POWER,0,0,0,0,0,0,0,0,0}, // doze
1c79356b
A
1224 {1,0,ON_POWER,0,0,0,0,0,0,0,0,0} // running
1225};
1226
1c79356b
A
1227bool IORootParent::start ( IOService * nub )
1228{
0b4e3aa0 1229 mostRecentChange = ON_STATE;
1c79356b
A
1230 super::start(nub);
1231 PMinit();
0b4e3aa0 1232 registerPowerDriver(this,patriarchPowerStates,number_of_power_states);
1c79356b
A
1233 powerOverrideOnPriv();
1234 return true;
1235}
1236
1237
1238void IORootParent::shutDownSystem ( void )
1239{
0b4e3aa0
A
1240 mostRecentChange = OFF_STATE;
1241 changePowerStateToPriv(OFF_STATE);
1242}
1243
1244
1245void IORootParent::restartSystem ( void )
1246{
1247 mostRecentChange = RESTART_STATE;
1248 changePowerStateToPriv(RESTART_STATE);
1c79356b
A
1249}
1250
1251
1252void IORootParent::sleepSystem ( void )
1253{
0b4e3aa0
A
1254 mostRecentChange = SLEEP_STATE;
1255 changePowerStateToPriv(SLEEP_STATE);
1256}
1257
1258
1259void IORootParent::dozeSystem ( void )
1260{
1261 mostRecentChange = DOZE_STATE;
1262 changePowerStateToPriv(DOZE_STATE);
1263}
1264
1265// Called in demand sleep when sleep discovered to be impossible after actually attaining that state.
1266// This brings the parent to doze, which allows the root to step up from sleep to doze.
1267
1268// In idle sleep, do nothing because the parent is still on and the root can freely change state.
1269
1270void IORootParent::sleepToDoze ( void )
1271{
1272 if ( mostRecentChange == SLEEP_STATE ) {
1273 changePowerStateToPriv(DOZE_STATE);
1274 }
1c79356b
A
1275}
1276
1277
1278void IORootParent::wakeSystem ( void )
1279{
0b4e3aa0
A
1280 mostRecentChange = ON_STATE;
1281 changePowerStateToPriv(ON_STATE);
1c79356b
A
1282}
1283