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@ 
  23 #include <IOKit/IOService.h> 
  24 #include <IOKit/IOLib.h> 
  25 #include <IOKit/IOCommandQueue.h> 
  26 #include <IOKit/IOCommandGate.h> 
  27 #include <IOKit/IOTimerEventSource.h> 
  28 #include <IOKit/IOWorkLoop.h> 
  29 #include <IOKit/IOPlatformExpert.h> 
  30 #include <IOKit/assert.h> 
  31 #include <IOKit/IOMessage.h> 
  32 #include <IOKit/pwr_mgt/IOPMinformee.h> 
  33 #include "IOKit/pwr_mgt/IOPMinformeeList.h" 
  34 #include "IOKit/pwr_mgt/IOPMchangeNoteList.h" 
  35 #include "IOKit/pwr_mgt/IOPMlog.h" 
  36 #include "IOKit/pwr_mgt/IOPowerConnection.h" 
  37 #include <kern/clock.h> 
  39 #define super IORegistryEntry 
  41 static void ack_timer_expired(thread_call_param_t
); 
  42 static void settle_timer_expired(thread_call_param_t
); 
  43 void PMreceiveCmd ( OSObject 
*,  void *, void *, void *, void * ); 
  44 static void PM_idle_timer_expired(OSObject 
*, IOTimerEventSource 
*); 
  45 static void c_PM_Clamp_Timer_Expired (OSObject 
* client
,IOTimerEventSource 
*); 
  46 void tellAppWithResponse ( OSObject 
* object
, void * context
); 
  47 void tellClientWithResponse ( OSObject 
* object
, void * context
); 
  48 void tellClient ( OSObject 
* object
, void * context
); 
  49 IOReturn 
serializedAllowPowerChange ( OSObject 
*, void *, void *, void *, void *); 
  50 IOReturn 
serializedCancelPowerChange ( OSObject 
*, void *, void *, void *, void *); 
  52 extern const IORegistryPlane 
* gIOPowerPlane
; 
  55 // and there's 1000 nanoseconds in a microsecond: 
  56 #define ns_per_us 1000 
  59 // The current change note is processed by a state machine. 
  60 // Inputs are acks from interested parties, ack from the controlling driver, 
  61 // ack timeouts, settle timeout, and powerStateDidChange from the parent. 
  62 // These are the states: 
  65     IOPMour_prechange_03 
