2  * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   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. 
  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 
  20  * @APPLE_LICENSE_HEADER_END@ 
  22 #include <IOKit/IOWorkLoop.h> 
  23 #include <IOKit/IOCommandQueue.h> 
  24 #include <IOKit/IOTimerEventSource.h> 
  25 #include <IOKit/IOPlatformExpert.h> 
  26 #include <IOKit/pwr_mgt/RootDomain.h> 
  27 #include <IOKit/pwr_mgt/IOPM.h> 
  28 #include <IOKit/IOMessage.h> 
  29 #include "RootDomainUserClient.h" 
  30 #include "IOKit/pwr_mgt/IOPowerConnection.h" 
  33 extern void kprintf(const char *, ...); 
  36 extern const IORegistryPlane 
* gIOPowerPlane
; 
  38 void PMreceiveCmd ( OSObject 
*,  void *, void *, void *, void * ); 
  39 static void sleepTimerExpired(thread_call_param_t
); 
  42 #define number_of_power_states 5 
  44 #define RESTART_STATE 1 
  49 #define ON_POWER kIOPMPowerOn 
  50 #define RESTART_POWER kIOPMRestart 
  51 #define SLEEP_POWER kIOPMAuxPowerOn 
  52 #define DOZE_POWER kIOPMDoze 
  54 static IOPMPowerState ourPowerStates
