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