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