[number_of_power_states
] = { 
  55     {1,0,                       0,              0,0,0,0,0,0,0,0,0},             // state 0, off 
  56     {1,kIOPMRestartCapability
,  kIOPMRestart
,   RESTART_POWER
,0,0,0,0,0,0,0,0}, // state 1, restart 
  57     {1,kIOPMSleepCapability
,    kIOPMSleep
,     SLEEP_POWER
,0,0,0,0,0,0,0,0},   // state 2, sleep 
  58     {1,kIOPMDoze
,               kIOPMDoze
,      DOZE_POWER
,0,0,0,0,0,0,0,0},    // state 3, doze 
  59     {1,kIOPMPowerOn
,            kIOPMPowerOn
,   ON_POWER
,0,0,0,0,0,0,0,0},      // state 4, on 
  62 static IOPMrootDomain 
* gRootDomain
; 
  63 static UInt32           gSleepOrShutdownPending 
= 0; 
  66 #define super IOService 
  67 OSDefineMetaClassAndStructors(IOPMrootDomain
,IOService
) 
  71     IONotifier 
* registerSleepWakeInterest(IOServiceInterestHandler handler
, void * self
, void * ref 
= 0) 
  73         return gRootDomain
->registerInterest( gIOGeneralInterest
, handler
, self
, ref 
); 
  76     IONotifier 
* registerPrioritySleepWakeInterest(IOServiceInterestHandler handler
, void * self
, void * ref 
= 0) 
  78         return gRootDomain
->registerInterest( gIOPriorityPowerStateInterest
, handler
, self
, ref 
); 
  81     IOReturn 
acknowledgeSleepWakeNotification(void * PMrefcon
) 
  83         return gRootDomain
->allowPowerChange ( (unsigned long)PMrefcon 
); 
  86     IOReturn 
vetoSleepWakeNotification(void * PMrefcon
) 
  88         return gRootDomain
->cancelPowerChange ( (unsigned long)PMrefcon 
); 
  91     IOReturn 
rootDomainRestart ( void ) 
  93         return gRootDomain
->restartSystem(); 
  96     IOReturn 
rootDomainShutdown ( void ) 
  98         return gRootDomain
->shutdownSystem(); 
 101         void IOSystemShutdownNotification ( void ) 
 103         for ( int i 
= 0; i 
< 100; i
++ ) 
 105             if ( OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending 
) ) break; 
 110     int sync_internal(void);     
 114 A device is always in the highest power state which satisfies its driver, its policy-maker, and any power domain 
 115 children it has, but within the constraint of the power state provided by its parent.  The driver expresses its desire by 
 116 calling changePowerStateTo(), the policy-maker expresses its desire by calling changePowerStateToPriv(), and the children 
 117 express their desires by calling requestPowerDomainState(). 
 119 The Root Power Domain owns the policy for idle and demand sleep and doze for the system.  It is a power-managed IOService just 
 120 like the others in the system.  It implements several power states which correspond to what we see as Sleep, Doze, etc. 
 122 The sleep/doze policy is as follows: 
 123 Sleep and Doze are prevented if the case is open so that nobody will think the machine is off and plug/unplug cards. 
 124 Sleep and Doze are prevented if the sleep timeout slider in the preferences panel is at zero. 
 125 The system cannot Sleep, but can Doze if some object in the tree is in a power state marked kIOPMPreventSystemSleep. 
 127 These three conditions are enforced using the "driver clamp" by calling changePowerStateTo().  For example, if the case is 
 128 opened, changePowerStateTo(ON_STATE) is called to hold the system on regardless of the desires of the children of the root or 
 129 the state of the other clamp. 
 131 Demand Sleep/Doze is initiated by pressing the front panel power button, closing the clamshell, or selecting the menu item. 
 132 In this case the root's parent actually initiates the power state change so that the root has no choice and does not give 
 133 applications the opportunity to veto the change. 
 135 Idle Sleep/Doze occurs if no objects in the tree are in a state marked kIOPMPreventIdleSleep.  When this is true, the root's 
 136 children are not holding the root on, so it sets the "policy-maker clamp" by calling changePowerStateToPriv(ON_STATE) 
 137 to hold itself on until the sleep timer expires.  This timer is set for the difference between the sleep timeout slider and 
 138 the larger of the display dim timeout slider and the disk spindown timeout slider in the Preferences panel.  For example, if 
 139 the system is set to sleep after thirty idle minutes, and the display and disk are set to sleep after five idle minutes, 
 140 when there is no longer an object in the tree holding the system out of Idle Sleep (via kIOPMPreventIdleSleep), the root 
 141 sets its timer for 25 minutes (30 - 5).  When the timer expires, it releases its clamp and now nothing is holding it awake, 
 144 Demand sleep is prevented when the system is booting.  When preferences are transmitted by the loginwindow at the end of 
 145 boot, a flag is cleared, and this allows subsequent Demand Sleep. 
 147 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 
 148 a clamp, but sets a flag which is noticed before actually sleeping the kernel.  If the flag is set, the root steps up 
 149 one power state from Sleep to Doze, and any objects in the tree for which this is relevent will act appropriately (USB and 
 150 ADB will turn on again so that they can wake the system out of Doze (keyboard/mouse activity will cause the Display Wrangler 
 155 // ********************************************************************************** 
 157 IOPMrootDomain 
* IOPMrootDomain::construct( void ) 
 159     IOPMrootDomain 
* root
; 
 161     root 
= new IOPMrootDomain
; 
 168 // ********************************************************************************** 
 170 static void disk_sync_callout(thread_call_param_t p0
, thread_call_param_t p1
) 
 172     IOService 
* rootDomain 
= (IOService 
*) p0
; 
 173     unsigned long pmRef 
= (unsigned long) p1
; 
 176     rootDomain
->allowPowerChange(pmRef
); 
 179 // ********************************************************************************** 
 182 // We don't do much here.  The real initialization occurs when the platform 
 183 // expert informs us we are the root. 
 184 // ********************************************************************************** 
 187 bool IOPMrootDomain::start ( IOService 
* nub 
) 
 194     setProperty("IOSleepSupported",""); 
 196     sleepIsSupported 
= true; 
 197     systemBooting 
= true; 
 198     ignoringClamshell 
= true; 
 200     idleSleepPending 
= false; 
 205     pm_vars
->PMworkloop 
= IOWorkLoop::workLoop();                               // make the workloop 
 206     pm_vars
->commandQueue 
= IOCommandQueue::commandQueue(this, PMreceiveCmd
);   // make a command queue 
 207     if (! pm_vars
->commandQueue 
|| 
 208         (  pm_vars
->PMworkloop
->addEventSource( pm_vars
->commandQueue
) != kIOReturnSuccess
) ) { 
 211     extraSleepTimer 
= thread_call_allocate((thread_call_func_t
)sleepTimerExpired
, (thread_call_param_t
) this); 
 213     diskSyncCalloutEntry 
= thread_call_allocate(&disk_sync_callout
, (thread_call_param_t
) this); 
 215     patriarch 
= new IORootParent
;                               // create our parent 
 217     patriarch
->attach(this); 
 218     patriarch
->start(this); 
 219     patriarch
->youAreRoot(); 
 220     patriarch
->wakeSystem(); 
 221     patriarch
->addPowerChild(this); 
 223     registerPowerDriver(this,ourPowerStates
,number_of_power_states
); 
 225     setPMRootDomain(this); 
 226     changePowerStateToPriv(ON_STATE
);                           // set a clamp until we sleep 
 228     registerPrioritySleepWakeInterest( &sysPowerDownHandler
, this, 0); // install power change handler 
 230     // Register for a notification when IODisplayWrangler is published 
 231     addNotification( gIOPublishNotification
, serviceMatching("IODisplayWrangler"), &displayWranglerPublished
, this, 0); 
 233     registerService();                                          // let clients find us 
 239 //********************************************************************************* 
 242 // Power Managment is informing us that we are the root power domain. 
 243 // We know we are not the root however, since we have just instantiated a parent 
 244 // for ourselves and made it the root.  We override this method so it will have 
 246 //********************************************************************************* 
 247 IOReturn 
IOPMrootDomain::youAreRoot ( void ) 
 252 // ********************************************************************************** 
 255 // We have received a command from ourselves on the command queue. 
 256 // If it is to send a recently-received aggressiveness factor, do so. 
 257 // Otherwise, it's something the superclass enqueued. 
 258 // ********************************************************************************** 
 259 void IOPMrootDomain::command_received ( void * command
, void * x
, void * y
, void * z 
) 
 261     switch ( (int)command 
) { 
 262         case kIOPMBroadcastAggressiveness
: 
 264             super::setAggressiveness((unsigned long)x
,(unsigned long)y
); 
 266             // Save user's spin down timer to restore after we replace it for idle sleep 
 267             if( (int)x 
== kPMMinutesToSpinDown 
) user_spindown 
= (unsigned int) y
; 
 269             // Use longestNonSleepSlider to calculate dimming adjust idle sleep timer 
 270             longestNonSleepSlider 
= pm_vars
->current_aggressiveness_values
[kPMMinutesToDim
]; 
 273             if ( (int)x 
== kPMMinutesToSleep 
) { 
 274                 if ( (sleepSlider 
== 0) && ((int)y 
!= 0) ) { 
 275                     sleepSlider 
= (int)y
; 
 276                     adjustPowerState();                         // idle sleep is now enabled, maybe sleep now 
 278                 sleepSlider 
= (int)y
; 
 279                 if ( sleepSlider 
== 0 ) {                        
 280                     adjustPowerState();                         // idle sleep is now disabled 
 281                     patriarch
->wakeSystem();                    // make sure we're powered 
 284             if ( sleepSlider 
> longestNonSleepSlider 
) { 
 285                 extraSleepDelay 
= sleepSlider 
- longestNonSleepSlider 
; 
 293             super::command_received(command
,x
,y
,z
); 
 299 // ********************************************************************************** 
 302 // ********************************************************************************** 
 303 static void sleepTimerExpired ( thread_call_param_t us
) 
 305     ((IOPMrootDomain 
*)us
)->handleSleepTimerExpiration(); 
 309 // ********************************************************************************** 
 310 // handleSleepTimerExpiration 
 312 // The time between the sleep idle timeout and the next longest one has elapsed. 
 313 // It's time to sleep.  Start that by removing the clamp that's holding us awake. 
 314 // ********************************************************************************** 
 315 void IOPMrootDomain::handleSleepTimerExpiration ( void ) 
 317     // accelerate disk spin down if spin down timer is non-zero (zero = never spin down)   
 318     if(0 != user_spindown
) 
 319         setQuickSpinDownTimeout(); 
 326 //********************************************************************************* 
 329 // Some aggressiveness factor has changed.  We put this change on our 
 330 // command queue so that we can broadcast it to the hierarchy while on 
 331 // the Power Mangement workloop thread.  This enables objects in the 
 332 // hierarchy to successfully alter their idle timers, which are all on the 
 334 //********************************************************************************* 
 336 IOReturn 
IOPMrootDomain::setAggressiveness ( unsigned long type
, unsigned long newLevel 
) 
 338     if ( systemBooting 
&& (type 
== kPMMinutesToDim
) ) { 
 339         systemBooting 
= false;  // when the login window launches, this method gets called -- system booting is done. 
 340         IOLog("Root power domain receiving initial preferences\n"); 
 344     pm_vars
->commandQueue
->enqueueCommand(true, (void *)kIOPMBroadcastAggressiveness
, (void *) type
, (void *) newLevel 
); 
 346     return kIOReturnSuccess
; 
 350 // ********************************************************************************** 
 353 // ********************************************************************************** 
 354 IOReturn 
IOPMrootDomain::sleepSystem ( void ) 
 356     kprintf("sleep demand received\n"); 
 357     if ( !systemBooting 
&& allowSleep 
&& sleepIsSupported 
) { 
 358         patriarch
->sleepSystem(); 
 359         return kIOReturnSuccess
; 
 361     if ( !systemBooting 
&& allowSleep 
&& !sleepIsSupported 
) { 
 362         patriarch
->dozeSystem(); 
 363         return kIOReturnSuccess
; 
 365     return kIOReturnSuccess
; 
 369 // ********************************************************************************** 
 372 // ********************************************************************************** 
 373 IOReturn 
IOPMrootDomain::shutdownSystem ( void ) 
 375     patriarch
->shutDownSystem(); 
 376     return kIOReturnSuccess
; 
 380 // ********************************************************************************** 
 383 // ********************************************************************************** 
 384 IOReturn 
IOPMrootDomain::restartSystem ( void ) 
 386     patriarch
->restartSystem(); 
 387     return kIOReturnSuccess
; 
 391 // ********************************************************************************** 
 394 // This overrides powerChangeDone in IOService. 
 396 // Finder sleep and idle sleep move us from the ON state to the SLEEP_STATE. 
 398 // If we just finished going to the SLEEP_STATE, and the platform is capable of true sleep, 
 399 // sleep the kernel.  Otherwise switch up to the DOZE_STATE which will keep almost 
 400 // everything as off as it can get. 
 402 // ********************************************************************************** 
 403 void IOPMrootDomain::powerChangeDone ( unsigned long previousState 
) 
 405     OSNumber 
*          propertyPtr
; 
 406     unsigned short      theProperty
; 
 407     AbsoluteTime        deadline
; 
 409     switch ( pm_vars
->myCurrentState 
) { 
 411             if ( canSleep 
&& sleepIsSupported 
) { 
 412                 idleSleepPending 
= false;                       // re-enable this timer for next sleep 
 413                 IOLog("System Sleep\n"); 
 414                 pm_vars
->thePlatform
->sleepKernel();            // sleep now 
 417                 clock_interval_to_deadline(30, kSecondScale
, &deadline
);        // stay awake for at least 30 seconds 
 418                 thread_call_enter_delayed(extraSleepTimer
, deadline
); 
 419                 idleSleepPending 
= true;                        // this gets turned off when we sleep again 
 420                 gSleepOrShutdownPending 
= 0;        // sleep transition complete 
 421                 patriarch
->wakeSystem();                        // get us some power 
 423                 IOLog("System Wake\n"); 
 424                 systemWake();                                   // tell the tree we're waking  
 426                 propertyPtr 
= OSDynamicCast(OSNumber
,getProperty("WakeEvent")); 
 427                 if ( propertyPtr 
) {                            // find out what woke us 
 428                     theProperty 
= propertyPtr
->unsigned16BitValue(); 
 429                     IOLog("Wake event %04x\n",theProperty
); 
 430                     if ( (theProperty 
== 0x0008) ||     //lid 
 431                         (theProperty 
== 0x0800) ||      // front panel button 
 432                         (theProperty 
== 0x0020) ||      // external keyboard 
 433                         (theProperty 
== 0x0001) ) {     // internal keyboard 
 438                     IOLog("Unknown wake event\n"); 
 439                     reportUserInput();                          // don't know, call it user input then 
 442                 changePowerStateToPriv(ON_STATE
);               // wake for thirty seconds 
 443                 powerOverrideOffPriv(); 
 446                 patriarch
->sleepToDoze();               // allow us to step up a power state 
 447                 changePowerStateToPriv(DOZE_STATE
);     // and do it 
 452             if ( previousState 
!= DOZE_STATE 
) { 
 453                 IOLog("System Doze\n"); 
 455             idleSleepPending 
= false;                   // re-enable this timer for next sleep 
 456             gSleepOrShutdownPending 
= 0; 
 460             IOLog("System Restart\n"); 
 461             PEHaltRestart(kPERestartCPU
); 
 465             IOLog("System Halt\n"); 
 466             PEHaltRestart(kPEHaltCPU
); 
 472 // ********************************************************************************** 
 475 // The Display Wrangler calls here when it switches to its highest state.  If the  
 476 // system is currently dozing, allow it to wake by making sure the parent is 
 478 // ********************************************************************************** 
 479 void IOPMrootDomain::wakeFromDoze( void ) 
 481     if ( pm_vars
->myCurrentState 
== DOZE_STATE 
) { 
 482         canSleep 
= true;                                // reset this till next attempt 
 483         powerOverrideOffPriv(); 
 484         patriarch
->wakeSystem();                        // allow us to wake if children so desire 
 489 // ********************************************************************************** 
 492 // ********************************************************************************** 
 493 IOReturn 
IOPMrootDomain::newUserClient(  task_t owningTask
,  void * /* security_id */, UInt32 type
, IOUserClient 
** handler 
) 
 495     IOReturn            err 
= kIOReturnSuccess
; 
 496     RootDomainUserClient 
*      client
; 
 498     client 
= RootDomainUserClient::withTask(owningTask
); 
 500     if( !client 
|| (false == client
->attach( this )) || 
 501         (false == client
->start( this )) ) { 
 503             client
->detach( this ); 
 507         err 
= kIOReturnNoMemory
; 
 513 //********************************************************************************* 
 514 // receivePowerNotification 
 516 // The power controller is notifying us of a hardware-related power management 
 517 // event that we must handle. This is a result of an 'environment' interrupt from 
 518 // the power mgt micro. 
 519 //********************************************************************************* 
 521 IOReturn 
IOPMrootDomain::receivePowerNotification (UInt32 msg
) 
 523     if (msg 
& kIOPMSleepNow
) { 
 524       (void) sleepSystem (); 
 527     if (msg 
& kIOPMPowerEmergency
) { 
 528       (void) sleepSystem (); 
 531     if (msg 
& kIOPMClamshellClosed
) { 
 532         if ( ! ignoringClamshell 
) { 
 533             (void) sleepSystem (); 
 537     if (msg 
& kIOPMEnableClamshell
) { 
 538         ignoringClamshell 
= false; 
 540     if (msg 
& kIOPMDisableClamshell
) { 
 541         ignoringClamshell 
= true; 
 544     if (msg 
& kIOPMPowerButton
) {                               // toggle state of sleep/wake 
 545         if ( pm_vars
->myCurrentState 
== DOZE_STATE 
) {          // are we dozing? 
 546             systemWake();                                       // yes, tell the tree we're waking  
 547             reportUserInput();                                  // wake the Display Wrangler 
 550             (void) sleepSystem (); 
 554     // if the case has been closed, we allow 
 555     // the machine to be put to sleep or to idle sleep 
 557     if ( (msg 
& kIOPMAllowSleep
) && !allowSleep 
) { 
 562     // if the case has been opened, we disallow sleep/doze 
 564     if (msg 
& kIOPMPreventSleep
) { 
 566         if ( pm_vars
->myCurrentState 
== DOZE_STATE 
) {          // are we dozing? 
 567             systemWake();                                       // yes, tell the tree we're waking  
 569             reportUserInput();                                  // wake the Display Wrangler 
 573             patriarch
->wakeSystem();                            // make sure we have power to clamp 
 581 //********************************************************************************* 
 584 //********************************************************************************* 
 586 void IOPMrootDomain::setSleepSupported( IOOptionBits flags 
) 
 588     if ( flags 
& kPCICantSleep 
) { 
 592         platformSleepSupport 
= flags
; 
 597 //********************************************************************************* 
 598 // requestPowerDomainState 
 600 // The root domain intercepts this call to the superclass. 
 602 // If the clamp bit is not set in the desire, then the child doesn't need the power 
 603 // state it's requesting; it just wants it.  The root ignores desires but not needs. 
 604 // If the clamp bit is not set, the root takes it that the child can tolerate no 
 605 // power and interprets the request accordingly.  If all children can thus tolerate 
 606 // no power, we are on our way to idle sleep. 
 607 //********************************************************************************* 
 609 IOReturn 
IOPMrootDomain::requestPowerDomainState ( IOPMPowerFlags desiredState
, IOPowerConnection 
* whichChild
, unsigned long specification 
) 
 613     IOPowerConnection 
* connection
; 
 614     unsigned long       powerRequestFlag 
= 0; 
 615     IOPMPowerFlags      editedDesire 
= desiredState
; 
 617     if ( !(desiredState 
& kIOPMPreventIdleSleep
) ) {            // if they don't really need it, they don't get it 
 622     IOLockLock(pm_vars
->childLock
);                     // recompute sleepIsSupported 
 623                                                         // and see if all children are asleep 
 624     iter 
= getChildIterator(gIOPowerPlane
); 
 625     sleepIsSupported 
= true; 
 628         while ( (next 
= iter
->getNextObject()) ) { 
 629             if ( (connection 
= OSDynamicCast(IOPowerConnection
,next
)) ) { 
 630                 if ( connection 
== whichChild 
) { 
 631                     powerRequestFlag 
+= editedDesire
; 
 632                     if ( desiredState 
& kIOPMPreventSystemSleep 
) { 
 633                         sleepIsSupported 
= false; 
 637                     powerRequestFlag 
+= connection
->getDesiredDomainState(); 
 638                     if ( connection
->getPreventSystemSleepFlag() ) { 
 639                         sleepIsSupported 
= false; 
 647     if ( (extraSleepDelay 
== 0) &&  (powerRequestFlag 
== 0) ) { 
 651     adjustPowerState();                                 // this may put the system to sleep 
 653     IOLockUnlock(pm_vars
->childLock
); 
 655     editedDesire 
|= desiredState 
& kIOPMPreventSystemSleep
; 
 657     return super::requestPowerDomainState(editedDesire
,whichChild
,specification
); 
 661 //********************************************************************************* 
 664 //********************************************************************************* 
 666 IOOptionBits 
IOPMrootDomain::getSleepSupported( void ) 
 668     return( platformSleepSupport 
); 
 672 //********************************************************************************* 
 675 // We override the superclass implementation so we can send a different message 
 676 // type to the client or application being notified. 
 677 //********************************************************************************* 
 679 bool IOPMrootDomain::tellChangeDown ( unsigned long stateNum 
) 
 681     switch ( stateNum 
) { 
 684             return super::tellClientsWithResponse(kIOMessageSystemWillSleep
); 
 686             return super::tellClientsWithResponse(kIOMessageSystemWillRestart
); 
 688             return super::tellClientsWithResponse(kIOMessageSystemWillPowerOff
); 
 690     return super::tellChangeDown(stateNum
);             // this shouldn't execute 
 694 //********************************************************************************* 
 697 // We override the superclass implementation so we can send a different message 
 698 // type to the client or application being notified. 
 700 // This must be idle sleep since we don't ask apps during any other power change. 
 701 //********************************************************************************* 
 703 bool IOPMrootDomain::askChangeDown ( unsigned long ) 
 705     return super::tellClientsWithResponse(kIOMessageCanSystemSleep
); 
 709 //********************************************************************************* 
 712 // Notify registered applications and kernel clients that we are not 
 715 // We override the superclass implementation so we can send a different message 
 716 // type to the client or application being notified. 
 718 // This must be a vetoed idle sleep, since no other power change can be vetoed. 
 719 //********************************************************************************* 
 721 void IOPMrootDomain::tellNoChangeDown ( unsigned long ) 
 723     return tellClients(kIOMessageSystemWillNotSleep
); 
 727 //********************************************************************************* 
 730 // Notify registered applications and kernel clients that we are raising power. 
 732 // We override the superclass implementation so we can send a different message 
 733 // type to the client or application being notified. 
 734 //********************************************************************************* 
 736 void IOPMrootDomain::tellChangeUp ( unsigned long ) 
 738     return tellClients(kIOMessageSystemHasPoweredOn
); 
 741 //********************************************************************************* 
 744 //********************************************************************************* 
 746 void IOPMrootDomain::reportUserInput ( void ) 
 751         iter 
= getMatchingServices(serviceMatching("IODisplayWrangler")); 
 753             wrangler 
= (IOService 
*) iter
->getNextObject(); 
 759         wrangler
->activityTickle(0,0); 
 762 //********************************************************************************* 
 763 // setQuickSpinDownTimeout 
 765 //********************************************************************************* 
 767 void IOPMrootDomain::setQuickSpinDownTimeout ( void ) 
 769     //IOLog("setQuickSpinDownTimeout\n"); 
 770     super::setAggressiveness((unsigned long)kPMMinutesToSpinDown
,(unsigned long)1); 
 773 //********************************************************************************* 
 774 // restoreUserSpinDownTimeout 
 776 //********************************************************************************* 
 778 void IOPMrootDomain::restoreUserSpinDownTimeout ( void ) 
 781         IOLog("!!!!! WARNING !!!!! restoreUserSpinDownTimeout called too early\n"); 
 783     //IOLog("restoreUserSpinDownTimeout, user_spindown = %u\n", user_spindown); 
 785     super::setAggressiveness((unsigned long)kPMMinutesToSpinDown
,(unsigned long)user_spindown
); 
 789 //********************************************************************************* 
 790 // sysPowerDownHandler 
 792 // Receives a notification when the RootDomain changes state.  
 794 // Allows us to take action on system sleep, power down, and restart after 
 795 // applications have received their power change notifications and replied, 
 796 // but before drivers have powered down. We perform a vfs sync on power down. 
 797 //********************************************************************************* 
 799 IOReturn 
IOPMrootDomain::sysPowerDownHandler( void * target
, void * refCon
, 
 800                                     UInt32 messageType
, IOService 
* service
, 
 801                                     void * messageArgument
, vm_size_t argSize 
) 
 804     IOPowerStateChangeNotification 
* params 
= (IOPowerStateChangeNotification 
*) messageArgument
; 
 805     IOPMrootDomain 
*                 rootDomain 
= OSDynamicCast(IOPMrootDomain
, service
); 
 808         return kIOReturnUnsupported
; 
 810     switch (messageType
) { 
 811         case kIOMessageSystemWillSleep
: 
 812             rootDomain
->powerOverrideOnPriv();          // start ignoring children's requests 
 813                                                         // (fall through to other cases) 
 814         case kIOMessageSystemWillPowerOff
: 
 815         case kIOMessageSystemWillRestart
: 
 817             // Interested applications have been notified of an impending power 
 818             // change and have acked (when applicable). 
 819             // This is our chance to save whatever state we can before powering 
 821             // We call sync_internal defined in xnu/bsd/vfs/vfs_syscalls.c, 
 824             // We will ack within 20 seconds 
 825             params
->returnValue 
= 20 * 1000 * 1000; 
 827             if ( ! OSCompareAndSwap( 0, 1, &gSleepOrShutdownPending 
) ) 
 829                 // Purposely delay the ack and hope that shutdown occurs quickly. 
 830                 // Another option is not to schedule the thread and wait for 
 832                 AbsoluteTime deadline
; 
 833                 clock_interval_to_deadline( 15, kSecondScale
, &deadline 
); 
 834                 thread_call_enter1_delayed( rootDomain
->diskSyncCalloutEntry
,  
 835                                             (thread_call_param_t
)params
->powerRef
, 
 839                 thread_call_enter1(rootDomain
->diskSyncCalloutEntry
, (thread_call_param_t
)params
->powerRef
); 
 840             ret 
= kIOReturnSuccess
; 
 843             ret 
= kIOReturnUnsupported
; 
 849 //********************************************************************************* 
 850 // displayWranglerNotification 
 852 // Receives a notification when the IODisplayWrangler changes state. 
 854 // Allows us to take action on display dim/undim. 
 856 // When the display goes dim we: 
 857 // - Start the idle sleep timer 
 858 // - set the quick spin down timeout 
 860 // On wake from display dim: 
 861 // - Cancel the idle sleep timer 
 862 // - restore the user's chosen spindown timer from the "quick" spin down value 
 863 //********************************************************************************* 
 865 IOReturn 
IOPMrootDomain::displayWranglerNotification( void * target
, void * refCon
, 
 866                                     UInt32 messageType
, IOService 
* service
, 
 867                                     void * messageArgument
, vm_size_t argSize 
) 
 869     IOPMrootDomain 
*                rootDomain 
= OSDynamicCast(IOPMrootDomain
, (IOService 
*)target
); 
 870     AbsoluteTime                 deadline
; 
 871     static bool                  deviceAlreadyPoweredOff 
= false; 
 874         return kIOReturnUnsupported
; 
 876     switch (messageType
) { 
 877        case kIOMessageDeviceWillPowerOff
: 
 878             // The IODisplayWrangler has powered off either because of idle display sleep 
 879             // or force system sleep. 
 881             // The display wrangler will send the DeviceWillPowerOff message 4 times until 
 882             // it gets into its lowest state. We only want to act on the first of those 4. 
 883             if( deviceAlreadyPoweredOff 
) return kIOReturnUnsupported
; 
 885            deviceAlreadyPoweredOff 
= true; 
 887            if( rootDomain
->extraSleepDelay 
) { 
 889                 // start the extra sleep timer 
 890                 clock_interval_to_deadline(rootDomain
->extraSleepDelay
*60, kSecondScale
, &deadline 
); 
 891                 thread_call_enter_delayed(rootDomain
->extraSleepTimer
, deadline
); 
 892                 rootDomain
->idleSleepPending 
= true; 
 896                 // accelerate disk spin down if spin down timer is non-zero (zero = never spin down) 
 897                 if(0 != rootDomain
->user_spindown
) 
 898                     rootDomain
->setQuickSpinDownTimeout(); 
 903         case kIOMessageDeviceHasPoweredOn
: 
 905             // The display has powered on either because of UI activity or wake from sleep/doze 
 906             deviceAlreadyPoweredOff 
= false; 
 907             rootDomain
->adjustPowerState(); 
 910             // cancel any pending idle sleep 
 911             if(rootDomain
->idleSleepPending
) { 
 912                 thread_call_cancel(rootDomain
->extraSleepTimer
); 
 913                 rootDomain
->idleSleepPending 
= false; 
 916             // Change the spindown value back to the user's selection from our accelerated setting 
 917             if(0 != rootDomain
->user_spindown
) 
 918                 rootDomain
->restoreUserSpinDownTimeout(); 
 920             // Put on the policy maker's on clamp. 
 927      return kIOReturnUnsupported
; 
 930 //********************************************************************************* 
 931 // displayWranglerPublished 
 933 // Receives a notification when the IODisplayWrangler is published. 
 934 // When it's published we install a power state change handler. 
 936 //********************************************************************************* 
 938 bool IOPMrootDomain::displayWranglerPublished( void * target
, void * refCon
, 
 939                                     IOService 
* newService
) 
 941     IOPMrootDomain 
*                rootDomain 
= OSDynamicCast(IOPMrootDomain
, (IOService 
*)target
); 
 946        rootDomain
->wrangler 
= newService
; 
 948        // we found the display wrangler, now install a handler 
 949        if( !rootDomain
->wrangler
->registerInterest( gIOGeneralInterest
, &displayWranglerNotification
, target
, 0) ) { 
 950                IOLog("IOPMrootDomain::displayWranglerPublished registerInterest failed\n"); 
 958 //********************************************************************************* 
 961 // Some condition that affects our wake/sleep/doze decision has changed. 
 963 // If the sleep slider is in the off position, we cannot sleep or doze. 
 964 // If the enclosure is open, we cannot sleep or doze. 
 965 // If the system is still booting, we cannot sleep or doze. 
 967 // In those circumstances, we prevent sleep and doze by holding power on with 
 968 // changePowerStateToPriv(ON). 
 970 // If the above conditions do not exist, and also the sleep timer has expired, we 
 971 // allow sleep or doze to occur with either changePowerStateToPriv(SLEEP) or 
 972 // changePowerStateToPriv(DOZE) depending on whether or not we already know the 
 973 // platform cannot sleep. 
 975 // In this case, sleep or doze will either occur immediately or at the next time 
 976 // that no children are holding the system out of idle sleep via the  
 977 // kIOPMPreventIdleSleep flag in their power state arrays. 
 978 //********************************************************************************* 
 980 void IOPMrootDomain::adjustPowerState( void ) 
 982     if ( (sleepSlider 
== 0) || 
 985         changePowerStateToPriv(ON_STATE
); 
 990             if ( sleepIsSupported 
) { 
 991                 changePowerStateToPriv(SLEEP_STATE
); 
 994                 changePowerStateToPriv(DOZE_STATE
); 
1001 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 
1004 #define super IOService 
1006 OSDefineMetaClassAndStructors(IORootParent
, IOService
) 
1008 // This array exactly parallels the state array for the root domain. 
1009 // Power state changes initiated by a device can be vetoed by a client of the device, and 
1010 // power state changes initiated by the parent of a device cannot be vetoed by a client of the device, 
1011 // so when the root domain wants a power state change that cannot be vetoed (e.g. demand sleep), it asks 
1012 // its parent to make the change.  That is the reason for this complexity. 
1014 static IOPMPowerState patriarchPowerStates
[number_of_power_states
] = { 
1015     {1,0,0,0,0,0,0,0,0,0,0,0},                                          // off 
1016     {1,0,RESTART_POWER
,0,0,0,0,0,0,0,0,0},                              // reset 
1017     {1,0,SLEEP_POWER
,0,0,0,0,0,0,0,0,0},                                // sleep 
1018     {1,0,DOZE_POWER
,0,0,0,0,0,0,0,0,0},                                 // doze 
1019     {1,0,ON_POWER
,0,0,0,0,0,0,0,0,0}                                    // running 
1022 bool IORootParent::start ( IOService 
* nub 
) 
1024     mostRecentChange 
= ON_STATE
; 
1027     registerPowerDriver(this,patriarchPowerStates
,number_of_power_states
); 
1028     powerOverrideOnPriv(); 
1033 void IORootParent::shutDownSystem ( void ) 
1035     mostRecentChange 
= OFF_STATE
; 
1036     changePowerStateToPriv(OFF_STATE
); 
1040 void IORootParent::restartSystem ( void ) 
1042     mostRecentChange 
= RESTART_STATE
; 
1043     changePowerStateToPriv(RESTART_STATE
); 
1047 void IORootParent::sleepSystem ( void ) 
1049     mostRecentChange 
= SLEEP_STATE
; 
1050     changePowerStateToPriv(SLEEP_STATE
); 
1054 void IORootParent::dozeSystem ( void ) 
1056     mostRecentChange 
= DOZE_STATE
; 
1057     changePowerStateToPriv(DOZE_STATE
); 
1060 // Called in demand sleep when sleep discovered to be impossible after actually attaining that state. 
1061 // This brings the parent to doze, which allows the root to step up from sleep to doze. 
1063 // In idle sleep, do nothing because the parent is still on and the root can freely change state. 
1065 void IORootParent::sleepToDoze ( void ) 
1067     if ( mostRecentChange 
== SLEEP_STATE 
) { 
1068         changePowerStateToPriv(DOZE_STATE
); 
1073 void IORootParent::wakeSystem ( void ) 
1075     mostRecentChange 
= ON_STATE
; 
1076     changePowerStateToPriv(ON_STATE
);