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