= 1, 
  87 enum {                          // values of outofbandparameter 
  92 struct context 
{                // used for applyToInterested 
  93     OSArray 
*   responseFlags
; 
  96     UInt32      maxTimeRequested
; 
 100     unsigned long stateNumber
; 
 101     IOPMPowerFlags stateFlags
; 
 104                                 // five minutes in microseconds 
 105 #define FIVE_MINUTES 5*60*1000000 
 106 #define k30seconds 30*1000000 
 109  There are two different kinds of power state changes.  One is initiated by a subclassed device object which has either 
 110  decided to change power state, or its controlling driver has suggested it, or some other driver wants to use the 
 111  idle device and has asked it to become usable.  The second kind of power state change is initiated by the power 
 112  domain parent.  The two are handled slightly differently. 
 114 There is a queue of so-called change notifications, or change notes for short.  Usually the queue is empty, and when 
 115  it isn't, usually there is one change note in it, but since it's possible to have more than one power state change pending 
 116  at one time, a queue is implemented.  Example:  the subclass device decides it's idle and initiates a change to a lower 
 117  power state.  This causes interested parties to be notified, but they don't all acknowledge right away.  This causes the 
 118  change note to sit in the queue until all the acks are received.  During this time, the device decides it isn't idle anymore and 
 119  wants to raise power back up again.  This change can't be started, however, because the previous one isn't complete yet, 
 120  so the second one waits in the queue.  During this time, the parent decides to lower or raise the power state of the entire 
 121  power domain and notifies the device, and that notification goes into the queue, too, and can't be actioned until the 
 124  This is how a power change initiated by the subclass device is handled: 
 125  First, all interested parties are notified of the change via their powerStateWillChangeTo method.  If they all don't 
 126  acknowledge via return code, then we have to wait.  If they do, or when they finally all acknowledge via our 
 127  acknowledgePowerChange method, then we can continue.  We call the controlling driver, instructing it to change to 
 128  the new state.  Then we wait for power to settle.  If there is no settling-time, or after it has passed, we notify 
 129  interested parties again, this time via their powerStateDidChangeTo methods.  When they have all acked, we're done. 
 130  If we lowered power and don't need the power domain to be in its current power state, we suggest to the parent that 
 131  it lower the power domain state. 
 133  This is how a change to a lower power domain state initiated by the parent is handled: 
 134  First, we figure out what power state we will be in when the new domain state is reached.  Then all interested parties are 
 135  notified that we are moving to that new state.  When they have acknowledged, we call the controlling driver to assume 
 136  that state and we wait for power to settle.  Then we acknowledge our preparedness to our parent.  When all its interested 
 137  parties have acknowledged, it lowers power and then notifies its interested parties again.  When we get this call, we notify 
 138  our interested parties that the power state has changed, and when they have all acknowledged, we're done. 
 140  This is how a change to a higher power domain state initiated by the parent is handled: 
 141  We figure out what power state we will be in when the new domain state is reached.  If it is different from our current 
 142  state we acknowledge the parent.  When all the parent's interested parties have acknowledged, it raises power in the 
 143 domain and waits for power to settle.  Then it  notifies everyone that the new state has been reached.  When we get this call, 
 144  we call the controlling driver, instructing it  to assume the new state, and wait for power to settle.  Then we notify our interested 
 145  parties.  When they all acknowledge  we are done. 
 147  In either of the two cases above, it is possible that we will not be changing state even though the domain is.  Examples: 
 148  A change to a lower domain state may not affect us because we are already in a low enough state, and 
 149  We will not take advantage of a change to a higher domain state, because we have no need of the higher power. 
 150  In such a case, there is nothing to do but acknowledge the parent.  So when the parent calls our powerDomainWillChange 
 151  method, and we decide that we will not be changing state, we merely acknowledge the parent, via return code, and wait. 
 152  When the parent subsequently calls powerStateDidChange, we acknowledge again via return code, and the change is complete. 
 154  Power state changes are processed in a state machine, and since there are four varieties of power state changes, there are 
 155  four major paths through the state machine: 
 157  The fourth is nearly trivial.  In this path, the parent is changing the domain state, but we are not changing the device state. 
 158  The change starts when the parent calls powerDomainWillChange.  All we do is acknowledge the parent. 
 159 When the parent calls powerStateDidChange, we acknowledge the parent again, and we're done. 
 161  The first is fairly simple.  It starts when a power domain child calls requestPowerDomainState and we decide to change power states 
 162  to accomodate the child, or if our power-controlling driver calls changePowerStateTo, or if some other driver which is using our 
 163  device calls makeUsable, or if a subclassed object calls changePowerStateToPriv.  These are all power changes initiated by us, not 
 164  forced upon us by the parent.  We start by notifying interested parties.  If they all acknowledge via return code, we can go 
 165  on to state "our_prechange_1".  Otherwise, we start the ack timer and wait for the stragglers to acknowlege by calling 
 166  acknowledgePowerChange.  We move on to state "our_prechange_1" when all the stragglers have acknowledged, 
 167  or when the ack timer expires on all those which didn't acknowledge.  In "our_prechange_1" we call the power-controlling 
 168  driver to change the power state of the hardware.  If it returns saying it has done so, we go on to state "our_prechange_2". 
 169  Otherwise, we have to wait for it, so we set the ack timer and wait.  When it calls acknowledgeSetPowerState, or when the 
 170  ack timer expires, we go on.  In "our_prechange_2", we look in the power state array to see if there is any settle time required 
 171  when changing from our current state to the new state.  If not, we go right away to "our_prechange_3".  Otherwise, we 
 172  set the settle timer and wait.  When it expires, we move on.  In "our_prechange_3" state, we notify all our interested parties 
 173  via their powerStateDidChange methods that we have finished changing power state.  If they all acknowledge via return 
 174  code, we move on to "our_prechange_4".  Otherwise we set the ack timer and wait.  When they have all acknowledged, or 
 175  when the ack timer has expired for those that didn't, we move on to "our_prechange_4", where we remove the used 
 176  change note from the head of the queue and start the next one if one exists. 
 178  Parent-initiated changes are more complex in the state machine.  First, power going up and power going down are handled 
 179  differently, so they have different paths throught the state machine.  Second, we can acknowledge the parent's notification 
 180  in two different ways, so each of the parent paths is really two. 
 182  When the parent calls our powerDomainWillChange method, notifying us that it will lower power in the domain, we decide 
 183  what state that will put our device in.  Then we embark on the state machine path "IOPMparent_down_1" 
 184  and "IOPMparent_down_2", in which we notify interested parties of the upcoming change,  instruct our driver to make 
 185  the change, check for settle time, and notify interested parties of the completed change.   If we get to the end of this path without 
 186  stalling due to an interested party which didn't acknowledge via return code, due to the controlling driver not able to change 
 187  state right away, or due to a non-zero settling time, then we return IOPMAckImplied to the parent, and we're done with the change. 
 188  If we do stall in any of those states, we return IOPMWillAckLater to the parent and enter the parallel path "IOPMparent_down_4" 
 189  "IOPMparent_down_5", and "IOPMparent_down_3", where we continue with the same processing, except that at the end we 
 190  acknowledge the parent explicitly via acknowledgePowerChange, and we're done with the change. 
 191 Then when the parent calls us at powerStateDidChange we acknowledging via return code, because we have already made 
 192  the power change.  In any case, when we are done we remove the used change note from the head of the queue and start on the next one. 
 194  The case of the parent raising power in the domain is handled similarly in that there are parallel paths, one for no-stall 
 195  that ends in implicit acknowleging the parent, and one that has stalled at least once that ends in explicit acknowledging 
 196  the parent.  This case is different, though in that our device changes state in the second half, after the parent calls 
 197  powerStateDidChange rather than before, as in the power-lowering case. 
 199  When the parent calls our powerDomainWillChange method, notifying us that it will raise power in the domain, we acknowledge 
 200  via return code, because there's really nothing we can do until the power is actually raised in the domain. 
 201  When the parent calls us at powerStateDidChange, we start by notifying our interested parties.  If they all acknowledge via return code, 
 202  we go on to" IOPMparent_up_1" to instruct the driver to raise its power level. After that, we check for any 
 203  necessary settling time in "IOPMparent_up_2", and we notify all interested parties that power has changed 
 204  in "IOPMparent_up_3".  If none of these operations stall, we acknowledge the parent via return code, release 
 205  the change note, and start the next, if there is one.  If one of them does stall, we enter the parallel path  "IOPMparent_up_0", 
 206  "IOPMparent_up_4", "IOPMparent_up_5", and "IOPMparent_up_6", which ends with 
 207  our explicit acknowledgement to the parent. 
 212 const char priv_key
[ ] = "Power Management private data"; 
 213 const char prot_key
[ ] = "Power Management protected data"; 
 216 void IOService::PMinit ( void ) 
 218     if ( ! initialized 
) { 
 220         pm_vars 
=  new IOPMprot
;                                        // make space for our variables 
 225         setProperty(prot_key
, (OSObject 
*) pm_vars
);                    // add these to the properties 
 226         setProperty(priv_key
, (OSObject 
*) priv
); 
 229         pm_vars
->theNumberOfPowerStates 
= 0;                            // then initialize them 
 230         priv
->we_are_root 
= false; 
 231         pm_vars
->theControllingDriver 
= NULL
; 
 232         priv
->our_lock 
= IOLockAlloc(); 
 233         priv
->flags_lock 
= IOLockAlloc(); 
 234         priv
->queue_lock 
= IOLockAlloc(); 
 235         pm_vars
->childLock 
= IOLockAlloc(); 
 236         pm_vars
->parentLock 
= IOLockAlloc(); 
 237         priv
->interestedDrivers 
= new IOPMinformeeList
; 
 238         priv
->interestedDrivers
->initialize(); 
 239         priv
->changeList 
= new IOPMchangeNoteList
; 
 240         priv
->changeList
->initialize(); 
 241         pm_vars
->aggressiveness 
= 0; 
 242         for (unsigned int i 
= 0; i 
<= kMaxType
; i
++) { 
 243              pm_vars
->current_aggressiveness_values
[i
] = 0; 
 244              pm_vars
->current_aggressiveness_valid
[i
] = false; 
 246         pm_vars
->myCurrentState 
=  0; 
 247         priv
->imminentState 
= 0; 
 248         priv
->ourDesiredPowerState 
= 0; 
 249         pm_vars
->parentsCurrentPowerFlags 
= 0; 
 250         pm_vars
->maxCapability 
= 0; 
 251         priv
->driverDesire 
= 0; 
 252         priv
->deviceDesire 
= 0; 
 253         priv
->initial_change 
= true; 
 254         priv
->need_to_become_usable 
= false; 
 255         priv
->previousRequest 
= 0; 
 256         priv
->device_overrides 
= false; 
 257         priv
->machine_state 
= IOPMfinished
; 
 258         pm_vars
->commandQueue 
= NULL
; 
 259         priv
->timerEventSrc 
= NULL
; 
 260         priv
->clampTimerEventSrc 
= NULL
; 
 261         pm_vars
->PMworkloop 
= NULL
; 
 262         priv
->activityLock 
= NULL
; 
 263         pm_vars
->ourName 
= getName(); 
 264         pm_vars
->thePlatform 
= getPlatform(); 
 265         pm_vars
->parentsKnowState 
= false; 
 266         assert( pm_vars
->thePlatform 
!= 0 ); 
 267         priv
->clampOn 
= false; 
 268         pm_vars
->serialNumber 
= 0; 
 269         pm_vars
->responseFlags 
= NULL
; 
 270         pm_vars
->doNotPowerDown 
= true; 
 271         pm_vars
->PMcommandGate 
= NULL
; 
 272         priv
->ackTimer 
= thread_call_allocate((thread_call_func_t
)ack_timer_expired
, (thread_call_param_t
)this); 
 273         priv
->settleTimer 
= thread_call_allocate((thread_call_func_t
)settle_timer_expired
, (thread_call_param_t
)this); 
 279 //********************************************************************************* 
 282 // Free up the data created in PMinit, if it exists. 
 283 //********************************************************************************* 
 284 void IOService::PMfree ( void ) 
 287         if (  priv
->clampTimerEventSrc 
!= NULL 
) { 
 288             getPMworkloop()->removeEventSource(priv
->clampTimerEventSrc
); 
 289             priv
->clampTimerEventSrc
->release(); 
 290             priv
->clampTimerEventSrc 
= NULL
; 
 292         if (  priv
->timerEventSrc 
!= NULL 
) { 
 293             pm_vars
->PMworkloop
->removeEventSource(priv
->timerEventSrc
); 
 294             priv
->timerEventSrc
->release(); 
 295             priv
->timerEventSrc 
= NULL
; 
 297         if ( priv
->settleTimer 
) { 
 298             thread_call_cancel(priv
->settleTimer
); 
 299             thread_call_free(priv
->settleTimer
); 
 300             priv
->settleTimer 
= NULL
; 
 302         if ( priv
->ackTimer 
) { 
 303             thread_call_cancel(priv
->ackTimer
); 
 304             thread_call_free(priv
->ackTimer
); 
 305             priv
->ackTimer 
= NULL
; 
 307         if ( priv
->our_lock 
) { 
 308             IOLockFree(priv
->our_lock
); 
 309             priv
->our_lock 
= NULL
; 
 311         if ( priv
->flags_lock 
) { 
 312             IOLockFree(priv
->flags_lock
); 
 313             priv
->flags_lock 
= NULL
; 
 315         if ( priv
->activityLock 
) { 
 316             IOLockFree(priv
->activityLock
); 
 317             priv
->activityLock 
= NULL
; 
 319         priv
->interestedDrivers
->release(); 
 320         priv
->changeList
->release(); 
 321         priv
->release();                                // remove instance variables 
 325         if ( pm_vars
->commandQueue 
) { 
 326             pm_vars
->commandQueue
->release(); 
 327             pm_vars
->commandQueue 
= NULL
; 
 329         if ( pm_vars
->PMcommandGate 
) { 
 330             pm_vars
->PMcommandGate
->release(); 
 331             pm_vars
->PMcommandGate 
= NULL
; 
 333         if ( pm_vars
->PMworkloop 
) { 
 334             // The work loop object returned from getPMworkLoop() is 
 335             // never retained, therefore it should not be released. 
 336             // pm_vars->PMworkloop->release(); 
 337             pm_vars
->PMworkloop 
= NULL
; 
 339         if ( pm_vars
->responseFlags 
) { 
 340             pm_vars
->responseFlags
->release(); 
 341             pm_vars
->responseFlags 
= NULL
; 
 343         pm_vars
->release();                             // remove instance variables 
 348 //********************************************************************************* 
 351 // Disconnect the node from its parents and children in the Power Plane. 
 352 //********************************************************************************* 
 353 void IOService::PMstop ( void ) 
 357     IOPowerConnection 
* connection
; 
 358     IOService 
*         theChild
; 
 359     IOService 
*         theParent
; 
 361     removeProperty(prot_key
);                   // remove the properties 
 362     removeProperty(priv_key
); 
 364     iter 
= getParentIterator(gIOPowerPlane
);    // detach parents 
 367         while ( (next 
= iter
->getNextObject()) ) { 
 368             if ( (connection 
= OSDynamicCast(IOPowerConnection
,next
)) ) { 
 369                 theParent 
= (IOService 
*)connection
->copyParentEntry(gIOPowerPlane
); 
 371                     theParent
->removePowerChild(connection
); 
 372                     theParent
->release(); 
 378     detachAbove( gIOPowerPlane 
);               // detach IOConnections    
 380     pm_vars
->parentsKnowState 
= false;          // no more power state changes 
 382     iter 
= getChildIterator(gIOPowerPlane
);     // detach children 
 385         while ( (next 
= iter
->getNextObject()) ) { 
 386             if ( (connection 
= OSDynamicCast(IOPowerConnection
,next
)) ) { 
 387                 theChild 
= ((IOService 
*)(connection
->copyChildEntry(gIOPowerPlane
))); 
 389                     connection
->detachFromChild(theChild
,gIOPowerPlane
);        // detach nub from child 
 392                 detachFromChild(connection
,gIOPowerPlane
);                      // detach us from nub 
 398     // Remove all interested drivers from the list, including the power 
 399     // controlling driver. 
 401     // Usually, the controlling driver and the policy-maker functionality 
 402     // are implemented by the same object, and without the deregistration, 
 403     // the object will be holding an extra retain on itself, and cannot 
 406     if ( priv 
&& priv
->interestedDrivers 
) 
 408         IOPMinformee 
* informee
; 
 410         while (( informee 
= priv
->interestedDrivers
->firstInList() )) 
 411             deRegisterInterestedDriver( informee
->whatObject 
); 
 416 //********************************************************************************* 
 419 // A policy-maker calls its nub here when initializing, to be attached into 
 420 // the power management hierarchy.  The default function is to call the 
 421 // platform expert, which knows how to do it.  This method is overridden 
 422 // by a nub subclass which may either know how to do it, or may need 
 423 // to take other action. 
 425 // This may be the only "power management" method used in a nub, 
 426 // meaning it may not be initialized for power management. 
 427 //********************************************************************************* 
 428 void IOService::joinPMtree ( IOService 
* driver 
) 
 430     IOPlatformExpert 
* thePlatform
; 
 432     thePlatform 
= getPlatform(); 
 433     assert(thePlatform 
!= 0 ); 
 434     thePlatform
->PMRegisterDevice(this,driver
); 
 438 //********************************************************************************* 
 441 // Power Managment is informing us that we are the root power domain. 
 442 // The only difference between us and any other power domain is that 
 443 // we have no parent and therefore never call it. 
 444 //********************************************************************************* 
 445 IOReturn 
IOService::youAreRoot ( void ) 
 447     priv
-> we_are_root 
= true; 
 448     pm_vars
->parentsKnowState 
= true; 
 449     attachToParent( getRegistryRoot(),gIOPowerPlane 
); 
 455 //********************************************************************************* 
 458 // Power Management is informing us who our parent is. 
 459 // If we have a controlling driver, find out, given our newly-informed 
 460 // power domain state, what state it would be in, and then tell it 
 461 // to assume that state. 
 462 //********************************************************************************* 
 463 IOReturn 
IOService::setPowerParent ( IOPowerConnection 
* theParent
, bool stateKnown
, IOPMPowerFlags currentState 
) 
 467     IOPowerConnection 
* connection
; 
 468     unsigned long               tempDesire
; 
 470     pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogSetParent
,stateKnown
,currentState
); 
 472     IOLockLock(pm_vars
->parentLock
); 
 474     if ( stateKnown 
&& ((pm_vars
->PMworkloop 
== NULL
) || (pm_vars
->PMcommandGate 
== NULL
)) ) { 
 475         getPMworkloop();                                                // we have a path to the root 
 476         if ( pm_vars
->PMworkloop 
!= NULL 
) {                            // find out the workloop 
 477             if ( pm_vars
->PMcommandGate 
== NULL 
) {                     // and make our command gate 
 478                 pm_vars
->PMcommandGate 
= IOCommandGate::commandGate((OSObject 
*)this); 
 479                 if ( pm_vars
->PMcommandGate 
!= NULL 
) { 
 480                     pm_vars
->PMworkloop
->addEventSource(pm_vars
->PMcommandGate
); 
 486     IOLockUnlock(pm_vars
->parentLock
); 
 488     theParent
->setParentCurrentPowerFlags(currentState
);        // set our connection data 
 489     theParent
->setParentKnowsState(stateKnown
); 
 491     pm_vars
->parentsKnowState 
= true;                           // combine parent knowledge 
 492     pm_vars
->parentsCurrentPowerFlags 
= 0; 
 494     iter 
= getParentIterator(gIOPowerPlane
); 
 497         while ( (next 
= iter
->getNextObject()) ) { 
 498             if ( (connection 
= OSDynamicCast(IOPowerConnection
,next
)) ) { 
 499                 pm_vars
->parentsKnowState 
&= connection
->parentKnowsState(); 
 500                 pm_vars
->parentsCurrentPowerFlags 
|= connection
->parentCurrentPowerFlags(); 
 506     if ( (pm_vars
->theControllingDriver 
!= NULL
) && 
 507          (pm_vars
->parentsKnowState
) ) { 
 508         pm_vars
->maxCapability 
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(pm_vars
->parentsCurrentPowerFlags
); 
 509         tempDesire 
= priv
->deviceDesire
;                        // initially change into the state we are already in 
 510         priv
->deviceDesire 
= pm_vars
->theControllingDriver
->initialPowerStateForDomainState(pm_vars
->parentsCurrentPowerFlags
); 
 511         computeDesiredState(); 
 512         priv
->previousRequest 
= 0xffffffff; 
 514         priv
->deviceDesire 
= tempDesire
;                        // put this back like before 
 521 //********************************************************************************* 
 524 // Power Management is informing us who our children are. 
 525 //********************************************************************************* 
 526 IOReturn 
IOService::addPowerChild ( IOService 
* theChild 
) 
 528     IOPowerConnection 
* connection
; 
 531     if ( ! initialized 
) { 
 532         return IOPMNotYetInitialized
;   // we're not a power-managed IOService 
 535     pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAddChild
,0,0); 
 537     connection 
= new IOPowerConnection
;                 // make a nub 
 540     connection
->start(this); 
 541     connection
->setAwaitingAck(false); 
 543     attachToChild( connection
,gIOPowerPlane 
);                  // connect it up 
 544     connection
->attachToChild( theChild
,gIOPowerPlane 
); 
 545     connection
->release(); 
 547     if ( (pm_vars
->theControllingDriver 
== NULL
) ||             // tell it the current state of the power domain 
 548          ! (inPlane(gIOPowerPlane
)) || 
 549        ! (pm_vars
->parentsKnowState
) ) { 
 550         theChild
->setPowerParent(connection
,false,0); 
 551         if ( inPlane(gIOPowerPlane
) ) { 
 552             for (i 
= 0; i 
<= kMaxType
; i
++) { 
 553                 if ( pm_vars
->current_aggressiveness_valid
[i
] ) { 
 554                     theChild
->setAggressiveness (i
, pm_vars
->current_aggressiveness_values
[i
]); 
 560         theChild
->setPowerParent(connection
,true,pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].outputPowerCharacter
); 
 561         for (i 
= 0; i 
<= kMaxType
; i
++) { 
 562             if ( pm_vars
->current_aggressiveness_valid
[i
] ) { 
 563                 theChild
->setAggressiveness (i
, pm_vars
->current_aggressiveness_values
[i
]); 
 566         add_child_to_active_change(connection
);                                                 // catch it up if change is in progress 
 573 //********************************************************************************* 
 576 //********************************************************************************* 
 577 IOReturn 
IOService::removePowerChild ( IOPowerConnection 
* theNub 
) 
 579     IORegistryEntry 
* theChild
; 
 581     pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRemoveChild
,0,0); 
 585     theChild 
= theNub
->copyChildEntry(gIOPowerPlane
);                   // detach nub from child 
 587         theNub
->detachFromChild(theChild
, gIOPowerPlane
); 
 590     detachFromChild(theNub
,gIOPowerPlane
);                              // detach from the nub 
 592     if ( theNub
->getAwaitingAck() ) {                                   // are we awaiting an ack from this child? 
 593         theNub
->setAwaitingAck(false);                                  // yes, pretend we got one 
 594         if ( acquire_lock() ) { 
 595             if (priv
->head_note_pendingAcks 
!= 0 ) { 
 596                 priv
->head_note_pendingAcks 
-= 1;                       // that's one fewer ack to worry about 
 597                 if ( priv
->head_note_pendingAcks 
== 0 ) {               // is that the last? 
 598                     stop_ack_timer();                                   // yes, stop the timer 
 599                     IOUnlock(priv
->our_lock
); 
 600                     all_acked();                                        // and now we can continue our power change 
 603                     IOUnlock(priv
->our_lock
); 
 607                 IOUnlock(priv
->our_lock
); 
 614     if ( (pm_vars
->theControllingDriver 
== NULL
) ||     // if not fully initialized 
 615          ! (inPlane(gIOPowerPlane
)) || 
 616        ! (pm_vars
->parentsKnowState
) ) { 
 617         return IOPMNoErr
;                               // we can do no more 
 620     computeDesiredState();                              // this may be different now 
 621     changeState();                                      // change state if we can now tolerate lower power 
 627 //********************************************************************************* 
 628 // registerPowerDriver 
 630 // A driver has called us volunteering to control power to our device. 
 631 // If the power state array it provides is richer than the one we already 
 632 // know about (supplied by an earlier volunteer), then accept the offer. 
 633 // Notify all interested parties of our power state, which we now know. 
 634 //********************************************************************************* 
 636 IOReturn 
IOService::registerPowerDriver ( IOService 
* controllingDriver
, IOPMPowerState
* powerStates
, unsigned long numberOfStates  
) 
 639     unsigned long tempDesire
; 
 641     if ( (numberOfStates 
> pm_vars
->theNumberOfPowerStates
) && (numberOfStates 
> 1) ) { 
 642         if (  priv
->changeList
->currentChange() == -1 ) { 
 643             if ( controllingDriver 
!= NULL 
) { 
 644                 if ( numberOfStates 
<= IOPMMaxPowerStates 
) { 
 645                     switch ( powerStates
[0].version  
) { 
 647                             pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriver
, 
 648                                                                     (unsigned long)numberOfStates
, (unsigned long)powerStates
[0].version
); 
 649                             for ( i 
= 0; i 
< numberOfStates
; i
++ ) { 
 650                                 pm_vars
->thePowerStates
[i
] = powerStates
[i
]; 
 654                             pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriver
, 
 655                                                                     (unsigned long) numberOfStates
,(unsigned long) powerStates
[0].version
); 
 656                             for ( i 
= 0; i 
< numberOfStates
; i
++ ) { 
 657                                 pm_vars
->thePowerStates
[i
].version 
= powerStates
[i
].version
; 
 658                                 pm_vars
->thePowerStates
[i
].capabilityFlags 
= powerStates
[i
].capabilityFlags
; 
 659                                 pm_vars
->thePowerStates
[i
].outputPowerCharacter 
= powerStates
[i
].outputPowerCharacter
; 
 660                                 pm_vars
->thePowerStates
[i
].inputPowerRequirement 
= powerStates
[i
].inputPowerRequirement
; 
 661                                 pm_vars
->thePowerStates
[i
].staticPower 
= powerStates
[i
].staticPower
; 
 662                                 pm_vars
->thePowerStates
[i
].unbudgetedPower 
= powerStates
[i
].unbudgetedPower
; 
 663                                 pm_vars
->thePowerStates
[i
].powerToAttain 
= powerStates
[i
].powerToAttain
; 
 664                                 pm_vars
->thePowerStates
[i
].timeToAttain 
= powerStates
[i
].timeToAttain
; 
 665                                 pm_vars
->thePowerStates
[i
].settleUpTime 
= powerStates
[i
].settleUpTime
; 
 666                                 pm_vars
->thePowerStates
[i
].timeToLower 
= powerStates
[i
].timeToLower
; 
 667                                 pm_vars
->thePowerStates
[i
].settleDownTime 
= powerStates
[i
].settleDownTime
; 
 668                                 pm_vars
->thePowerStates
[i
].powerDomainBudget 
= powerStates
[i
].powerDomainBudget
; 
 672                             pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr1
, 
 673                                                                     (unsigned long)powerStates
[0].version
,0); 
 677                     pm_vars
->myCharacterFlags 
= 0;      // make a mask of all the character bits we know about 
 678                     for ( i 
= 0; i 
< numberOfStates
; i
++ ) { 
 679                         pm_vars
->myCharacterFlags 
|= pm_vars
->thePowerStates
[i
].outputPowerCharacter
; 
 682                    pm_vars
->theNumberOfPowerStates 
= numberOfStates
; 
 683                     pm_vars
->theControllingDriver 
= controllingDriver
; 
 684                     if ( priv
->interestedDrivers
->findItem(controllingDriver
) == NULL 
) {       // register it as interested 
 685                         registerInterestedDriver (controllingDriver 
);                          // unless already done 
 687                     if ( priv
->need_to_become_usable 
) { 
 688                         priv
->need_to_become_usable 
= false; 
 689                         priv
->deviceDesire 
= pm_vars
->theNumberOfPowerStates 
- 1; 
 692                     if ( inPlane(gIOPowerPlane
) && 
 693                          (pm_vars
->parentsKnowState
) ) { 
 694                         pm_vars
->maxCapability 
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(pm_vars
->parentsCurrentPowerFlags
); 
 695                         tempDesire 
= priv
->deviceDesire
;                        // initially change into the state we are already in 
 696                         priv
->deviceDesire 
= pm_vars
->theControllingDriver
->initialPowerStateForDomainState(pm_vars
->parentsCurrentPowerFlags
); 
 697                         computeDesiredState(); 
 699                         priv
->deviceDesire 
= tempDesire
;                        // put this back like before 
 703                     pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr2
,(unsigned long)numberOfStates
,0); 
 707                 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr4
,0,0); 
 712         pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr5
,(unsigned long)numberOfStates
,0); 
 717 //********************************************************************************* 
 718 // registerInterestedDriver 
 720 // Add the caller to our list of interested drivers and return our current 
 721 // power state.  If we don't have a power-controlling driver yet, we will 
 722 // call this interested driver again later when we do get a driver and find 
 723 // out what the current power state of the device is. 
 724 //********************************************************************************* 
 726 IOPMPowerFlags 
IOService::registerInterestedDriver ( IOService 
* theDriver 
) 
 728     IOPMinformee 
* newInformee
; 
 729     IOPMPowerFlags futureCapability
; 
 731     if (theDriver 
== NULL 
) { 
 735     newInformee 
= new IOPMinformee
;                             // make new driver node 
 736     newInformee
->initialize(theDriver
); 
 737     priv
->interestedDrivers
->addToList(newInformee
);                    // add it to list of drivers 
 739     if ( (pm_vars
->theControllingDriver 
== NULL
) || 
 740          ! (inPlane(gIOPowerPlane
)) || 
 741        ! (pm_vars
->parentsKnowState
) ) { 
 742         pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInterestedDriver
,IOPMNotPowerManaged
,0); 
 743         return IOPMNotPowerManaged
;                                     // can't tell it a state yet 
 746     switch (priv
->machine_state
) {                                      // can we notify new driver of a change in progress? 
 747         case IOPMour_prechange_1
: 
 748         case IOPMour_prechange_4
: 
 749         case IOPMparent_down_4
: 
 750         case IOPMparent_down_6
: 
 751         case IOPMparent_up_0
: 
 752         case IOPMparent_up_6
: 
 753             futureCapability 
= priv
->head_note_capabilityFlags
;                 // yes, remember what we tell it 
 754             pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInterestedDriver
,(unsigned long)futureCapability
,1); 
 755             add_driver_to_active_change(newInformee
);                           // notify it 
 756             return futureCapability
;                                            // and return the same thing 
 759     pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInterestedDriver
, 
 760                                             (unsigned long) pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
,2); 
 761     return  pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
;   // no, return current capability 
 765 //********************************************************************************* 
 766 // deRegisterInterestedDriver 
 768 //********************************************************************************* 
 769 IOReturn 
IOService::deRegisterInterestedDriver ( IOService 
* theDriver 
) 
 771     pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRemoveDriver
,0,0); 
 773     priv
->interestedDrivers
->removeFromList(theDriver
);                           // remove the departing driver 
 779 //********************************************************************************* 
 780 // acknowledgePowerChange 
 782 // After we notified one of the interested drivers or a power-domain child 
 783 // of an impending change in power, it has called to say it is now 
 784 // prepared for the change.  If this object is the last to 
 785 // acknowledge this change, we take whatever action we have been waiting 
 787 // That may include acknowledging to our parent.  In this case, we do it 
 788 // last of all to insure that this doesn't cause the parent to call us some- 
 789 // where else and alter data we are relying on here (like the very existance 
 790 // of a "current change note".) 
 791 //********************************************************************************* 
 793 IOReturn 
IOService::acknowledgePowerChange ( IOService 
* whichObject 
) 
 795    IOPMinformee 
*       ackingObject
; 
 796    unsigned long        childPower 
= kIOPMUnknown
; 
 797    IOService 
*          theChild
; 
 799     ackingObject 
=  priv
->interestedDrivers
->findItem(whichObject
);                             // one of our interested drivers? 
 800    if ( ackingObject 
== NULL 
) { 
 801        if ( ! isChild(whichObject
,gIOPowerPlane
) ) { 
 802            pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr1
,0,0); 
 803            kprintf("errant driver: %s\n",whichObject
->getName()); 
 804            return IOPMNoErr
;                                                    // no, just return 
 807            pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChildAcknowledge
,priv
->head_note_pendingAcks
,0); 
 811        pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogDriverAcknowledge
,priv
->head_note_pendingAcks
,0); 
 814    if (! acquire_lock() ) { 
 818    if (priv
->head_note_pendingAcks 
!= 0 ) {                                     // yes, make sure we're expecting acks 
 819        if ( ackingObject 
!= NULL 
) {                                            // it's an interested driver 
 820            if ( ackingObject
->timer 
!= 0 ) {                                    // make sure we're expecting this ack 
 821                ackingObject
->timer 
= 0;                                         // mark it acked 
 822                priv
->head_note_pendingAcks 
-= 1;                                // that's one fewer to worry about 
 823                if ( priv
->head_note_pendingAcks 
== 0 ) {                        // is that the last? 
 824                    stop_ack_timer();                                            // yes, stop the timer 
 825                    IOUnlock(priv
->our_lock
); 
 826                    all_acked();                                                 // and now we can continue 
 831                pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr2
,0,0);  // this driver has already acked 
 832            kprintf("errant driver: %s\n",whichObject
->getName()); 
 835        else {                                                                   // it's a child 
 836             if ( ((IOPowerConnection 
*)whichObject
)->getAwaitingAck() ) {       // make sure we're expecting this ack 
 837                 priv
->head_note_pendingAcks 
-= 1;                               // that's one fewer to worry about 
 838                 ((IOPowerConnection 
*)whichObject
)->setAwaitingAck(false); 
 839                 theChild 
= (IOService 
*)whichObject
->copyChildEntry(gIOPowerPlane
); 
 841                     childPower 
= theChild
->currentPowerConsumption(); 
 844                 if ( childPower 
== kIOPMUnknown 
) { 
 845                     pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower 
= kIOPMUnknown
; 
 848                     if ( pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower 
!= kIOPMUnknown 
) { 
 849                         pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower 
+= childPower
; 
 852                 if ( priv
->head_note_pendingAcks 
== 0 ) {                               // is that the last? 
 853                     stop_ack_timer();                                                   // yes, stop the timer 
 854                     IOUnlock(priv
->our_lock
); 
 855                     all_acked();                                                        // and now we can continue 
 862        pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr3
,0,0);  // not expecting anybody to ack 
 863        kprintf("errant driver: %s\n",whichObject
->getName()); 
 865    IOUnlock(priv
->our_lock
); 
 869 //********************************************************************************* 
 870 // acknowledgeSetPowerState 
 872 // After we instructed our controlling driver to change power states, 
 873 // it has called to say it has finished doing so. 
 874 // We continue to process the power state change. 
 875 //********************************************************************************* 
 877 IOReturn 
IOService::acknowledgeSetPowerState ( void ) 
 879     if (! acquire_lock() ) { 
 882     if ( priv
->driver_timer 
== -1 ) { 
 883         priv
->driver_timer 
= 0;                         // driver is acking instead of using return code 
 886         if ( priv
->driver_timer 
> 0 ) {                 // are we expecting this? 
 887             stop_ack_timer();                           // yes, stop the timer 
 888             priv
->driver_timer 
= 0; 
 889             IOUnlock(priv
->our_lock
); 
 890             pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogDriverAcknowledgeSet
,0,0); 
 895             pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr4
,0,0);             // no 
 898     IOUnlock(priv
->our_lock
); 
 903 //********************************************************************************* 
 906 // Either the controlling driver has called acknowledgeSetPowerState 
 907 // or the acknowledgement timer has expired while waiting for that. 
 908 // We carry on processing the current change note. 
 909 //********************************************************************************* 
 911 void IOService::driver_acked ( void ) 
 913     switch (priv
->machine_state
) { 
 914         case IOPMour_prechange_2
: 
 917         case IOPMparent_down_5
: 
 920         case IOPMparent_up_4
: 
 927 //********************************************************************************* 
 928 // powerDomainWillChangeTo 
 930 // Called by the power-hierarchy parent notifying of a new power state 
 931 // in the power domain. 
 932 // We enqueue a parent power-change to our queue of power changes. 
 933 // This may or may not cause us to change power, depending on what 
 934 // kind of change is occuring in the domain. 
 935 //********************************************************************************* 
 937 IOReturn 
IOService::powerDomainWillChangeTo ( IOPMPowerFlags newPowerStateFlags
, IOPowerConnection 
* whichParent 
) 
 941     IOPowerConnection 
* connection
; 
 942     unsigned long               newStateNumber
; 
 943     IOPMPowerFlags              combinedPowerFlags
; 
 945     pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogWillChange
,(unsigned long)newPowerStateFlags
,0); 
 947     if ( ! inPlane(gIOPowerPlane
) ) { 
 948         return IOPMAckImplied
;                                          // somebody goofed 
 951     IOLockLock(pm_vars
->parentLock
); 
 953     if ( (pm_vars
->PMworkloop 
== NULL
) || (pm_vars
->PMcommandGate 
== NULL
) ) { 
 954         getPMworkloop();                                                // we have a path to the root, 
 955         if ( pm_vars
->PMworkloop 
!= NULL 
) {                            // so find out the workloop 
 956             if ( pm_vars
->PMcommandGate 
== NULL 
) {                     // and make our command gate 
 957                 pm_vars
->PMcommandGate 
= IOCommandGate::commandGate((OSObject 
*)this); 
 958                 if ( pm_vars
->PMcommandGate 
!= NULL 
) { 
 959                     pm_vars
->PMworkloop
->addEventSource(pm_vars
->PMcommandGate
); 
 965     IOLockUnlock(pm_vars
->parentLock
); 
 967     combinedPowerFlags 
= 0;                                             // combine parents' power states 
 969     iter 
= getParentIterator(gIOPowerPlane
); 
 972         while ( (next 
= iter
->getNextObject()) ) { 
 973             if ( (connection 
= OSDynamicCast(IOPowerConnection
,next
)) ) { 
 974                 if ( connection 
== whichParent 
){ 
 975                     combinedPowerFlags 
|= newPowerStateFlags
; 
 978                     combinedPowerFlags 
|= connection
->parentCurrentPowerFlags(); 
 985     if  ( pm_vars
->theControllingDriver 
== NULL 
) {                                     // we can't take any more action 
 986         return IOPMAckImplied
; 
 988     newStateNumber 
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(combinedPowerFlags
); 
 989     return enqueuePowerChange(IOPMParentInitiated 
| IOPMDomainWillChange
, 
 990                             newStateNumber
,combinedPowerFlags
,whichParent
,newPowerStateFlags
);  //make the change 
 994 //********************************************************************************* 
 995 // powerDomainDidChangeTo 
 997 // Called by the power-hierarchy parent after the power state of the power domain 
 998 // has settled at a new level. 
 999 // We enqueue a parent power-change to our queue of power changes. 
1000 // This may or may not cause us to change power, depending on what 
1001 // kind of change is occuring in the domain. 
1002 //********************************************************************************* 
1004 IOReturn 
IOService::powerDomainDidChangeTo ( IOPMPowerFlags newPowerStateFlags
, IOPowerConnection 
* whichParent 
) 
1006     unsigned long newStateNumber
; 
1008     pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogDidChange
,newPowerStateFlags
,0); 
1010     setParentInfo(newPowerStateFlags
,whichParent
); 
1012     if ( pm_vars
->theControllingDriver 
== NULL 
) { 
1013         return IOPMAckImplied
; 
1016     newStateNumber 
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(pm_vars
->parentsCurrentPowerFlags
); 
1017     return enqueuePowerChange(IOPMParentInitiated 
| IOPMDomainDidChange
, 
1018                     newStateNumber
,pm_vars
->parentsCurrentPowerFlags
,whichParent
,0);    // tell interested parties about it 
1022 //********************************************************************************* 
1025 // Set our connection data for one specific parent, and then combine all the parent 
1027 //********************************************************************************* 
1029 void IOService::setParentInfo ( IOPMPowerFlags newPowerStateFlags
, IOPowerConnection 
* whichParent 
) 
1033     IOPowerConnection 
* connection
; 
1035     whichParent
->setParentCurrentPowerFlags(newPowerStateFlags
);                // set our connection data 
1036     whichParent
->setParentKnowsState(true); 
1038     IOLockLock(pm_vars
->parentLock
); 
1040     pm_vars
->parentsCurrentPowerFlags 
= 0;                                      // recompute our parent info 
1041     pm_vars
->parentsKnowState 
= true; 
1043     iter 
= getParentIterator(gIOPowerPlane
); 
1046         while ( (next 
= iter
->getNextObject()) ) { 
1047             if ( (connection 
= OSDynamicCast(IOPowerConnection
,next
)) ) { 
1048                 pm_vars
->parentsKnowState 
&= connection
->parentKnowsState(); 
1049                 pm_vars
->parentsCurrentPowerFlags 
|= connection
->parentCurrentPowerFlags(); 
1054     IOLockUnlock(pm_vars
->parentLock
); 
1058 //********************************************************************************* 
1059 // requestPowerDomainState 
1061 // The kIOPMPreventIdleSleep and/or kIOPMPreventIdleSleep bits may be be set in the parameter. 
1062 // It is not considered part of the state specification. 
1063 //********************************************************************************* 
1064 IOReturn 
IOService::requestPowerDomainState ( IOPMPowerFlags desiredState
, IOPowerConnection 
* whichChild
, unsigned long specification 
) 
1067     unsigned long       computedState
; 
1068     unsigned long       theDesiredState 
= desiredState 
& ~(kIOPMPreventIdleSleep 
| kIOPMPreventSystemSleep
); 
1071     IOPowerConnection 
* connection
; 
1073     pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRequestDomain
, 
1074                                 (unsigned long)desiredState
,(unsigned long)specification
); 
1076     if ( pm_vars
->theControllingDriver 
== NULL
) { 
1077         return IOPMNotYetInitialized
; 
1080     switch (specification
) { 
1081         case IOPMLowestState
: 
1083             while ( i 
< pm_vars
->theNumberOfPowerStates 
) { 
1084                 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter 
& theDesiredState
) == (theDesiredState 
& pm_vars
->myCharacterFlags
) ) { 
1089                 if ( i 
>= pm_vars
->theNumberOfPowerStates 
) { 
1090                 return IOPMNoSuchState
; 
1094         case IOPMNextLowerState
: 
1095             i 
= pm_vars
->myCurrentState 
- 1; 
1097                 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter 
& theDesiredState
) == (theDesiredState 
& pm_vars
->myCharacterFlags
) ) { 
1103                 return IOPMNoSuchState
; 
1107         case IOPMHighestState
: 
1108             i 
= pm_vars
->theNumberOfPowerStates
; 
1111                 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter 
& theDesiredState
) == (theDesiredState 
& pm_vars
->myCharacterFlags
) ) { 
1116                 return IOPMNoSuchState
; 
1120         case IOPMNextHigherState
: 
1121             i 
= pm_vars
->myCurrentState 
+ 1; 
1122             while ( i 
< pm_vars
->theNumberOfPowerStates 
) { 
1123                 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter 
& theDesiredState
) == (theDesiredState 
& pm_vars
->myCharacterFlags
) ) { 
1128                 if ( i 
== pm_vars
->theNumberOfPowerStates 
) { 
1129                 return IOPMNoSuchState
; 
1134             return IOPMBadSpecification
; 
1139     IOLockLock(pm_vars
->childLock
); 
1141 // A child's desires has changed.  We need to rebuild the child-clamp bits in our 
1142 // power state array.  Start by clearing the bits in each power state. 
1144     for ( i 
= 0; i 
< pm_vars
->theNumberOfPowerStates
; i
++ ) { 
1145         pm_vars
->thePowerStates
[i
].capabilityFlags 
&= ~(kIOPMChildClamp 
| kIOPMChildClamp2
); 
1148 // Now loop through the children.  When we encounter the calling child, save 
1149 // the computed state as this child's desire.  And while we're at it, set the ChildClamp bits 
1150 // in any of our states that some child has requested with clamp on. 
1152     iter 
= getChildIterator(gIOPowerPlane
); 
1155         while ( (next 
= iter
->getNextObject()) ) { 
1156             if ( (connection 
= OSDynamicCast(IOPowerConnection
,next
)) ) { 
1157                 if ( connection 
== whichChild 
) { 
1158                     connection
->setDesiredDomainState(computedState
); 
1159                     connection
->setPreventIdleSleepFlag(desiredState 
& kIOPMPreventIdleSleep
); 
1160                     connection
->setPreventSystemSleepFlag(desiredState 
& kIOPMPreventSystemSleep
); 
1161                     connection
->setChildHasRequestedPower(); 
1163                 if ( connection
->getPreventIdleSleepFlag() ) { 
1164                     pm_vars
->thePowerStates
[connection
->getDesiredDomainState()].capabilityFlags 
|= kIOPMChildClamp
; 
1166                 if ( connection
->getPreventSystemSleepFlag() ) { 
1167                     pm_vars
->thePowerStates
[connection
->getDesiredDomainState()].capabilityFlags 
|= kIOPMChildClamp2
; 
1174     IOLockUnlock(pm_vars
->childLock
); 
1176     computeDesiredState();                              // this may be different now 
1178    if ( inPlane(gIOPowerPlane
) && 
1179         (pm_vars
->parentsKnowState
) ) { 
1180        changeState();                                   // change state if all children can now tolerate lower power 
1183    if ( priv
->clampOn 
) {                               // are we clamped on, waiting for this child? 
1184        priv
->clampOn 
= false;                           // yes, remove the clamp 
1185        changePowerStateToPriv(0); 
1192 //********************************************************************************* 
1193 // temporaryPowerClampOn 
1195 // A power domain wants to clamp its power on till it has children which 
1196 // will thendetermine the power domain state. 
1198 // We enter the highest state until addPowerChild is called. 
1199 //********************************************************************************* 
1201 IOReturn 
IOService::temporaryPowerClampOn ( void ) 
1203     priv
->clampOn 
= true; 
1209 //********************************************************************************* 
1212 // Some client of our device is asking that we become usable.  Although 
1213 // this has not come from a subclassed device object, treat it exactly 
1214 // as if it had.  In this way, subsequent requests for lower power from 
1215 // a subclassed device object will pre-empt this request. 
1217 // We treat this as a subclass object request to switch to the 
1218 // highest power state. 
1219 //********************************************************************************* 
1221 IOReturn 
IOService::makeUsable ( void ) 
1223     pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogMakeUsable
,0,0); 
1225     if ( pm_vars
->theControllingDriver 
== NULL 
) { 
1226         priv
->need_to_become_usable 
= true; 
1229     priv
->deviceDesire 
= pm_vars
->theNumberOfPowerStates 
- 1; 
1230     computeDesiredState(); 
1231     if ( inPlane(gIOPowerPlane
) && (pm_vars
->parentsKnowState
) ) { 
1232         return changeState(); 
1238 //********************************************************************************* 
1239 // currentCapability 
1241 //********************************************************************************* 
1243 IOPMPowerFlags 
IOService::currentCapability ( void ) 
1245     if ( pm_vars
->theControllingDriver 
== NULL 
) { 
1249         return   pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
; 
1254 //********************************************************************************* 
1255 // changePowerStateTo 
1257 // For some reason, our power-controlling driver has decided it needs to change 
1258 // power state.  We enqueue the power change so that appropriate parties 
1259 // will be notified, and then we will instruct the driver to make the change. 
1260 //********************************************************************************* 
1262 IOReturn 
IOService::changePowerStateTo ( unsigned long ordinal 
) 
1264     pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeStateTo
,ordinal
,0); 
1266     if ( ordinal 
>= pm_vars
->theNumberOfPowerStates 
) { 
1267         return IOPMParameterError
; 
1269     priv
->driverDesire 
= ordinal
; 
1270     computeDesiredState(); 
1271     if ( inPlane(gIOPowerPlane
) && (pm_vars
->parentsKnowState
) ) { 
1272         return changeState(); 
1278 //********************************************************************************* 
1279 // changePowerStateToPriv 
1281 // For some reason, a subclassed device object has decided it needs to change 
1282 // power state.  We enqueue the power change so that appropriate parties 
1283 // will be notified, and then we will instruct the driver to make the change. 
1284 //********************************************************************************* 
1286 IOReturn 
IOService::changePowerStateToPriv ( unsigned long ordinal 
) 
1288     pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeStateToPriv
,ordinal
,0); 
1290     if ( pm_vars
->theControllingDriver 
== NULL
) { 
1291         return IOPMNotYetInitialized
; 
1293     if ( ordinal 
>= pm_vars
->theNumberOfPowerStates 
) { 
1294         return IOPMParameterError
; 
1296     priv
->deviceDesire 
= ordinal
; 
1297     computeDesiredState(); 
1298     if ( inPlane(gIOPowerPlane
) && (pm_vars
->parentsKnowState
) ) { 
1299         return changeState(); 
1306 //********************************************************************************* 
1307 // computeDesiredState 
1309 //********************************************************************************* 
1311 void IOService::computeDesiredState ( void ) 
1315     IOPowerConnection 
* connection
; 
1316     unsigned long       newDesiredState 
= 0; 
1318     // Compute the maximum  of our children's desires, our controlling driver's desire, and the subclass device's desire. 
1320     if ( !  priv
->device_overrides 
) { 
1321         iter 
= getChildIterator(gIOPowerPlane
); 
1324             while ( (next 
= iter
->getNextObject()) ) { 
1325                 if ( (connection 
= OSDynamicCast(IOPowerConnection
,next
)) ) { 
1326                     if ( connection
->getDesiredDomainState() > newDesiredState 
) { 
1327                         newDesiredState 
= connection
->getDesiredDomainState(); 
1334         if (  priv
->driverDesire 
> newDesiredState 
) { 
1335             newDesiredState 
=  priv
->driverDesire
; 
1339     if ( priv
->deviceDesire 
> newDesiredState 
) { 
1340         newDesiredState 
= priv
->deviceDesire
; 
1343     priv
->ourDesiredPowerState 
= newDesiredState
; 
1347 //********************************************************************************* 
1350 // A subclass object, our controlling driver, or a power domain child 
1351 // has asked for a different power state.  Here we compute what new 
1352 // state we should enter and enqueue the change (or start it). 
1353 //********************************************************************************* 
1355 IOReturn 
IOService::changeState ( void ) 
1357     if ( (pm_vars
->theControllingDriver 
== NULL
) ||     // if not fully initialized 
1358          ! (inPlane(gIOPowerPlane
)) || 
1359        ! (pm_vars
->parentsKnowState
) ) { 
1360         return IOPMNoErr
;                               // we can do no more 
1363     return enqueuePowerChange(IOPMWeInitiated
,priv
->ourDesiredPowerState
,0,0,0); 
1367 //********************************************************************************* 
1368 // currentPowerConsumption 
1370 //********************************************************************************* 
1372 unsigned long IOService::currentPowerConsumption ( void ) 
1374     if ( pm_vars
->theControllingDriver 
== NULL 
) { 
1375         return kIOPMUnknown
; 
1377     if ( pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags 
& kIOPMStaticPowerValid 
) { 
1378         return  pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].staticPower
; 
1380     return kIOPMUnknown
; 
1383 //********************************************************************************* 
1386 // The activity tickle with parameter kIOPMSubclassPolicyis not handled 
1387 // here and should have been intercepted by the subclass. 
1388 // The tickle with parameter kIOPMSuperclassPolicy1 causes the activity 
1389 // flag to be set, and the device state checked.  If the device has been 
1390 // powered down, it is powered up again. 
1391 //********************************************************************************* 
1393 bool IOService::activityTickle ( unsigned long type
, unsigned long stateNumber
=0 ) 
1395     AbsoluteTime uptime
; 
1397     if ( type 
== kIOPMSuperclassPolicy1 
) { 
1398         if ( (priv
->activityLock 
== NULL
) || 
1399              (pm_vars
->theControllingDriver 
== NULL
) || 
1400              (pm_vars
->commandQueue 
== NULL
) ) { 
1403         IOTakeLock(priv
->activityLock
); 
1404         priv
->device_active 
= true; 
1406         clock_get_uptime(&uptime
); 
1407         priv
->device_active_timestamp 
= uptime
; 
1409         if ( pm_vars
->myCurrentState 
>= stateNumber
) { 
1410             IOUnlock(priv
->activityLock
); 
1413         IOUnlock(priv
->activityLock
);                           // send a message on the command queue 
1414         pm_vars
->commandQueue
->enqueueCommand(true, (void *)kIOPMUnidleDevice
, (void *)stateNumber
); 
1420 //********************************************************************************* 
1423 // A child is calling to get a pointer to the Power Management workloop. 
1424 // We got it or get it from one of our parents. 
1425 //********************************************************************************* 
1427 IOWorkLoop 
* IOService::getPMworkloop ( void ) 
1432     if ( ! inPlane(gIOPowerPlane
) ) { 
1435     if ( pm_vars
->PMworkloop 
== NULL 
) {                                // we have no workloop yet 
1436         nub 
= (IOService 
*)copyParentEntry(gIOPowerPlane
); 
1438             parent 
= (IOService 
*)nub
->copyParentEntry(gIOPowerPlane
); 
1440             if ( parent 
) {                                             // ask one of our parents for the workloop 
1441                 pm_vars
->PMworkloop 
= parent
->getPMworkloop(); 
1446     return  pm_vars
->PMworkloop
; 
1450 //********************************************************************************* 
1451 // setIdleTimerPeriod 
1453 // A subclass policy-maker is going to use our standard idleness 
1454 // detection service.  Make a command queue and an idle timer and 
1455 // connect them to the power management workloop.  Finally, 
1457 //********************************************************************************* 
1459 IOReturn  
IOService::setIdleTimerPeriod ( unsigned long period 
) 
1461     pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMsetIdleTimerPeriod
,period
, 0); 
1463     priv
->idle_timer_period 
= period
; 
1466         if ( getPMworkloop() == NULL 
) { 
1467             return kIOReturnError
; 
1470         if (pm_vars
->commandQueue 
== NULL 
) {           // make the command queue 
1471             pm_vars
->commandQueue 
= IOCommandQueue::commandQueue(this, PMreceiveCmd
); 
1472             if (!  pm_vars
->commandQueue 
|| 
1473                 (  pm_vars
->PMworkloop
->addEventSource( pm_vars
->commandQueue
) != kIOReturnSuccess
) ) { 
1474                 return kIOReturnError
; 
1477                                                  // make the timer event 
1478         if (  priv
->timerEventSrc 
== NULL 
) { 
1479             priv
->timerEventSrc 
= IOTimerEventSource::timerEventSource(this, 
1480                                                     PM_idle_timer_expired
); 
1481             if ( !  priv
->timerEventSrc 
|| 
1482                  ( pm_vars
->PMworkloop
->addEventSource(  priv
->timerEventSrc
) != kIOReturnSuccess
) ) { 
1483                 return kIOReturnError
; 
1487         if ( priv
->activityLock 
== NULL 
) { 
1488             priv
->activityLock 
= IOLockAlloc(); 
1491         start_PM_idle_timer(); 
1497 //********************************************************************************* 
1498 // start_PM_idle_timer 
1500 // The parameter is a pointer to us.  Use it to call our timeout method. 
1501 //********************************************************************************* 
1502 void IOService::start_PM_idle_timer ( void ) 
1504     AbsoluteTime uptime
; 
1510     IOLockLock(priv
->activityLock
); 
1512     clock_get_uptime(&uptime
); 
1514    /* Calculate time difference using funky macro from clock.h. 
1517     SUB_ABSOLUTETIME(&delta
, &(priv
->device_active_timestamp
)); 
1519    /* Figure it in seconds. 
1521     absolutetime_to_nanoseconds(delta
, &delta_ns
); 
1522     delta_secs 
= delta_ns 
/ NSEC_PER_SEC
; 
1524    /* Be paranoid about delta somehow exceeding timer period. 
1526     if (delta_secs 
< priv
->idle_timer_period 
) { 
1527         delay_secs 
= priv
->idle_timer_period 
- delta_secs
; 
1529         delay_secs 
= priv
->idle_timer_period
; 
1532     priv
->timerEventSrc
->setTimeout(delay_secs
, NSEC_PER_SEC
); 
1534     IOLockUnlock(priv
->activityLock
); 
1539 //********************************************************************************* 
1540 // PM_idle_timer_expired 
1542 // The parameter is a pointer to us.  Use it to call our timeout method. 
1543 //********************************************************************************* 
1545 void PM_idle_timer_expired(OSObject 
* ourSelves
, IOTimerEventSource 
*) 
1547     ((IOService 
*)ourSelves
)->PM_idle_timer_expiration(); 
1551 //********************************************************************************* 
1552 // PM_idle_timer_expiration 
1554 // The idle timer has expired.  If there has been activity since the last 
1555 // expiration, just restart the timer and return.  If there has not been 
1556 // activity, switch to the next lower power state and restart the timer. 
1557 //********************************************************************************* 
1559 void IOService::PM_idle_timer_expiration ( void ) 
1561     if ( ! initialized 
) { 
1562         return;                                 // we're unloading 
1565     if (  priv
->idle_timer_period 
> 0 ) { 
1566         IOTakeLock(priv
->activityLock
); 
1567         if ( priv
->device_active 
) { 
1568             priv
->device_active 
= false; 
1569             IOUnlock(priv
->activityLock
); 
1570             start_PM_idle_timer(); 
1573         if ( pm_vars
->myCurrentState 
> 0 ) { 
1574             IOUnlock(priv
->activityLock
); 
1575             changePowerStateToPriv(pm_vars
->myCurrentState 
- 1); 
1576             start_PM_idle_timer(); 
1579         IOUnlock(priv
->activityLock
); 
1580         start_PM_idle_timer(); 
1586 // ********************************************************************************** 
1591 // ********************************************************************************** 
1592 void PMreceiveCmd ( OSObject 
* theDriver
,  void * command
, void * param1
, void * param2
, void *param3 
) 
1594    ((IOService 
*)theDriver
)->command_received(command
,param1
,param2
,param3
); 
1598 // ********************************************************************************** 
1601 // We have received a command from ourselves on the command queue. 
1602 // This is to prevent races with timer-expiration code. 
1603 // ********************************************************************************** 
1604 void IOService::command_received ( void * command
, void *stateNumber 
, void * , void *) 
1606     if ( ! initialized 
) { 
1607         return;                                 // we're unloading 
1610     if ( command 
== (void *)kIOPMUnidleDevice 
) { 
1611         if ( (pm_vars
->myCurrentState 
< (unsigned long)stateNumber
) && 
1612             (priv
->imminentState 
< (unsigned long)stateNumber
) ) { 
1613             changePowerStateToPriv((unsigned long)stateNumber
); 
1619 //********************************************************************************* 
1620 // setAggressiveness 
1622 // Pass on the input parameters to all power domain children. All those which are 
1623 // power domains will pass it on to their children, etc. 
1624 //********************************************************************************* 
1626 IOReturn 
IOService::setAggressiveness ( unsigned long type
, unsigned long newLevel 
) 
1630     IOPowerConnection 
* connection
; 
1633     pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogSetAggressiveness
,type
, newLevel
); 
1635     if ( type 
<= kMaxType 
) { 
1636         pm_vars
->current_aggressiveness_values
[type
] = newLevel
; 
1637         pm_vars
->current_aggressiveness_valid
[type
] = true; 
1640     iter 
= getChildIterator(gIOPowerPlane
); 
1643         while ( (next 
= iter
->getNextObject()) ) { 
1644             if ( (connection 
= OSDynamicCast(IOPowerConnection
,next
)) ) { 
1645                 child 
= ((IOService 
*)(connection
->copyChildEntry(gIOPowerPlane
))); 
1647                     child
->setAggressiveness(type
, newLevel
); 
1658 //********************************************************************************* 
1659 // getAggressiveness 
1661 // Called by the user client. 
1662 //********************************************************************************* 
1664 IOReturn 
IOService::getAggressiveness ( unsigned long type
, unsigned long * currentLevel 
) 
1666   if ( type 
<= kMaxType 
) { 
1667         *currentLevel 
= pm_vars
->current_aggressiveness_values
[type
]; 
1669     return kIOReturnSuccess
; 
1672 //********************************************************************************* 
1675 // Pass this to all power domain children. All those which are 
1676 // power domains will pass it on to their children, etc. 
1677 //********************************************************************************* 
1679 IOReturn 
IOService::systemWake ( void ) 
1683     IOPowerConnection 
* connection
; 
1684     IOService 
*         theChild
; 
1686     pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogSystemWake
,0, 0); 
1688     iter 
= getChildIterator(gIOPowerPlane
); 
1691         while ( (next 
= iter
->getNextObject()) ) { 
1692             if ( (connection 
= OSDynamicCast(IOPowerConnection
,next
)) ) { 
1693                 theChild 
= (IOService 
*)connection
->copyChildEntry(gIOPowerPlane
); 
1695                         theChild
->systemWake(); 
1696                         theChild
->release(); 
1703     if ( pm_vars
->theControllingDriver 
!= NULL 
) { 
1704         if ( pm_vars
->theControllingDriver
->didYouWakeSystem() ) { 
1713 //********************************************************************************* 
1714 // temperatureCriticalForZone 
1716 //********************************************************************************* 
1718 IOReturn 
IOService::temperatureCriticalForZone ( IOService 
* whichZone 
) 
1720     IOService 
* theParent
; 
1723     pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogCriticalTemp
,0,0); 
1725     if ( inPlane(gIOPowerPlane
) && ! (priv
->we_are_root
) ) { 
1726         theNub 
= (IOService 
*)copyParentEntry(gIOPowerPlane
); 
1728             theParent 
= (IOService 
*)theNub
->copyParentEntry(gIOPowerPlane
); 
1731                 theParent
->temperatureCriticalForZone(whichZone
); 
1732                 theParent
->release(); 
1740 //********************************************************************************* 
1741 // powerOverrideOnPriv 
1743 //********************************************************************************* 
1746 IOReturn 
IOService::powerOverrideOnPriv ( void ) 
1748     pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogOverrideOn
,0,0); 
1750     priv
->device_overrides 
= true;      // turn on the override 
1751     computeDesiredState(); 
1752     return changeState();               // change state if that changed something 
1756 //********************************************************************************* 
1757 // powerOverrideOffPriv 
1759 //********************************************************************************* 
1760 IOReturn 
IOService::powerOverrideOffPriv ( void ) 
1762     pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogOverrideOff
,0,0); 
1764     priv
->device_overrides 
= false;     // turn off the override 
1765     computeDesiredState(); 
1767         return makeUsable(); 
1769         return changeState();           // change state if that changed something 
1773 //********************************************************************************* 
1774 // enqueuePowerChange 
1776 // Allocate a new state change notification, initialize it with fields from the 
1777 // caller, and add it to the tail of the list of pending power changes. 
1779 // If it is early enough in the list, and almost all the time it is the only one in 
1780 // the list, start the power change. 
1782 // In rare instances, this change will preempt the previous change in the list. 
1783 // If the previous change is un-actioned in any way (because we are still 
1784 // processing an even earlier power change), and if both the previous change 
1785 // in the list and this change are initiated by us (not the parent), then we 
1786 // needn't perform the previous change, so we collapse the list a little. 
1787 //********************************************************************************* 
1789 IOReturn 
IOService::enqueuePowerChange ( unsigned long flags
,  unsigned long whatStateOrdinal
, unsigned long domainState
, IOPowerConnection 
* whichParent
, unsigned long singleParentState 
) 
1794 // Create and initialize the new change note 
1796     IOLockLock(priv
->queue_lock
); 
1797     newNote 
= priv
->changeList
->createChangeNote(); 
1798     if ( newNote 
== -1 ) { 
1799         IOLockUnlock(priv
->queue_lock
); 
1800         pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogEnqueueErr
,0,0); 
1801         return IOPMAckImplied
;                  // uh-oh, our list is full 
1804     priv
->changeList
->changeNote
[newNote
].newStateNumber 
= whatStateOrdinal
; 
1805     priv
->changeList
->changeNote
[newNote
].outputPowerCharacter 
=  pm_vars
->thePowerStates
[whatStateOrdinal
].outputPowerCharacter
; 
1806     priv
->changeList
->changeNote
[newNote
].inputPowerRequirement 
=  pm_vars
->thePowerStates
[whatStateOrdinal
].inputPowerRequirement
; 
1807     priv
->changeList
->changeNote
[newNote
].capabilityFlags 
=  pm_vars
->thePowerStates
[whatStateOrdinal
].capabilityFlags
; 
1808     priv
->changeList
->changeNote
[newNote
].flags 
= flags
; 
1809     if (flags 
& IOPMParentInitiated 
) { 
1810         priv
->changeList
->changeNote
[newNote
].domainState 
=  domainState
; 
1811         priv
->changeList
->changeNote
[newNote
].parent 
=  whichParent
; 
1812         whichParent
->retain(); 
1813         priv
->changeList
->changeNote
[newNote
].singleParentState 
=  singleParentState
; 
1816     previousNote 
= priv
->changeList
->previousChangeNote(newNote
); 
1818     if ( previousNote 
== -1 ) { 
1820         // Queue is empty, we can start this change. 
1822         if (flags 
& IOPMWeInitiated 
) { 
1823             IOLockUnlock(priv
->queue_lock
); 
1824             start_our_change(newNote
); 
1828             IOLockUnlock(priv
->queue_lock
); 
1829             return start_parent_change(newNote
); 
1833     // The queue is not empty.  Try to collapse this new change and the previous one in queue into one change. 
1834     // This is possible only if both changes are initiated by us, and neither has been started yet. 
1835     // Do this more than once if possible. 
1837     // (A change is started iff it is at the head of the queue) 
1839     while ( (previousNote 
!= priv
->head_note
) &&  (previousNote 
!= -1) && 
1840             (priv
->changeList
->changeNote
[newNote
].flags 
&  priv
->changeList
->changeNote
[previousNote
].flags 
&  IOPMWeInitiated
)  ) { 
1841         priv
->changeList
->changeNote
[previousNote
].outputPowerCharacter 
= priv
->changeList
->changeNote
[newNote
].outputPowerCharacter
; 
1842         priv
->changeList
->changeNote
[previousNote
].inputPowerRequirement 
= priv
->changeList
->changeNote
[newNote
].inputPowerRequirement
; 
1843         priv
->changeList
->changeNote
[previousNote
].capabilityFlags 
=priv
-> changeList
->changeNote
[newNote
].capabilityFlags
; 
1844         pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogCollapseQueue
,priv
->changeList
->changeNote
[newNote
].newStateNumber
, 
1845                                                                     priv
->changeList
->changeNote
[previousNote
].newStateNumber
); 
1846         priv
->changeList
->changeNote
[previousNote
].newStateNumber 
= priv
->changeList
->changeNote
[newNote
].newStateNumber
; 
1847         priv
->changeList
->releaseTailChangeNote(); 
1848         newNote 
= previousNote
; 
1849         previousNote 
= priv
->changeList
->previousChangeNote(newNote
); 
1851     IOLockUnlock(priv
->queue_lock
); 
1852     return IOPMWillAckLater
;                            // in any case, we can't start yet 
1855 //********************************************************************************* 
1858 // Notify all interested parties either that a change is impending or that the 
1859 // previously-notified change is done and power has settled. 
1860 // The parameter identifies whether this is the 
1861 // pre-change notification or the post-change notification. 
1863 //********************************************************************************* 
1865 IOReturn 
IOService::notifyAll ( bool is_prechange 
) 
1867     IOPMinformee 
*              nextObject
; 
1870     IOPowerConnection 
* connection
; 
1872     // To prevent acknowledgePowerChange from finishing the change note and removing it from the queue if 
1873     // some driver calls it, we inflate the number of pending acks so it cannot become zero.  We'll fix it later. 
1875     priv
->head_note_pendingAcks 
=1; 
1877     // OK, we will go through the lists of interested drivers and power domain children 
1878     // and notify each one of this change. 
1879     nextObject 
=  priv
->interestedDrivers
->firstInList();               // notify interested drivers 
1880     while (  nextObject 
!= NULL 
) { 
1881         priv
->head_note_pendingAcks 
+=1; 
1882         if (! inform(nextObject
, is_prechange
) ) { 
1884         nextObject  
=  priv
->interestedDrivers
->nextInList(nextObject
); 
1887     if (! acquire_lock() ) { 
1890     if ( priv
->head_note_pendingAcks 
> 1 ) {                                    // did they all ack? 
1891         pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);   // no 
1894     IOUnlock(priv
->our_lock
);                                                   // either way 
1896     iter 
= getChildIterator(gIOPowerPlane
);                             // notify children 
1897     pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower 
= 0;     // summing their power consumption 
1900         while ( (next 
= iter
->getNextObject()) ) { 
1901             if ( (connection 
= OSDynamicCast(IOPowerConnection
,next
)) ) { 
1902                 priv
->head_note_pendingAcks 
+=1; 
1903                 notifyChild(connection
, is_prechange
); 
1909     if (! acquire_lock() ) { 
1912     priv
->head_note_pendingAcks 
-= 1;                   // now make this real 
1913     if (priv
->head_note_pendingAcks 
== 0 ) {            // is it all acked? 
1914         IOUnlock(priv
->our_lock
);                       // yes 
1915         return IOPMAckImplied
;                          // return ack to parent 
1917     IOUnlock(priv
->our_lock
);                           // no 
1918     return IOPMWillAckLater
; 
1922 //********************************************************************************* 
1925 // Notify a power domain child of an upcoming power change. 
1927 // If the object acknowledges the current change, we return TRUE. 
1928 //********************************************************************************* 
1930 bool IOService::notifyChild ( IOPowerConnection 
* theNub
, bool is_prechange 
) 
1932     IOReturn            k 
= IOPMAckImplied
; 
1933     unsigned long       childPower
; 
1934     IOService 
*         theChild 
= (IOService 
*)(theNub
->copyChildEntry(gIOPowerPlane
)); 
1936    theNub
->setAwaitingAck(true);                                        // in case they don't ack 
1942    if ( is_prechange 
) { 
1943         k 
= theChild
->powerDomainWillChangeTo(priv
->head_note_outputFlags
,theNub
); 
1946         k 
= theChild
->powerDomainDidChangeTo(priv
->head_note_outputFlags
,theNub
); 
1949    if ( k 
== IOPMAckImplied 
) {                                         // did the return code ack? 
1950         priv
->head_note_pendingAcks 
-=1;                                // yes 
1951         theNub
->setAwaitingAck(false); 
1952         childPower 
= theChild
->currentPowerConsumption(); 
1953         if ( childPower 
== kIOPMUnknown 
) { 
1954             pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower 
= kIOPMUnknown
; 
1957             if ( pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower 
!= kIOPMUnknown 
) { 
1958                 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower 
+= childPower
; 
1961         theChild
->release(); 
1964    theChild
->release(); 
1969 //********************************************************************************* 
1972 // Notify an interested driver of an upcoming power change. 
1974 // If the object acknowledges the current change, we return TRUE. 
1975 //********************************************************************************* 
1977 bool IOService::inform ( IOPMinformee 
* nextObject
, bool is_prechange 
) 
1979     IOReturn k 
= IOPMAckImplied
; 
1981    nextObject
->timer 
= -1;                                      // initialize this 
1983    if ( is_prechange 
) { 
1984        pm_vars
->thePlatform
->PMLog (pm_vars
->ourName
,PMlogInformDriverPreChange
, 
1985                                     (unsigned long)priv
->head_note_capabilityFlags
,(unsigned long)priv
->head_note_state
); 
1986        k 
= nextObject
->whatObject
->powerStateWillChangeTo( priv
->head_note_capabilityFlags
,priv
->head_note_state
,this); 
1989        pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInformDriverPostChange
, 
1990                                    (unsigned long)priv
->head_note_capabilityFlags
,(unsigned long)priv
->head_note_state
); 
1991        k 
= nextObject
->whatObject
->powerStateDidChangeTo(priv
->head_note_capabilityFlags
,priv
->head_note_state
,this); 
1993    if ( nextObject
->timer 
== 0 ) {                              // did it ack behind our back? 
1996    if ( k 
==IOPMAckImplied 
) {                                  // no, did the return code ack? 
1997        nextObject
->timer 
= 0;                                   // yes 
1998        priv
->head_note_pendingAcks 
-= 1; 
2002        nextObject
->timer 
= 0;                                   // somebody goofed 
2003        priv
-> head_note_pendingAcks 
-= 1; 
2006    nextObject
->timer 
= (k 
* ns_per_us 
/ ACK_TIMER_PERIOD
) + 1;  // no, it's a timer 
2011 //********************************************************************************* 
2014 // All registered applications and kernel clients have positively acknowledged our 
2015 // intention of lowering power.  Here we notify them all that we will definitely 
2016 // lower the power.  If we don't have to wait for any of them to acknowledge, we 
2017 // carry on by notifying interested drivers.  Otherwise, we do wait. 
2018 //********************************************************************************* 
2020 void IOService::our_prechange_03 ( void ) 
2022     priv
->machine_state 
= IOPMour_prechange_04
;         // next state 
2023     if ( tellChangeDown1(priv
->head_note_state
) ) {     // are we waiting for responses? 
2024         our_prechange_04();                             // no, notify priority clients 
2029 //********************************************************************************* 
2032 // All registered applications and kernel clients have positively acknowledged our 
2033 // intention of lowering power.  Here we notify "priority" clients that we are 
2034 // lowering power.  If we don't have to wait for any of them to acknowledge, we 
2035 // carry on by notifying interested drivers.  Otherwise, we do wait. 
2036 //********************************************************************************* 
2038 void IOService::our_prechange_04 ( void ) 
2040     priv
->machine_state 
= IOPMour_prechange_05
;         // next state 
2041     if ( tellChangeDown2(priv
->head_note_state
) ) {     // are we waiting for responses? 
2042         return our_prechange_05();                      // no, notify interested drivers 
2047 //********************************************************************************* 
2050 // All registered applications and kernel clients have acknowledged our notification 
2051 // that we are lowering power.  Here we notify interested drivers.  If we don't have 
2052 // to wait for any of them to acknowledge, we instruct our power driver to make the change. 
2053 // Otherwise, we do wait. 
2054 //********************************************************************************* 
2056 void IOService::our_prechange_05 ( void ) 
2058     priv
->machine_state 
= IOPMour_prechange_1
;          // no, in case they don't all ack 
2059     if ( notifyAll(true) == IOPMAckImplied 
) { 
2065 //********************************************************************************* 
2068 // All interested drivers have acknowledged our pre-change notification of a power 
2069 // change we initiated.  Here we instruct our controlling driver to make 
2070 // the change to the hardware.  If it does so, we continue processing 
2071 // (waiting for settle and notifying interested parties post-change.) 
2072 // If it doesn't, we have to wait for it to acknowledge and then continue. 
2073 //********************************************************************************* 
2075 void IOService::our_prechange_1 ( void ) 
2077     if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied 
) { 
2078         our_prechange_2();                                      // it's done, carry on 
2081         priv
->machine_state 
= IOPMour_prechange_2
;              // it's not, wait for it 
2082         pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0); 
2088 //********************************************************************************* 
2091 // Our controlling driver has changed power state on the hardware 
2092 // during a power change we initiated.  Here we see if we need to wait 
2093 // for power to settle before continuing.  If not, we continue processing 
2094 // (notifying interested parties post-change).  If so, we wait and 
2096 //********************************************************************************* 
2098 void IOService::our_prechange_2 ( void ) 
2100     priv
->settle_time 
= compute_settle_time(); 
2101     if ( priv
->settle_time 
== 0 ) { 
2105         priv
->machine_state 
= IOPMour_prechange_3
; 
2106         startSettleTimer(priv
->settle_time
); 
2111 //********************************************************************************* 
2114 // Power has settled on a power change we initiated.  Here we notify 
2115 // all our interested parties post-change.  If they all acknowledge, we're 
2116 // done with this change note, and we can start on the next one. 
2117 // Otherwise we have to wait for acknowledgements and finish up later. 
2118 //********************************************************************************* 
2120 void IOService::our_prechange_3 ( void ) 
2122     priv
->machine_state 
= IOPMour_prechange_4
;          // in case they don't all ack 
2123     if ( notifyAll(false) == IOPMAckImplied 
) { 
2129 //********************************************************************************* 
2132 // Power has settled on a power change we initiated, and 
2133 // all our interested parties have acknowledged.  We're 
2134 // done with this change note, and we can start on the next one. 
2135 //********************************************************************************* 
2137 void IOService::our_prechange_4 ( void ) 
2143 //********************************************************************************* 
2146 // All applications and kernel clients have been notified of a power lowering 
2147 // initiated by the parent and we didn't have to wait for any responses.  Here 
2148 // we notify any priority clients.  If they all ack, we continue with the power change. 
2149 // If at least one doesn't, we have to wait for it to acknowledge and then continue. 
2150 //********************************************************************************* 
2152 IOReturn 
IOService::parent_down_0 ( void ) 
2154     priv
->machine_state 
= IOPMparent_down_05
;           // in case they don't all ack 
2155     if ( tellChangeDown2(priv
->head_note_state
) ) {     // are we waiting for responses? 
2156         return parent_down_02();                        // no, notify interested drivers 
2158     return IOPMWillAckLater
;                            // they didn't 
2162 //********************************************************************************* 
2165 // All priority kernel clients have been notified of a power lowering 
2166 // initiated by the parent and we didn't have to wait for any responses.  Here 
2167 // we notify any interested drivers and power domain children.  If they all ack, 
2168 // we continue with the power change. 
2169 // If at least one doesn't, we have to wait for it to acknowledge and then continue. 
2170 //********************************************************************************* 
2172 IOReturn 
IOService::parent_down_02 ( void ) 
2174     priv
->machine_state 
= IOPMparent_down_4
;            // in case they don't all ack 
2175     if ( notifyAll(true) == IOPMAckImplied 
) { 
2176         return parent_down_1();                         // they did 
2178     return IOPMWillAckLater
;                            // they didn't 
2182 //********************************************************************************* 
2185 // All applications and kernel clients have been notified of a power lowering 
2186 // initiated by the parent and we had to wait for responses.  Here 
2187 // we notify any priority clients.  If they all ack, we continue with the power change. 
2188 // If at least one doesn't, we have to wait for it to acknowledge and then continue. 
2189 //********************************************************************************* 
2191 void IOService::parent_down_04 ( void ) 
2193     priv
->machine_state 
= IOPMparent_down_05
;           // in case they don't all ack 
2194     if ( tellChangeDown2(priv
->head_note_state
) ) {     // are we waiting for responses? 
2195         parent_down_05();                               // no, notify interested drivers 
2200 //********************************************************************************* 
2203 // All applications and kernel clients have been notified of a power lowering 
2204 // initiated by the parent and we had to wait for their responses.  Here we notify 
2205 // any interested drivers and power domain children.  If they all ack, we continue 
2206 // with the power change. 
2207 // If at least one doesn't, we have to wait for it to acknowledge and then continue. 
2208 //********************************************************************************* 
2210 void IOService::parent_down_05 ( void ) 
2212     priv
->machine_state 
= IOPMparent_down_4
;            // in case they don't all ack 
2213     if ( notifyAll(true) == IOPMAckImplied 
) { 
2214         parent_down_4();                                // they did 
2219 //********************************************************************************* 
2222 // All parties have acknowledged our pre-change notification of a power 
2223 // lowering initiated by the parent.  Here we instruct our controlling driver 
2224 // to put the hardware in the state it needs to be in when the domain is 
2225 // lowered.  If it does so, we continue processing 
2226 // (waiting for settle and acknowledging the parent.) 
2227 // If it doesn't, we have to wait for it to acknowledge and then continue. 
2228 //********************************************************************************* 
2230 IOReturn 
IOService::parent_down_1 ( void ) 
2232     if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied 
) { 
2233         return parent_down_2();                 // it's done, carry on 
2235     priv
->machine_state 
= IOPMparent_down_5
;    // it's not, wait for it 
2236     pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0); 
2238     return IOPMWillAckLater
; 
2242 //********************************************************************************* 
2245 // We had to wait for it, but all parties have acknowledged our pre-change 
2246 // notification of a power lowering initiated by the parent. 
2247 // Here we instruct our controlling driver 
2248 // to put the hardware in the state it needs to be in when the domain is 
2249 // lowered.  If it does so, we continue processing 
2250 // (waiting for settle and acknowledging the parent.) 
2251 // If it doesn't, we have to wait for it to acknowledge and then continue. 
2252 //********************************************************************************* 
2254 void IOService::parent_down_4 ( void ) 
2256     if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied 
) { 
2257         parent_down_5();                                        // it's done, carry on 
2260         priv
-> machine_state 
= IOPMparent_down_5
;       // it's not, wait for it 
2261         pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0); 
2267 //********************************************************************************* 
2270 // Our controlling driver has changed power state on the hardware 
2271 // during a power change initiated by our parent.  Here we see if we need 
2272 // to wait for power to settle before continuing.  If not, we continue 
2273 // processing (acknowledging our preparedness to the parent). 
2274 // If so, we wait and continue later. 
2275 //********************************************************************************* 
2277 IOReturn 
IOService::parent_down_2 ( void ) 
2281     priv
->settle_time 
= compute_settle_time(); 
2282     if ( priv
->settle_time 
== 0 ) { 
2283         priv
->machine_state 
= IOPMparent_down_6
;        // in case they don't all ack 
2284         if ( notifyAll(false) == IOPMAckImplied 
) { 
2285             nub 
= priv
->head_note_parent
; 
2288             return IOPMAckImplied
; 
2290         return IOPMWillAckLater
;                        // they didn't 
2293        priv
->machine_state 
= IOPMparent_down_3
; 
2294        startSettleTimer(priv
->settle_time
); 
2295        return IOPMWillAckLater
; 
2300 //********************************************************************************* 
2303 // Our controlling driver has changed power state on the hardware 
2304 // during a power change initiated by our parent.  We have had to wait 
2305 // for acknowledgement from interested parties, or we have had to wait 
2306 // for the controlling driver to change the state.  Here we see if we need 
2307 // to wait for power to settle before continuing.  If not, we continue 
2308 // processing (acknowledging our preparedness to the parent). 
2309 // If so, we wait and continue later. 
2310 //********************************************************************************* 
2312 void IOService::parent_down_5 ( void ) 
2314     priv
->settle_time 
= compute_settle_time(); 
2315     if ( priv
->settle_time 
== 0 ) { 
2319        priv
->machine_state 
= IOPMparent_down_3
; 
2320        startSettleTimer(priv
->settle_time
); 
2325 //********************************************************************************* 
2328 // Power has settled on a power change initiated by our parent.  Here we 
2329 // notify interested parties. 
2330 //********************************************************************************* 
2332 void IOService::parent_down_3 ( void ) 
2334     IORegistryEntry 
*   nub
; 
2337     priv
->machine_state 
= IOPMparent_down_6
;    // in case they don't all ack 
2338     if ( notifyAll(false) == IOPMAckImplied 
) { 
2339         nub 
= priv
->head_note_parent
; 
2341         parent 
= (IOService 
*)nub
->copyParentEntry(gIOPowerPlane
); 
2343             parent
->acknowledgePowerChange((IOService 
*)nub
); 
2351 //********************************************************************************* 
2354 // We had to wait for it, but all parties have acknowledged our post-change 
2355 // notification of a power  lowering initiated by the parent. 
2356 // Here we acknowledge the parent. 
2357 // We are done with this change note, and we can start on the next one. 
2358 //********************************************************************************* 
2360 void IOService::parent_down_6 ( void ) 
2362     IORegistryEntry 
*   nub
; 
2365     nub 
= priv
->head_note_parent
; 
2367     parent 
= (IOService 
*)nub
->copyParentEntry(gIOPowerPlane
); 
2369         parent
->acknowledgePowerChange((IOService 
*)nub
); 
2376 //********************************************************************************* 
2379 // Our parent has informed us via powerStateDidChange that it has 
2380 // raised the power in our power domain, and we have had to wait 
2381 // for some interested party to acknowledge our notification. 
2382 //   Here we instruct our controlling 
2383 // driver to program the hardware to take advantage of the higher domain 
2384 // power.  If it does so, we continue processing 
2385 // (waiting for settle and notifying interested parties post-change.) 
2386 // If it doesn't, we have to wait for it to acknowledge and then continue. 
2387 //********************************************************************************* 
2389 void IOService::parent_up_0 ( void ) 
2391     if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied 
) { 
2392         parent_up_4();                                  // it did it, carry on 
2395         priv
->machine_state 
= IOPMparent_up_4
;  // it didn't, wait for it 
2396         pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0); 
2402 //********************************************************************************* 
2405 // Our parent has informed us via powerStateDidChange that it has 
2406 // raised the power in our power domain.  Here we instruct our controlling 
2407 // driver to program the hardware to take advantage of the higher domain 
2408 // power.  If it does so, we continue processing 
2409 // (waiting for settle and notifying interested parties post-change.) 
2410 // If it doesn't, we have to wait for it to acknowledge and then continue. 
2411 //********************************************************************************* 
2413 IOReturn 
IOService::parent_up_1 ( void ) 
2415     if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied 
) { 
2416         return parent_up_2();                           // it did it, carry on 
2419         priv
->machine_state 
= IOPMparent_up_4
;  // it didn't, wait for it 
2420         pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0); 
2422         return IOPMWillAckLater
; 
2427 //********************************************************************************* 
2430 // Our controlling driver has changed power state on the hardware 
2431 // during a power raise initiated by the parent.  Here we see if we need to wait 
2432 // for power to settle before continuing.  If not, we continue processing 
2433 // (notifying interested parties post-change).  If so, we wait and 
2435 //********************************************************************************* 
2437 IOReturn 
IOService::parent_up_2 ( void ) 
2439     priv
->settle_time 
= compute_settle_time(); 
2440     if ( priv
->settle_time 
== 0 ) { 
2441         return parent_up_3(); 
2444       priv
->machine_state 
= IOPMparent_up_5
; 
2445       startSettleTimer(priv
->settle_time
); 
2446       return IOPMWillAckLater
; 
2451 //********************************************************************************* 
2454 // Our controlling driver has changed power state on the hardware 
2455 // during a power raise initiated by the parent, but we had to wait for it. 
2456 // Here we see if we need to wait for power to settle before continuing. 
2457 // If not, we continue processing  (notifying interested parties post-change). 
2458 // If so, we wait and continue later. 
2459 //********************************************************************************* 
2461 void IOService::parent_up_4 ( void ) 
2463     priv
->settle_time 
= compute_settle_time(); 
2464     if ( priv
->settle_time 
== 0 ) { 
2468       priv
->machine_state 
= IOPMparent_up_5
; 
2469       startSettleTimer(priv
->settle_time
); 
2474 //********************************************************************************* 
2477 // No power settling was required on a power raise initiated by the parent. 
2478 // Here we notify all our interested parties post-change.  If they all acknowledge, 
2479 // we're done with this change note, and we can start on the next one. 
2480 // Otherwise we have to wait for acknowledgements and finish up later. 
2481 //********************************************************************************* 
2483 IOReturn 
IOService::parent_up_3 ( void ) 
2487     priv
->machine_state 
= IOPMparent_up_6
;      // in case they don't all ack 
2488     if ( notifyAll(false) == IOPMAckImplied 
) { 
2489         nub 
= priv
->head_note_parent
; 
2492         return IOPMAckImplied
; 
2494     return IOPMWillAckLater
;                    // they didn't 
2498 //********************************************************************************* 
2501 // Power has settled on a power raise initiated by the parent. 
2502 // Here we notify all our interested parties post-change.  If they all acknowledge, 
2503 // we're done with this change note, and we can start on the next one. 
2504 // Otherwise we have to wait for acknowledgements and finish up later. 
2505 //********************************************************************************* 
2507 void IOService::parent_up_5 ( void ) 
2509     priv
->machine_state 
= IOPMparent_up_6
;      // in case they don't all ack 
2510     if ( notifyAll(false) == IOPMAckImplied 
) { 
2516 //********************************************************************************* 
2519 // All parties have acknowledged our post-change notification of a power 
2520 // raising initiated by the parent.  Here we acknowledge the parent. 
2521 // We are done with this change note, and we can start on the next one. 
2522 //********************************************************************************* 
2524 void IOService::parent_up_6 ( void ) 
2526     IORegistryEntry 
*   nub
; 
2529     nub 
= priv
->head_note_parent
; 
2531     parent 
= (IOService 
*)nub
->copyParentEntry(gIOPowerPlane
); 
2533         parent
->acknowledgePowerChange((IOService 
*)nub
); 
2540 //********************************************************************************* 
2543 // A power change is complete, and the used post-change note is at 
2544 // the head of the queue.  Remove it and set myCurrentState to the result 
2545 // of the change.  Start up the next change in queue. 
2546 //********************************************************************************* 
2548 void IOService::all_done ( void ) 
2550     unsigned long       previous_state
; 
2551     IORegistryEntry 
*   nub
; 
2554     priv
->machine_state 
= IOPMfinished
; 
2556     if ( priv
->head_note_flags 
& IOPMWeInitiated 
) {                            // our power change 
2557         if ( !( priv
->head_note_flags 
& IOPMNotDone
) ) {                        // could our driver switch to the new state? 
2558             if ( pm_vars
->myCurrentState 
< priv
->head_note_state 
) {            // yes, did power raise? 
2559                 tellChangeUp (priv
->head_note_state
);                           // yes, inform clients and apps 
2562                 if ( !  priv
->we_are_root 
) {                                   // no, if this lowers our 
2563                     ask_parent(priv
->head_note_state
);                          // power requirements, tell the parent 
2566             previous_state 
= pm_vars
->myCurrentState
; 
2567             pm_vars
->myCurrentState 
= priv
->head_note_state
;                    // either way 
2568             priv
->imminentState 
= pm_vars
->myCurrentState
; 
2569             pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeDone
,(unsigned long)pm_vars
->myCurrentState
,0); 
2570             powerChangeDone(previous_state
);                                    // inform subclass policy-maker 
2573 //            pm_vars->myCurrentState = pm_vars->theControllingDriver->powerStateForDomainState(pm_vars->parentsCurrentPowerFlags); 
2576     if ( priv
->head_note_flags 
& IOPMParentInitiated
) {                         // parent's power change 
2577         if ( ((priv
->head_note_flags 
& IOPMDomainWillChange
) && (pm_vars
->myCurrentState 
>= priv
->head_note_state
)) || 
2578              ((priv
->head_note_flags 
& IOPMDomainDidChange
) && (pm_vars
->myCurrentState 
< priv
->head_note_state
)) ) { 
2579             if ( pm_vars
->myCurrentState 
< priv
->head_note_state 
) {            // did power raise? 
2580                 tellChangeUp (priv
->head_note_state
);                           // yes, inform clients and apps 
2582             previous_state 
= pm_vars
->myCurrentState
;                           // either way 
2583             pm_vars
->myCurrentState 
= priv
->head_note_state
; 
2584             priv
->imminentState 
= pm_vars
->myCurrentState
; 
2585             pm_vars
->maxCapability 
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(priv
->head_note_domainState
); 
2587             pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeDone
,(unsigned long)pm_vars
->myCurrentState
,0); 
2588             powerChangeDone(previous_state
);                                    // inform subclass policy-maker 
2592     IOLockLock(priv
->queue_lock
); 
2593     priv
->changeList
->releaseHeadChangeNote();                                  // we're done with this 
2595     priv
->head_note 
= priv
->changeList
->currentChange();                        // start next one in queue 
2596     if ( priv
->head_note 
!= -1 ) { 
2598         IOLockUnlock(priv
->queue_lock
); 
2599         if (priv
->changeList
->changeNote
[priv
->head_note
].flags 
& IOPMWeInitiated 
) { 
2600             start_our_change(priv
->head_note
); 
2603             nub 
= priv
->changeList
->changeNote
[priv
->head_note
].parent
; 
2604             if ( start_parent_change(priv
->head_note
) == IOPMAckImplied 
) { 
2605                 parent 
= (IOService 
*)nub
->copyParentEntry(gIOPowerPlane
); 
2607                     parent
->acknowledgePowerChange((IOService 
*)nub
); 
2613     IOLockUnlock(priv
->queue_lock
); 
2618 //********************************************************************************* 
2621 // A driver or child has acknowledged our notification of an upcoming power 
2622 // change, and this acknowledgement is the last one pending 
2623 // before we change power or after changing power. 
2625 //********************************************************************************* 
2627 void IOService::all_acked ( void ) 
2629     switch (priv
->machine_state
) { 
2630        case IOPMour_prechange_1
: 
2633        case IOPMour_prechange_4
: 
2636        case IOPMparent_down_4
: 
2639        case IOPMparent_down_6
: 
2642        case IOPMparent_up_0
: 
2645        case IOPMparent_up_6
: 
2652 //********************************************************************************* 
2653 // settleTimerExpired 
2655 // Power has settled after our last change.  Notify interested parties that 
2656 // there is a new power state. 
2657 //********************************************************************************* 
2659 void IOService::settleTimerExpired ( void ) 
2661     if ( ! initialized 
) { 
2662         return;                                 // we're unloading 
2665     switch (priv
->machine_state
) { 
2666         case IOPMour_prechange_3
: 
2669         case IOPMparent_down_3
: 
2672         case IOPMparent_up_5
: 
2679 //********************************************************************************* 
2680 // compute_settle_time 
2682 // Compute the power-settling delay in microseconds for the 
2683 // change from myCurrentState to head_note_state. 
2684 //********************************************************************************* 
2686 unsigned long IOService::compute_settle_time ( void ) 
2688     unsigned long totalTime
; 
2691     totalTime 
= 0;                                              // compute total time to attain the new state 
2692     i 
= pm_vars
->myCurrentState
; 
2693     if ( priv
->head_note_state 
< pm_vars
->myCurrentState 
) {    // we're lowering power 
2694         while ( i 
> priv
->head_note_state 
) { 
2695             totalTime 
+=  pm_vars
->thePowerStates
[i
].settleDownTime
; 
2700     if ( priv
->head_note_state 
> pm_vars
->myCurrentState 
) {    // we're raising power 
2701         while ( i 
< priv
->head_note_state 
) { 
2702             totalTime 
+=  pm_vars
->thePowerStates
[i
+1].settleUpTime
; 
2711 //********************************************************************************* 
2714 // Enter with a power-settling delay in microseconds and start a nano-second 
2715 // timer for that delay. 
2716 //********************************************************************************* 
2718 IOReturn 
IOService::startSettleTimer ( unsigned long delay 
) 
2720     AbsoluteTime        deadline
; 
2722     clock_interval_to_deadline(delay
, kMicrosecondScale
, &deadline
); 
2724     thread_call_enter_delayed(priv
->settleTimer
, deadline
); 
2729 //********************************************************************************* 
2732 // The acknowledgement timeout periodic timer has ticked. 
2733 // If we are awaiting acks for a power change notification, 
2734 // we decrement the timer word of each interested driver which hasn't acked. 
2735 // If a timer word becomes zero, we pretend the driver aknowledged. 
2736 // If we are waiting for the controlling driver to change the power 
2737 // state of the hardware, we decrement its timer word, and if it becomes 
2738 // zero, we pretend the driver acknowledged. 
2739 //********************************************************************************* 
2741 void IOService::ack_timer_ticked ( void ) 
2743     IOPMinformee 
* nextObject
; 
2745     if ( ! initialized 
) { 
2746         return;                                 // we're unloading 
2749     if (! acquire_lock() ) { 
2753     switch (priv
->machine_state
) { 
2754         case IOPMour_prechange_2
: 
2755         case IOPMparent_down_5
: 
2756         case IOPMparent_up_4
: 
2757             if ( priv
->driver_timer 
!= 0 ) {                            // are we waiting for our driver to make its change? 
2758                 priv
->driver_timer 
-= 1;                                // yes, tick once 
2759                 if ( priv
->driver_timer 
== 0 ) {                        // it's tardy, we'll go on without it 
2760                     IOUnlock(priv
->our_lock
); 
2761                     pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogCtrlDriverTardy
,0,0); 
2764                 else {                                                  // still waiting, set timer again 
2766                     IOUnlock(priv
->our_lock
); 
2770                 IOUnlock(priv
->our_lock
); 
2774         case IOPMour_prechange_1
: 
2775         case IOPMour_prechange_4
: 
2776         case IOPMparent_down_4
: 
2777         case IOPMparent_down_6
: 
2778         case IOPMparent_up_0
: 
2779         case IOPMparent_up_6
: 
2780             if (priv
->head_note_pendingAcks 
!= 0 ) {                    // are we waiting for interested parties to acknowledge? 
2781                 nextObject 
=  priv
->interestedDrivers
->firstInList();   // yes, go through the list of interested drivers 
2782                 while (  nextObject 
!= NULL 
) {                         // and check each one 
2783                     if ( nextObject
->timer 
> 0 ) { 
2784                         nextObject
->timer 
-= 1; 
2785                         if ( nextObject
->timer 
== 0 ) {                 // this one should have acked by now 
2786                             pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogIntDriverTardy
,0,0); 
2787                             kprintf("interested driver tardy: %s\n",nextObject
->whatObject
->getName()); 
2788                             priv
->head_note_pendingAcks 
-= 1; 
2791                     nextObject  
=  priv
->interestedDrivers
->nextInList(nextObject
); 
2793                 if ( priv
->head_note_pendingAcks 
== 0 ) {       // is that the last? 
2794                     IOUnlock(priv
->our_lock
); 
2795                     all_acked();                                // yes, we can continue 
2797                 else {                                          // no, set timer again 
2799                     IOUnlock(priv
->our_lock
); 
2803                 IOUnlock(priv
->our_lock
); 
2807         case IOPMparent_down_0
:                                 // apps didn't respond to parent-down notification 
2808             IOUnlock(priv
->our_lock
); 
2809             IOLockLock(priv
->flags_lock
); 
2810             if (pm_vars
->responseFlags
) { 
2811                 pm_vars
->responseFlags
->release();              // get rid of this stuff 
2812                 pm_vars
->responseFlags 
= NULL
; 
2814             IOLockUnlock(priv
->flags_lock
); 
2815             pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,5); 
2816             parent_down_04();                                   // carry on with the change 
2819         case IOPMparent_down_05
: 
2820             IOUnlock(priv
->our_lock
); 
2821             IOLockLock(priv
->flags_lock
); 
2822             if (pm_vars
->responseFlags
) { 
2823                 pm_vars
->responseFlags
->release();              // get rid of this stuff 
2824                 pm_vars
->responseFlags 
= NULL
; 
2826             IOLockUnlock(priv
->flags_lock
); 
2827             pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,1); 
2828             parent_down_05();                                   // carry on with the change 
2831         case IOPMour_prechange_03
:                              // apps didn't respond to our power-down request 
2832             IOUnlock(priv
->our_lock
); 
2833             IOLockLock(priv
->flags_lock
); 
2834             if (pm_vars
->responseFlags
) { 
2835                 pm_vars
->responseFlags
->release();              // get rid of this stuff 
2836                 pm_vars
->responseFlags 
= NULL
; 
2838             IOLockUnlock(priv
->flags_lock
); 
2839             pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,2); 
2840             tellNoChangeDown(priv
->head_note_state
);            // rescind the request 
2841             priv
->head_note_flags 
|= IOPMNotDone
;               // mark the change note un-actioned 
2842             all_done();                                         // and we're done 
2845         case IOPMour_prechange_04
:                              // clients didn't respond to our power-down note 
2846             IOUnlock(priv
->our_lock
); 
2847             IOLockLock(priv
->flags_lock
); 
2848             if (pm_vars
->responseFlags
) { 
2849                 pm_vars
->responseFlags
->release();              // get rid of this stuff 
2850                 pm_vars
->responseFlags 
= NULL
; 
2852             IOLockUnlock(priv
->flags_lock
); 
2853             pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,4); 
2854             our_prechange_04();                                 // carry on with the change 
2857         case IOPMour_prechange_05
:                              // apps didn't respond to our power-down notification 
2858             IOUnlock(priv
->our_lock
); 
2859             IOLockLock(priv
->flags_lock
); 
2860             if (pm_vars
->responseFlags
) { 
2861                 pm_vars
->responseFlags
->release();              // get rid of this stuff 
2862                 pm_vars
->responseFlags 
= NULL
; 
2864             IOLockUnlock(priv
->flags_lock
); 
2865             pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,3); 
2866             our_prechange_05();                                 // carry on with the change 
2870             IOUnlock(priv
->our_lock
);                           // not waiting for acks 
2876 //********************************************************************************* 
2879 //********************************************************************************* 
2881 void IOService::start_ack_timer ( void ) 
2883     AbsoluteTime        deadline
; 
2885     clock_interval_to_deadline(ACK_TIMER_PERIOD
, kNanosecondScale
, &deadline
); 
2887     thread_call_enter_delayed(priv
->ackTimer
, deadline
); 
2891 //********************************************************************************* 
2894 //********************************************************************************* 
2896 void IOService::stop_ack_timer ( void ) 
2898     thread_call_cancel(priv
->ackTimer
); 
2902 //********************************************************************************* 
2903 // c-language timer expiration functions 
2905 //********************************************************************************* 
2907 static void ack_timer_expired ( thread_call_param_t us
) 
2909     ((IOService 
*)us
)->ack_timer_ticked(); 
2913 static void settle_timer_expired ( thread_call_param_t us
) 
2915     ((IOService 
*)us
)->settleTimerExpired(); 
2919 //********************************************************************************* 
2920 // add_child_to_active_change 
2922 // A child has just registered with us.  If there is 
2923 // currently a change in progress, get the new party involved: if we 
2924 // have notified all parties and are waiting for acks, notify the new 
2926 //********************************************************************************* 
2928 IOReturn 
IOService::add_child_to_active_change ( IOPowerConnection 
* newObject 
) 
2930     if (! acquire_lock() ) { 
2934     switch (priv
->machine_state
) { 
2935         case IOPMour_prechange_1
: 
2936         case IOPMparent_down_4
: 
2937         case IOPMparent_up_0
: 
2938             priv
->head_note_pendingAcks 
+= 2;           // one for this child and one to prevent 
2939             IOUnlock(priv
->our_lock
);                   // incoming acks from changing our state 
2940             notifyChild(newObject
, true); 
2941             if (! acquire_lock() ) { 
2942                 --priv
->head_note_pendingAcks
;          // put it back 
2945             if ( --priv
->head_note_pendingAcks 
== 0 ) { // are we still waiting for acks? 
2946                 stop_ack_timer();                       // no, stop the timer 
2947                 IOUnlock(priv
->our_lock
); 
2948                 all_acked();                            // and now we can continue 
2952         case IOPMour_prechange_4
: 
2953         case IOPMparent_down_6
: 
2954         case IOPMparent_up_6
: 
2955             priv
->head_note_pendingAcks 
+= 2;           // one for this child and one to prevent 
2956             IOUnlock(priv
->our_lock
);                   // incoming acks from changing our state 
2957             notifyChild(newObject
, false); 
2958             if (! acquire_lock() ) { 
2959                 --priv
->head_note_pendingAcks
;          // put it back 
2962             if ( --priv
->head_note_pendingAcks 
== 0 ) { // are we still waiting for acks? 
2963                 stop_ack_timer();                       // no, stop the timer 
2964                 IOUnlock(priv
->our_lock
); 
2965                 all_acked();                            // and now we can continue 
2970     IOUnlock(priv
->our_lock
); 
2975 //********************************************************************************* 
2976 // add_driver_to_active_change 
2978 // An interested driver has just registered with us.  If there is 
2979 // currently a change in progress, get the new party involved: if we 
2980 // have notified all parties and are waiting for acks, notify the new 
2982 //********************************************************************************* 
2984 IOReturn 
IOService::add_driver_to_active_change ( IOPMinformee 
* newObject 
) 
2986     if (! acquire_lock() ) { 
2990     switch (priv
->machine_state
) { 
2991         case IOPMour_prechange_1
: 
2992         case IOPMparent_down_4
: 
2993         case IOPMparent_up_0
: 
2994             priv
->head_note_pendingAcks 
+= 2;           // one for this driver and one to prevent 
2995             IOUnlock(priv
->our_lock
);                   // incoming acks from changing our state 
2996             inform(newObject
, true);                    // inform the driver 
2997             if (! acquire_lock() ) { 
2998                 --priv
->head_note_pendingAcks
;          // put it back 
3001             if ( --priv
->head_note_pendingAcks 
== 0 ) { // are we still waiting for acks? 
3002                 stop_ack_timer();                       // no, stop the timer 
3003                 IOUnlock(priv
->our_lock
); 
3004                 all_acked();                            // and now we can continue 
3008         case IOPMour_prechange_4
: 
3009         case IOPMparent_down_6
: 
3010         case IOPMparent_up_6
: 
3011             priv
->head_note_pendingAcks 
+= 2;           // one for this driver and one to prevent 
3012             IOUnlock(priv
->our_lock
);                   // incoming acks from changing our state 
3013             inform(newObject
, false);                   // inform the driver 
3014             if (! acquire_lock() ) { 
3015                 --priv
->head_note_pendingAcks
;          // put it back 
3018             if ( --priv
->head_note_pendingAcks 
== 0 ) { // are we still waiting for acks? 
3019                 stop_ack_timer();                       // no, stop the timer 
3020                 IOUnlock(priv
->our_lock
); 
3021                 all_acked();                            // and now we can continue 
3026     IOUnlock(priv
->our_lock
); 
3031 //********************************************************************************* 
3032 // start_parent_change 
3034 // Here we begin the processing of a change note  initiated by our parent 
3035 // which is at the head of the queue. 
3037 // It is possible for the change to be processed to completion and removed from the queue. 
3038 // There are several possible interruptions to the processing, though, and they are: 
3039 // we may have to wait for interested parties to acknowledge our pre-change notification, 
3040 // we may have to wait for our controlling driver to change the hardware power state, 
3041 // there may be a settling time after changing the hardware power state, 
3042 // we may have to wait for interested parties to acknowledge our post-change notification, 
3043 // we may have to wait for the acknowledgement timer expiration to substitute for the 
3044 // acknowledgement from a failing driver. 
3045 //********************************************************************************* 
3047 IOReturn 
IOService::start_parent_change ( unsigned long queue_head 
) 
3049     priv
->head_note 
= queue_head
; 
3050     priv
->head_note_flags 
= priv
-> changeList
->changeNote
[priv
->head_note
].flags
; 
3051     priv
->head_note_state 
=  priv
->changeList
->changeNote
[priv
->head_note
].newStateNumber
; 
3052     priv
->imminentState 
= priv
->head_note_state
; 
3053     priv
->head_note_outputFlags 
=  priv
->changeList
->changeNote
[priv
->head_note
].outputPowerCharacter
; 
3054     priv
->head_note_domainState 
= priv
->changeList
->changeNote
[priv
->head_note
].domainState
; 
3055     priv
->head_note_parent 
= priv
->changeList
->changeNote
[priv
->head_note
].parent
; 
3056     priv
->head_note_capabilityFlags 
=  priv
->changeList
->changeNote
[priv
->head_note
].capabilityFlags
; 
3058     pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartParentChange
, 
3059                     (unsigned long)priv
->head_note_state
,(unsigned long)pm_vars
->myCurrentState
); 
3061     ask_parent( priv
->ourDesiredPowerState
);                    // if we need something and haven't told the parent, do so 
3063     if ( priv
->head_note_state 
< pm_vars
->myCurrentState 
) {    // power domain is lowering 
3064         setParentInfo(priv
->changeList
->changeNote
[priv
->head_note
].singleParentState
,priv
->head_note_parent
); 
3065         priv
->initial_change 
= false; 
3066         priv
->machine_state 
= IOPMparent_down_0
;                // tell apps and kernel clients 
3067         if ( tellChangeDown1(priv
->head_note_state
) ) {         // are we waiting for responses? 
3068             return parent_down_0();                             // no, notify priority clients 
3070        return IOPMWillAckLater
;                                 // yes 
3073     if ( priv
->head_note_state 
> pm_vars
->myCurrentState 
) {            // parent is raising power, we may or may not 
3074         if ( priv
->ourDesiredPowerState 
> pm_vars
->myCurrentState 
) { 
3075            if ( priv
->ourDesiredPowerState 
< priv
->head_note_state 
) { 
3076                priv
->head_note_state 
= priv
->ourDesiredPowerState
;      // we do, but not all the way 
3077                priv
->imminentState 
= priv
->head_note_state
; 
3078                priv
->head_note_outputFlags 
=   pm_vars
->thePowerStates
[priv
->head_note_state
].outputPowerCharacter
; 
3079                priv
->head_note_capabilityFlags 
=   pm_vars
->thePowerStates
[priv
->head_note_state
].capabilityFlags
; 
3080                pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAmendParentChange
,(unsigned long)priv
->head_note_state
,0); 
3084             priv
->head_note_state 
= pm_vars
->myCurrentState
;            // we don't 
3085             priv
->imminentState 
= priv
->head_note_state
; 
3086             priv
->head_note_outputFlags 
=   pm_vars
->thePowerStates
[priv
->head_note_state
].outputPowerCharacter
; 
3087             priv
->head_note_capabilityFlags 
=   pm_vars
->thePowerStates
[priv
->head_note_state
].capabilityFlags
; 
3088             pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAmendParentChange
,(unsigned long)priv
->head_note_state
,0); 
3092     if ( (priv
->head_note_state 
> pm_vars
->myCurrentState
) && 
3093          (priv
->head_note_flags 
& IOPMDomainDidChange
) ) {              // changing up 
3094         priv
->initial_change 
= false; 
3095         priv
->machine_state 
= IOPMparent_up_0
; 
3096         if (  notifyAll(true) == IOPMAckImplied 
) { 
3097             return parent_up_1(); 
3099         return IOPMWillAckLater
;                                        // they didn't all ack 
3103     return IOPMAckImplied
;                                              // a null change or power will go up 
3107 //********************************************************************************* 
3110 // Here we begin the processing of a change note  initiated by us 
3111 // which is at the head of the queue. 
3113 // It is possible for the change to be processed to completion and removed from the queue. 
3114 // There are several possible interruptions to the processing, though, and they are: 
3115 // we may have to wait for interested parties to acknowledge our pre-change notification, 
3116 // changes initiated by the parent will wait in the middle for powerStateDidChange, 
3117 // we may have to wait for our controlling driver to change the hardware power state, 
3118 // there may be a settling time after changing the hardware power state, 
3119 // we may have to wait for interested parties to acknowledge our post-change notification, 
3120 // we may have to wait for the acknowledgement timer expiration to substitute for the 
3121 // acknowledgement from a failing driver. 
3122 //********************************************************************************* 
3124 void IOService::start_our_change ( unsigned long queue_head 
) 
3126     priv
->head_note 
= queue_head
; 
3127     priv
->head_note_flags 
=  priv
->changeList
->changeNote
[priv
->head_note
].flags
; 
3128     priv
->head_note_state 
=  priv
->changeList
->changeNote
[priv
->head_note
].newStateNumber
; 
3129     priv
->imminentState 
= priv
->head_note_state
; 
3130     priv
->head_note_outputFlags 
=  priv
->changeList
->changeNote
[priv
->head_note
].outputPowerCharacter
; 
3131     priv
->head_note_capabilityFlags 
=  priv
->changeList
->changeNote
[priv
->head_note
].capabilityFlags
; 
3133     pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartDeviceChange
, 
3134                 (unsigned long)priv
->head_note_state
,(unsigned long)pm_vars
->myCurrentState
); 
3136     if ( priv
->head_note_capabilityFlags 
& IOPMNotAttainable 
) {        // can our driver switch to the new state? 
3137         if ( !  priv
->we_are_root 
) {                                   // no, ask the parent to do it then 
3138             ask_parent(priv
->head_note_state
); 
3140         priv
-> head_note_flags 
|= IOPMNotDone
;                          // mark the change note un-actioned 
3141         all_done();                                                     // and we're done 
3144                                                                         // is there enough power in the domain? 
3145     if ( (pm_vars
->maxCapability 
< priv
->head_note_state
) && (!  priv
->we_are_root
) ) { 
3146         if ( !  priv
->we_are_root 
) {                                   // no, ask the parent to raise it 
3147             ask_parent(priv
->head_note_state
); 
3149         priv
->head_note_flags 
|= IOPMNotDone
;                           // no, mark the change note un-actioned 
3150         all_done();                                                     // and we're done 
3151         return;                                                         // till the parent raises power 
3154     if ( !  priv
->initial_change 
) { 
3155         if ( priv
->head_note_state 
== pm_vars
->myCurrentState 
) { 
3156             all_done();                                         // we initiated a null change; forget it 
3160     priv
->initial_change 
= false; 
3162     if ( priv
->head_note_state 
< pm_vars
->myCurrentState 
) {    // dropping power? 
3163         priv
->machine_state 
= IOPMour_prechange_03
;             // yes, in case we have to wait for acks 
3164         pm_vars
->doNotPowerDown 
= false; 
3165         if ( askChangeDown(priv
->head_note_state
) ) {           // ask apps and kernel clients if we can drop power 
3166             if ( pm_vars
->doNotPowerDown 
) {                    // don't have to wait, did any clients veto? 
3167                 tellNoChangeDown(priv
->head_note_state
);        // yes, rescind the warning 
3168                 priv
-> head_note_flags 
|= IOPMNotDone
;          // mark the change note un-actioned 
3169                 all_done();                                     // and we're done 
3172                 our_prechange_03();                             // no, tell'em we're dropping power 
3177         if ( !  priv
->we_are_root 
) {                           // we are raising power 
3178             ask_parent(priv
->head_note_state
);                  // if this changes our power requirement, tell the parent 
3180         priv
->machine_state 
= IOPMour_prechange_1
;              // in case they don't all ack 
3181         if ( notifyAll(true) == IOPMAckImplied 
) {              // notify interested drivers and children 
3188 //********************************************************************************* 
3191 // Call the power domain parent to ask for a higher power state in the domain 
3192 // or to suggest a lower power state. 
3193 //********************************************************************************* 
3195 IOReturn 
IOService::ask_parent ( unsigned long requestedState 
) 
3199     IOPowerConnection 
* connection
; 
3201     unsigned long       ourRequest 
= pm_vars
->thePowerStates
[requestedState
].inputPowerRequirement
; 
3203     if ( pm_vars
->thePowerStates
[requestedState
].capabilityFlags 
& (kIOPMChildClamp 
| kIOPMPreventIdleSleep
) ) { 
3204         ourRequest 
|= kIOPMPreventIdleSleep
; 
3206     if ( pm_vars
->thePowerStates
[requestedState
].capabilityFlags 
& (kIOPMChildClamp2 
| kIOPMPreventSystemSleep
) ) { 
3207         ourRequest 
|= kIOPMPreventSystemSleep
; 
3210     if ( priv
->previousRequest 
== ourRequest 
) {        // is this a new desire? 
3211         return IOPMNoErr
;                               // no, the parent knows already, just return 
3214     if (  priv
->we_are_root 
) { 
3217     priv
->previousRequest 
=  ourRequest
; 
3219     iter 
= getParentIterator(gIOPowerPlane
); 
3222         while ( (next 
= iter
->getNextObject()) ) { 
3223             if ( (connection 
= OSDynamicCast(IOPowerConnection
,next
)) ) { 
3224                 parent 
= (IOService 
*)connection
->copyParentEntry(gIOPowerPlane
); 
3226                     if ( parent
->requestPowerDomainState(ourRequest
,connection
,IOPMLowestState
)!= IOPMNoErr 
) { 
3227                         pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRequestDenied
, 
3228                                                                 (unsigned long)priv
->previousRequest
,0); 
3241 //********************************************************************************* 
3244 // Call the controlling driver and have it change the power state of the 
3245 // hardware.  If it returns IOPMAckImplied, the change is complete, and 
3246 // we return IOPMAckImplied.  Otherwise, it will ack when the change 
3247 // is done; we return IOPMWillAckLater. 
3248 //********************************************************************************* 
3249 IOReturn 
IOService::instruct_driver ( unsigned long newState 
) 
3251     IOReturn return_code
; 
3253     if (  pm_vars
->thePowerStates
[newState
].capabilityFlags 
& IOPMNotAttainable 
) {     // can our driver switch to the desired state? 
3254         return IOPMAckImplied
;                                          // no, so don't try 
3256     priv
->driver_timer 
= -1; 
3258     pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogProgramHardware
,newState
,0); 
3260     return_code 
= pm_vars
->theControllingDriver
->setPowerState( newState
,this );        // yes, instruct it 
3261     if ( return_code 
== IOPMAckImplied 
) {                                      // it finished 
3262         priv
->driver_timer 
= 0; 
3263         return IOPMAckImplied
; 
3266     if ( priv
->driver_timer 
== 0 ) {                                            // it acked behind our back 
3267         return IOPMAckImplied
; 
3270     if ( return_code 
< 0 ) {                                                    // somebody goofed 
3271         return IOPMAckImplied
; 
3273     priv
->driver_timer 
= (return_code 
* ns_per_us 
/ ACK_TIMER_PERIOD
) + 1;      // it didn't finish 
3274     return IOPMWillAckLater
; 
3278 //********************************************************************************* 
3281 // We are acquiring the lock we use to protect our queue head from 
3282 // simutaneous access by a thread which calls acknowledgePowerStateChange 
3283 // or acknowledgeSetPowerState and the ack timer expiration thread. 
3284 // Return TRUE if we acquire the lock, and the queue head didn't change 
3285 // while we were acquiring the lock (and maybe blocked). 
3286 // If there is no queue head, or it changes while we are blocked, 
3287 // return FALSE with the lock unlocked. 
3288 //********************************************************************************* 
3290 bool IOService::acquire_lock ( void ) 
3292     long current_change_note
; 
3294     current_change_note 
= priv
->head_note
; 
3295     if ( current_change_note 
== -1 ) { 
3299     IOTakeLock(priv
->our_lock
); 
3300     if ( current_change_note 
== priv
->head_note 
) { 
3303     else {                                      // we blocked and something changed radically 
3304         IOUnlock(priv
->our_lock
);               // so there's nothing to do any more 
3310 //********************************************************************************* 
3313 // Ask registered applications and kernel clients if we can change to a lower 
3316 // Subclass can override this to send a different message type.  Parameter is 
3317 // the destination state number. 
3319 // Return true if we don't have to wait for acknowledgements 
3320 //********************************************************************************* 
3322 bool IOService::askChangeDown ( unsigned long stateNum 
) 
3324     return tellClientsWithResponse(kIOMessageCanDevicePowerOff
); 
3328 //********************************************************************************* 
3331 // Notify registered applications and kernel clients that we are definitely 
3334 // Return true if we don't have to wait for acknowledgements 
3335 //********************************************************************************* 
3337 bool IOService::tellChangeDown1 ( unsigned long stateNum 
) 
3339     pm_vars
->outofbandparameter 
= kNotifyApps
; 
3340     return tellChangeDown(stateNum
); 
3344 //********************************************************************************* 
3347 // Notify priority clients that we are definitely dropping power. 
3349 // Return true if we don't have to wait for acknowledgements 
3350 //********************************************************************************* 
3352 bool IOService::tellChangeDown2 ( unsigned long stateNum 
) 
3354     pm_vars
->outofbandparameter 
= kNotifyPriority
; 
3355     return tellChangeDown(stateNum
); 
3359 //********************************************************************************* 
3362 // Notify registered applications and kernel clients that we are definitely 
3365 // Subclass can override this to send a different message type.  Parameter is 
3366 // the destination state number. 
3368 // Return true if we don't have to wait for acknowledgements 
3369 //********************************************************************************* 
3371 bool IOService::tellChangeDown ( unsigned long stateNum 
) 
3373     return tellClientsWithResponse(kIOMessageDeviceWillPowerOff
); 
3377 //********************************************************************************* 
3378 // tellClientsWithResponse 
3380 // Notify registered applications and kernel clients that we are definitely 
3383 // Return true if we don't have to wait for acknowledgements 
3384 //********************************************************************************* 
3386 bool IOService::tellClientsWithResponse ( int messageType 
) 
3388     struct context      theContext
; 
3389     AbsoluteTime        deadline
; 
3392     pm_vars
->responseFlags 
= OSArray::withCapacity( 1 ); 
3393     pm_vars
->serialNumber 
+= 1; 
3395     theContext
.responseFlags 
= pm_vars
->responseFlags
; 
3396     theContext
.serialNumber 
= pm_vars
->serialNumber
; 
3397     theContext
.flags_lock 
= priv
->flags_lock
; 
3398     theContext
.counter 
= 1; 
3399     theContext
.msgType 
= messageType
; 
3400     theContext
.us 
= this; 
3401     theContext
.maxTimeRequested 
= 0; 
3402     theContext
.stateNumber 
= priv
->head_note_state
; 
3403     theContext
.stateFlags 
= priv
->head_note_capabilityFlags
; 
3405     IOLockLock(priv
->flags_lock
); 
3406     aBool 
= OSBoolean::withBoolean(false);              // position zero is false to    
3407     theContext
.responseFlags
->setObject(0,aBool
);       // prevent allowCancelCommon from succeeding 
3409     IOLockUnlock(priv
->flags_lock
); 
3411     switch ( pm_vars
->outofbandparameter 
) { 
3413             applyToInterested(gIOAppPowerStateInterest
,tellAppWithResponse
,(void *)&theContext
); 
3414             applyToInterested(gIOGeneralInterest
,tellClientWithResponse
,(void *)&theContext
); 
3416         case kNotifyPriority
: 
3417             applyToInterested(gIOPriorityPowerStateInterest
,tellClientWithResponse
,(void *)&theContext
); 
3421     if (! acquire_lock() ) { 
3424     IOLockLock(priv
->flags_lock
); 
3425     aBool 
= OSBoolean::withBoolean(true);               // now fix position zero 
3426     theContext
.responseFlags
->replaceObject(0,aBool
); 
3428     IOLockUnlock(priv
->flags_lock
); 
3430     if ( ! checkForDone() ) {                           // we have to wait for somebody 
3431         pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,theContext
.maxTimeRequested
,0); 
3432         clock_interval_to_deadline(theContext
.maxTimeRequested 
/ 1000, kMillisecondScale
, &deadline
); 
3434         thread_call_enter_delayed(priv
->ackTimer
, deadline
); 
3436         IOUnlock(priv
->our_lock
);                       // yes 
3440     IOUnlock(priv
->our_lock
); 
3441     IOLockLock(priv
->flags_lock
); 
3442     pm_vars
->responseFlags
->release();                  // everybody responded     
3443     pm_vars
->responseFlags 
= NULL
; 
3444     IOLockUnlock(priv
->flags_lock
); 
3450 //********************************************************************************* 
3451 // tellAppWithResponse 
3453 // We send a message to an application, and we expect a response, so we compute a 
3454 // cookie we can identify the response with. 
3455 //********************************************************************************* 
3456 void tellAppWithResponse ( OSObject 
* object
, void * context
) 
3458     struct context 
*    theContext 
= (struct context 
*)context
; 
3462     if( OSDynamicCast( IOService
, object
) ) { 
3463         IOLockLock(theContext
->flags_lock
); 
3464         aBool 
= OSBoolean::withBoolean(true); 
3465         theContext
->responseFlags
->setObject(theContext
->counter
,aBool
); 
3467         IOLockUnlock(theContext
->flags_lock
); 
3470         refcon 
= ((theContext
->serialNumber 
& 0xFFFF)<<16) + (theContext
->counter 
& 0xFFFF); 
3471         IOLockLock(theContext
->flags_lock
); 
3472         aBool 
= OSBoolean::withBoolean(false); 
3473         theContext
->responseFlags
->setObject(theContext
->counter
,aBool
); 
3475         IOLockUnlock(theContext
->flags_lock
); 
3476         theContext
->us
->messageClient(theContext
->msgType
,object
,(void *)refcon
); 
3477         if ( theContext
->maxTimeRequested 
< k30seconds 
) { 
3478             theContext
->maxTimeRequested 
= k30seconds
; 
3481     theContext
->counter 
+= 1; 
3485 //********************************************************************************* 
3486 // tellClientWithResponse 
3488 // We send a message to an in-kernel client, and we expect a response, so we compute a 
3489 // cookie we can identify the response with. 
3490 // If it doesn't understand the notification (it is not power-management savvy) 
3491 // we won't wait for it to prepare for sleep.  If it tells us via a return code 
3492 // in the passed struct that it is currently ready, we won't wait for it to prepare. 
3493 // If it tells us via the return code in the struct that it does need time, we will chill. 
3494 //********************************************************************************* 
3495 void tellClientWithResponse ( OSObject 
* object
, void * context
) 
3497     struct context 
*                    theContext 
= (struct context 
*)context
; 
3498     IOPowerStateChangeNotification      notify
; 
3504     refcon 
= ((theContext
->serialNumber 
& 0xFFFF)<<16) + (theContext
->counter 
& 0xFFFF); 
3505     IOLockLock(theContext
->flags_lock
); 
3506     aBool 
= OSBoolean::withBoolean(false); 
3507     theContext
->responseFlags
->setObject(theContext
->counter
,aBool
); 
3509     IOLockUnlock(theContext
->flags_lock
); 
3511     notify
.powerRef 
= (void *)refcon
; 
3512     notify
.returnValue 
= 0; 
3513     notify
.stateNumber 
= theContext
->stateNumber
; 
3514     notify
.stateFlags 
= theContext
->stateFlags
; 
3515     retCode 
= theContext
->us
->messageClient(theContext
->msgType
,object
,(void *)¬ify
); 
3516     if ( retCode 
== kIOReturnSuccess 
) { 
3517         if ( notify
.returnValue 
== 0 ) {                                                // client doesn't want time to respond 
3518             IOLockLock(theContext
->flags_lock
); 
3519             aBool 
= OSBoolean::withBoolean(true); 
3520             theContext
->responseFlags
->replaceObject(theContext
->counter
,aBool
);        // so set its flag true 
3522             IOLockUnlock(theContext
->flags_lock
); 
3525             IOLockLock(theContext
->flags_lock
); 
3526             theFlag 
= theContext
->responseFlags
->getObject(theContext
->counter
);        // it does want time, and it hasn't 
3527             if ( theFlag 
!= 0 ) {                                                       // responded yet 
3528                 if ( ((OSBoolean 
*)theFlag
)->isFalse() ) {                              // so note its time requirement 
3529                     if ( theContext
->maxTimeRequested 
< notify
.returnValue 
) { 
3530                         theContext
->maxTimeRequested 
= notify
.returnValue
; 
3534             IOLockUnlock(theContext
->flags_lock
); 
3537     else {                                                                      // not a client of ours 
3538         IOLockLock(theContext
->flags_lock
); 
3539         aBool 
= OSBoolean::withBoolean(true);                                   // so we won't be waiting for response 
3540         theContext
->responseFlags
->replaceObject(theContext
->counter
,aBool
); 
3542         IOLockUnlock(theContext
->flags_lock
); 
3544     theContext
->counter 
+= 1; 
3548 //********************************************************************************* 
3551 // Notify registered applications and kernel clients that we are not 
3554 // Subclass can override this to send a different message type.  Parameter is 
3555 // the aborted destination state number. 
3556 //********************************************************************************* 
3558 void IOService::tellNoChangeDown ( unsigned long ) 
3560     return tellClients(kIOMessageDeviceWillNotPowerOff
); 
3564 //********************************************************************************* 
3567 // Notify registered applications and kernel clients that we are raising power. 
3569 // Subclass can override this to send a different message type.  Parameter is 
3570 // the aborted destination state number. 
3571 //********************************************************************************* 
3573 void IOService::tellChangeUp ( unsigned long ) 
3575     return tellClients(kIOMessageDeviceHasPoweredOn
); 
3579 //********************************************************************************* 
3582 // Notify registered applications and kernel clients of something. 
3583 //********************************************************************************* 
3585 void IOService::tellClients ( int messageType 
) 
3587     struct context theContext
; 
3589     theContext
.msgType 
= messageType
; 
3590     theContext
.us 
= this; 
3591     theContext
.stateNumber 
= priv
->head_note_state
; 
3592     theContext
.stateFlags 
= priv
->head_note_capabilityFlags
; 
3594     applyToInterested(gIOAppPowerStateInterest
,tellClient
,(void *)&theContext
); 
3595     applyToInterested(gIOGeneralInterest
,tellClient
,(void *)&theContext
); 
3599 //********************************************************************************* 
3602 // Notify a registered application or kernel client of something. 
3603 //********************************************************************************* 
3604 void tellClient ( OSObject 
* object
, void * context
) 
3606     struct context 
*                    theContext 
= (struct context 
*)context
; 
3607     IOPowerStateChangeNotification      notify
; 
3609     notify
.powerRef     
= (void *) 0; 
3610     notify
.returnValue  
= 0; 
3611     notify
.stateNumber  
= theContext
->stateNumber
; 
3612     notify
.stateFlags   
= theContext
->stateFlags
; 
3614     theContext
->us
->messageClient(theContext
->msgType
,object
, ¬ify
); 
3618 // ********************************************************************************** 
3621 // ********************************************************************************** 
3622 bool IOService::checkForDone ( void ) 
3627     IOLockLock(priv
->flags_lock
); 
3628     if ( pm_vars
->responseFlags 
== NULL 
) { 
3629         IOLockUnlock(priv
->flags_lock
); 
3632     for ( i 
= 0; ; i
++ ) { 
3633         theFlag 
= pm_vars
->responseFlags
->getObject(i
); 
3634         if ( theFlag 
== NULL 
) { 
3637         if ( ((OSBoolean 
*)theFlag
)->isFalse() ) { 
3638             IOLockUnlock(priv
->flags_lock
); 
3642     IOLockUnlock(priv
->flags_lock
); 
3647 // ********************************************************************************** 
3650 // ********************************************************************************** 
3651 bool IOService::responseValid ( unsigned long x 
) 
3653     UInt16 serialComponent
; 
3654     UInt16 ordinalComponent
; 
3656     unsigned long refcon 
= (unsigned long)x
; 
3659     serialComponent 
= (refcon
>>16) & 0xFFFF; 
3660     ordinalComponent 
= refcon 
& 0xFFFF; 
3662     if ( serialComponent 
!= pm_vars
->serialNumber 
) { 
3666     IOLockLock(priv
->flags_lock
); 
3667     if ( pm_vars
->responseFlags 
== NULL 
) { 
3668         IOLockUnlock(priv
->flags_lock
); 
3672     theFlag 
= pm_vars
->responseFlags
->getObject(ordinalComponent
); 
3674     if ( theFlag 
== 0 ) { 
3675         IOLockUnlock(priv
->flags_lock
); 
3679     if ( ((OSBoolean 
*)theFlag
)->isFalse() ) { 
3680         aBool 
= OSBoolean::withBoolean(true); 
3681         pm_vars
->responseFlags
->replaceObject(ordinalComponent
,aBool
); 
3685     IOLockUnlock(priv
->flags_lock
); 
3690 // ********************************************************************************** 
3693 // Our power state is about to lower, and we have notified applications 
3694 // and kernel clients, and one of them has acknowledged.  If this is the last to do 
3695 // so, and all acknowledgements are positive, we continue with the power change. 
3697 // We serialize this processing with timer expiration with a command gate on the 
3698 // power management workloop, which the timer expiration is command gated to as well. 
3699 // ********************************************************************************** 
3700 IOReturn 
IOService::allowPowerChange ( unsigned long refcon 
) 
3702     if ( ! initialized 
) { 
3703         return kIOReturnSuccess
;                                // we're unloading 
3706     return pm_vars
->PMcommandGate
->runAction(serializedAllowPowerChange
,(void *)refcon
); 
3710 IOReturn 
serializedAllowPowerChange ( OSObject 
*owner
, void * refcon
, void *, void *, void *) 
3712     return ((IOService 
*)owner
)->serializedAllowPowerChange2((unsigned long)refcon
); 
3715 IOReturn 
IOService::serializedAllowPowerChange2 ( unsigned long refcon 
) 
3717     if ( ! responseValid(refcon
) ) {                                                    // response valid? 
3718         pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr5
,refcon
,0); 
3719         return kIOReturnSuccess
;                                                        // no, just return 
3721     pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientAcknowledge
,refcon
,0); 
3723     return allowCancelCommon(); 
3727 // ********************************************************************************** 
3728 // cancelPowerChange 
3730 // Our power state is about to lower, and we have notified applications 
3731 // and kernel clients, and one of them has vetoed the change.  If this is the last 
3732 // client to respond, we abandon the power change. 
3734 // We serialize this processing with timer expiration with a command gate on the 
3735 // power management workloop, which the timer expiration is command gated to as well. 
3736 // ********************************************************************************** 
3737 IOReturn 
IOService::cancelPowerChange ( unsigned long refcon 
) 
3739     if ( ! initialized 
) { 
3740         return kIOReturnSuccess
;                                // we're unloading 
3743     return pm_vars
->PMcommandGate
->runAction(serializedCancelPowerChange
,(void *)refcon
); 
3747 IOReturn 
serializedCancelPowerChange ( OSObject 
*owner
, void * refcon
, void *, void *, void *) 
3749     return ((IOService 
*)owner
)->serializedCancelPowerChange2((unsigned long)refcon
); 
3752 IOReturn 
IOService::serializedCancelPowerChange2 ( unsigned long refcon 
) 
3754     if ( ! responseValid(refcon
) ) {                                                    // response valid? 
3755         pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr5
,refcon
,0); 
3756         return kIOReturnSuccess
;                                                        // no, just return 
3758     pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientCancel
,refcon
,0); 
3760     pm_vars
->doNotPowerDown 
= true; 
3762     return allowCancelCommon(); 
3766 // ********************************************************************************** 
3767 // allowCancelCommon 
3769 // ********************************************************************************** 
3770 IOReturn 
IOService::allowCancelCommon ( void ) 
3772     if (! acquire_lock() ) { 
3773         return kIOReturnSuccess
; 
3776     if ( checkForDone() ) {                                     // is this the last response? 
3777         stop_ack_timer();                                       // yes, stop the timer 
3778         IOUnlock(priv
->our_lock
); 
3779         IOLockLock(priv
->flags_lock
); 
3780         if ( pm_vars
->responseFlags 
) { 
3781             pm_vars
->responseFlags
->release(); 
3782             pm_vars
->responseFlags 
= NULL
; 
3784         IOLockUnlock(priv
->flags_lock
); 
3785         switch (priv
->machine_state
) { 
3786             case IOPMour_prechange_03
:                          // our change, was it vetoed? 
3787                 if ( ! pm_vars
->doNotPowerDown 
) { 
3788                     our_prechange_03();                         // no, we can continue 
3791                     tellNoChangeDown(priv
->head_note_state
);    // yes, rescind the warning 
3792                     priv
->head_note_flags 
|= IOPMNotDone
;       // mark the change note un-actioned 
3793                     all_done();                                 // and we're done 
3796             case IOPMour_prechange_04
: 
3799             case IOPMour_prechange_05
: 
3800                 our_prechange_05();                             // our change, continue 
3802             case IOPMparent_down_0
: 
3803                 parent_down_04();                               // parent change, continue 
3805             case IOPMparent_down_05
: 
3806                 parent_down_05();                               // parent change, continue 
3811     IOUnlock(priv
->our_lock
);                                   // not done yet 
3812     return kIOReturnSuccess
; 
3816 //********************************************************************************* 
3819 // Set to highest available power state for a minimum of duration milliseconds 
3820 //********************************************************************************* 
3822 #define kFiveMinutesInNanoSeconds (300 * NSEC_PER_SEC) 
3824 void IOService::clampPowerOn (unsigned long duration
) 
3826   changePowerStateToPriv (pm_vars
->theNumberOfPowerStates
-1); 
3828   if (  priv
->clampTimerEventSrc 
== NULL 
) { 
3829     priv
->clampTimerEventSrc 
= IOTimerEventSource::timerEventSource(this, 
3830                                                     c_PM_Clamp_Timer_Expired
); 
3832     IOWorkLoop 
* workLoop 
= getPMworkloop (); 
3834     if ( !priv
->clampTimerEventSrc 
|| !workLoop 
|| 
3835        ( workLoop
->addEventSource(  priv
->clampTimerEventSrc
) != kIOReturnSuccess
) ) { 
3840     priv
->clampTimerEventSrc
->setTimeout(kFiveMinutesInNanoSeconds
, NSEC_PER_SEC
); 
3843 //********************************************************************************* 
3844 // PM_Clamp_Timer_Expired 
3846 // called when clamp timer expires...set power state to 0. 
3847 //********************************************************************************* 
3849 void IOService::PM_Clamp_Timer_Expired (void) 
3851     if ( ! initialized 
) { 
3852         return;                                 // we're unloading 
3855   changePowerStateToPriv (0); 
3858 //********************************************************************************* 
3859 // c_PM_clamp_Timer_Expired (C Func) 
3861 // Called when our clamp timer expires...we will call the object method. 
3862 //********************************************************************************* 
3864 void c_PM_Clamp_Timer_Expired (OSObject 
* client
, IOTimerEventSource 
*) 
3867     ((IOService 
*)client
)->PM_Clamp_Timer_Expired (); 
3871 //********************************************************************************* 
3874 // Does nothing here.  This should be implemented in a subclass driver. 
3875 //********************************************************************************* 
3877 IOReturn 
IOService::setPowerState ( unsigned long powerStateOrdinal
, IOService
* whatDevice 
) 
3883 //********************************************************************************* 
3884 // maxCapabilityForDomainState 
3886 // Finds the highest power state in the array whose input power 
3887 // requirement is equal to the input parameter.  Where a more intelligent 
3888 // decision is possible, override this in the subclassed driver. 
3889 //********************************************************************************* 
3891 unsigned long IOService::maxCapabilityForDomainState ( IOPMPowerFlags domainState 
) 
3895    if (pm_vars
->theNumberOfPowerStates 
== 0 ) { 
3898    for ( i 
= (pm_vars
->theNumberOfPowerStates
)-1; i 
>= 0; i
-- ) { 
3899        if (  (domainState 
& pm_vars
->thePowerStates
[i
].inputPowerRequirement
) == pm_vars
->thePowerStates
[i
].inputPowerRequirement 
) { 
3907 //********************************************************************************* 
3908 // initialPowerStateForDomainState 
3910 // Finds the highest power state in the array whose input power 
3911 // requirement is equal to the input parameter.  Where a more intelligent 
3912 // decision is possible, override this in the subclassed driver. 
3913 //********************************************************************************* 
3915 unsigned long IOService::initialPowerStateForDomainState ( IOPMPowerFlags domainState 
) 
3919    if (pm_vars
->theNumberOfPowerStates 
== 0 ) { 
3922    for ( i 
= (pm_vars
->theNumberOfPowerStates
)-1; i 
>= 0; i
-- ) { 
3923        if (  (domainState 
& pm_vars
->thePowerStates
[i
].inputPowerRequirement
) == pm_vars
->thePowerStates
[i
].inputPowerRequirement 
) { 
3931 //********************************************************************************* 
3932 // powerStateForDomainState 
3934 // Finds the highest power state in the array whose input power 
3935 // requirement is equal to the input parameter.  Where a more intelligent 
3936 // decision is possible, override this in the subclassed driver. 
3937 //********************************************************************************* 
3939 unsigned long IOService::powerStateForDomainState ( IOPMPowerFlags domainState 
) 
3943    if (pm_vars
->theNumberOfPowerStates 
== 0 ) { 
3946    for ( i 
= (pm_vars
->theNumberOfPowerStates
)-1; i 
>= 0; i
-- ) { 
3947        if (  (domainState 
& pm_vars
->thePowerStates
[i
].inputPowerRequirement
) == pm_vars
->thePowerStates
[i
].inputPowerRequirement 
) { 
3955 //********************************************************************************* 
3958 // Does nothing here.  This should be implemented in a subclass driver. 
3959 //********************************************************************************* 
3961 bool IOService::didYouWakeSystem  ( void ) 
3967 //********************************************************************************* 
3968 // powerStateWillChangeTo 
3970 // Does nothing here.  This should be implemented in a subclass driver. 
3971 //********************************************************************************* 
3973 IOReturn 
IOService::powerStateWillChangeTo ( IOPMPowerFlags
, unsigned long, IOService
*) 
3979 //********************************************************************************* 
3980 // powerStateDidChangeTo 
3982 // Does nothing here.  This should be implemented in a subclass driver. 
3983 //********************************************************************************* 
3985 IOReturn 
IOService::powerStateDidChangeTo ( IOPMPowerFlags
, unsigned long, IOService
*) 
3991 //********************************************************************************* 
3994 // Does nothing here.  This should be implemented in a subclass policy-maker. 
3995 //********************************************************************************* 
3997 void IOService::powerChangeDone ( unsigned long ) 
4002 //********************************************************************************* 
4005 // Does nothing here.  This should be implemented in a subclass driver. 
4006 //********************************************************************************* 
4008 IOReturn 
IOService::newTemperature ( long currentTemp
, IOService 
* whichZone 
) 
4016 #define super OSObject 
4018 OSDefineMetaClassAndStructors(IOPMprot
, OSObject
) 
4019 //********************************************************************************* 
4022 // Serialize protected instance variables for debug output. 
4023 //********************************************************************************* 
4024 bool IOPMprot::serialize(OSSerialize 
*s
) const 
4026     OSString 
* theOSString
; 
4032     buffer 
= ptr 
= IONew(char, 2000); 
4036     ptr 
+= sprintf(ptr
,"{ theNumberOfPowerStates = %d, ",(unsigned int)theNumberOfPowerStates
); 
4038     if ( theNumberOfPowerStates 
!= 0 ) { 
4039         ptr 
+= sprintf(ptr
,"version %d, ",(unsigned int)thePowerStates
[0].version
); 
4042     if ( theNumberOfPowerStates 
!= 0 ) { 
4043         for ( i 
= 0; i 
< (int)theNumberOfPowerStates
; i
++ ) { 
4044             ptr 
+= sprintf(ptr
,"power state %d = { ",i
); 
4045             ptr 
+= sprintf(ptr
,"capabilityFlags %08x, ",(unsigned int)thePowerStates
[i
].capabilityFlags
); 
4046             ptr 
+= sprintf(ptr
,"outputPowerCharacter %08x, ",(unsigned int)thePowerStates
[i
].outputPowerCharacter
); 
4047             ptr 
+= sprintf(ptr
,"inputPowerRequirement %08x, ",(unsigned int)thePowerStates
[i
].inputPowerRequirement
); 
4048             ptr 
+= sprintf(ptr
,"staticPower %d, ",(unsigned int)thePowerStates
[i
].staticPower
); 
4049             ptr 
+= sprintf(ptr
,"unbudgetedPower %d, ",(unsigned int)thePowerStates
[i
].unbudgetedPower
); 
4050             ptr 
+= sprintf(ptr
,"powerToAttain %d, ",(unsigned int)thePowerStates
[i
].powerToAttain
); 
4051             ptr 
+= sprintf(ptr
,"timeToAttain %d, ",(unsigned int)thePowerStates
[i
].timeToAttain
); 
4052             ptr 
+= sprintf(ptr
,"settleUpTime %d, ",(unsigned int)thePowerStates
[i
].settleUpTime
); 
4053             ptr 
+= sprintf(ptr
,"timeToLower %d, ",(unsigned int)thePowerStates
[i
].timeToLower
); 
4054             ptr 
+= sprintf(ptr
,"settleDownTime %d, ",(unsigned int)thePowerStates
[i
].settleDownTime
); 
4055             ptr 
+= sprintf(ptr
,"powerDomainBudget %d }, ",(unsigned int)thePowerStates
[i
].powerDomainBudget
); 
4059     ptr 
+= sprintf(ptr
,"aggressiveness = %d, ",(unsigned int)aggressiveness
); 
4060     ptr 
+= sprintf(ptr
,"myCurrentState = %d, ",(unsigned int)myCurrentState
); 
4061     ptr 
+= sprintf(ptr
,"parentsCurrentPowerFlags = %08x, ",(unsigned int)parentsCurrentPowerFlags
); 
4062     ptr 
+= sprintf(ptr
,"maxCapability = %d }",(unsigned int)maxCapability
); 
4064     theOSString 
= OSString::withCString(buffer
); 
4065     rtn_code 
= theOSString
->serialize(s
); 
4066     theOSString
->release(); 
4067     IODelete(buffer
, char, 2000); 
4074 #define super OSObject 
4076 OSDefineMetaClassAndStructors(IOPMpriv
, OSObject
) 
4077 //********************************************************************************* 
4080 // Serialize private instance variables for debug output. 
4081 //********************************************************************************* 
4082 bool IOPMpriv::serialize(OSSerialize 
*s
) const 
4084     OSString 
*                  theOSString
; 
4088     IOPMinformee 
*              nextObject
; 
4090     buffer 
= ptr 
= IONew(char, 2000); 
4094     ptr 
+= sprintf(ptr
,"{ this object = %08x",(unsigned int)owner
); 
4095     if ( we_are_root 
) { 
4096         ptr 
+= sprintf(ptr
," (root)"); 
4098     ptr 
+= sprintf(ptr
,", "); 
4100     nextObject 
= interestedDrivers
->firstInList();                      // display interested drivers 
4101     while (  nextObject 
!= NULL 
) { 
4102         ptr 
+= sprintf(ptr
,"interested driver = %08x, ",(unsigned int)nextObject
->whatObject
); 
4103         nextObject  
=  interestedDrivers
->nextInList(nextObject
); 
4106     if ( machine_state 
!= IOPMfinished 
) { 
4107         ptr 
+= sprintf(ptr
,"machine_state = %d, ",(unsigned int)machine_state
); 
4108         ptr 
+= sprintf(ptr
,"driver_timer = %d, ",(unsigned int)driver_timer
); 
4109         ptr 
+= sprintf(ptr
,"settle_time = %d, ",(unsigned int)settle_time
); 
4110         ptr 
+= sprintf(ptr
,"head_note_flags = %08x, ",(unsigned int)head_note_flags
); 
4111         ptr 
+= sprintf(ptr
,"head_note_state = %d, ",(unsigned int)head_note_state
); 
4112         ptr 
+= sprintf(ptr
,"head_note_outputFlags = %08x, ",(unsigned int)head_note_outputFlags
); 
4113         ptr 
+= sprintf(ptr
,"head_note_domainState = %08x, ",(unsigned int)head_note_domainState
); 
4114         ptr 
+= sprintf(ptr
,"head_note_capabilityFlags = %08x, ",(unsigned int)head_note_capabilityFlags
); 
4115         ptr 
+= sprintf(ptr
,"head_note_pendingAcks = %d, ",(unsigned int)head_note_pendingAcks
); 
4118     if ( device_overrides 
) { 
4119         ptr 
+= sprintf(ptr
,"device overrides, "); 
4121     ptr 
+= sprintf(ptr
,"driverDesire = %d, ",(unsigned int)driverDesire
); 
4122     ptr 
+= sprintf(ptr
,"deviceDesire = %d, ",(unsigned int)deviceDesire
); 
4123     ptr 
+= sprintf(ptr
,"ourDesiredPowerState = %d, ",(unsigned int)ourDesiredPowerState
); 
4124     ptr 
+= sprintf(ptr
,"previousRequest = %d }",(unsigned int)previousRequest
); 
4126     theOSString 
=  OSString::withCString(buffer
); 
4127     rtn_code 
= theOSString
->serialize(s
); 
4128     theOSString
->release(); 
4129     IODelete(buffer
, char, 2000);