Annotation of XNU/iokit/Kernel/IOServicePM.cpp, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: #include <IOKit/IOService.h>
        !            23: #include <IOKit/IOLib.h>
        !            24: #include <IOKit/IOCommandQueue.h>
        !            25: #include <IOKit/IOTimerEventSource.h>
        !            26: #include <IOKit/IOWorkLoop.h>
        !            27: #include <IOKit/IOPlatformExpert.h>
        !            28: #include <IOKit/assert.h>
        !            29: #include "IOKit/pwr_mgt/IOPMpmChild.h"
        !            30: #include "IOKit/pwr_mgt/IOPMinformeeList.h"
        !            31: #include "IOKit/pwr_mgt/IOPMchangeNoteList.h"
        !            32: #include "IOKit/pwr_mgt/IOPMlog.h"
        !            33: 
        !            34: static void ack_timer_expired(thread_call_param_t, thread_call_param_t);
        !            35: static void settle_timer_expired(thread_call_param_t, thread_call_param_t);
        !            36: void PMreceiveCmd ( OSObject *,  void *, void *, void *, void * );
        !            37: static void PM_idle_timer_expired(OSObject *, IOTimerEventSource *);
        !            38: 
        !            39: extern const IORegistryPlane * gIOPowerPlane;
        !            40: 
        !            41: 
        !            42: // and there's 1000 nanosecons in a microsecond:
        !            43: #define ns_per_us 1000
        !            44: 
        !            45: 
        !            46: // The current change note is processed by a state machine.
        !            47: // Inputs are acks from interested parties, ack from the controlling driver,
        !            48: // ack timeouts, settle timeout, and powerStateDidChange from the parent.
        !            49: // These are the states:
        !            50: 
        !            51: #define IOPMour_prechange_1            1
        !            52: #define IOPMour_prechange_2            2
        !            53: #define IOPMour_prechange_3            3
        !            54: #define IOPMour_prechange_4            4
        !            55: #define IOPMparent_prechange_down_3    5
        !            56: #define IOPMparent_prechange_down_4    6
        !            57: #define IOPMparent_prechange_down_5    7
        !            58: #define IOPMparent_postchange_down_1   8
        !            59: #define IOPMparent_postchange_down_2   9
        !            60: #define IOPMparent_prechange_up_1      10
        !            61: #define IOPMparent_postchange_up_1     11
        !            62: #define IOPMparent_postchange_up_4     12
        !            63: #define IOPMparent_postchange_up_5     13
        !            64: #define IOPMparent_postchange_up_6     14
        !            65: #define IOPMparent_postchange_null     15
        !            66: #define IOPMfinished                   16
        !            67: 
        !            68: /*
        !            69:  There are two different kinds of power state changes.  One is initiated by a subclassed device object which has either
        !            70:  decided to change power state, or its controlling driver has suggested it, or some other driver wants to use the
        !            71:  idle device and has asked it to become usable.  The second kind of power state change is initiated by the power
        !            72:  domain parent.  The two are handled slightly differently.
        !            73: 
        !            74: There is a queue of so-called change notifications, or change notes for short.  Usually the queue is empty, and when
        !            75:  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
        !            76:  at one time, a queue is implemented.  Example:  the subclass device decides it's idle and initiates a change to a lower
        !            77:  power state.  This causes interested parties to be notified, but they don't all acknowledge right away.  This causes the
        !            78:  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
        !            79:  wants to raise power back up again.  This change can't be started, however, because the previous one isn't complete yet,
        !            80:  so the second one waits in the queue.  During this time, the parent decides to lower or raise the power state of the entire
        !            81:  power domain and notifies the device, and that notification goes into the queue, too, and can't be actioned until the
        !            82:  others are.
        !            83: 
        !            84:  This is how a power change initiated by the subclass device is handled:
        !            85:  First, all interested parties are notified of the change via their powerStateWillChangeTo method.  If they all don't
        !            86:  acknowledge via return code, then we have to wait.  If they do, or when they finally all acknowledge via our
        !            87:  acknowledgePowerChange method, then we can continue.  We call the controlling driver, instructing it to change to
        !            88:  the new state.  Then we wait for power to settle.  If there is no settling-time, or after it has passed, we notify
        !            89:  interested parties again, this time via their powerStateDidChangeTo methods.  When they have all acked, we're done.
        !            90:  If we lowered power and don't need the power domain to be in its current power state, we suggest to the parent that
        !            91:  it lower the power domain state.
        !            92: 
        !            93:  This is how a change to a lower power domain state initiated by the parent is handled:
        !            94:  First, we figure out what power state we will be in when the new domain state is reached.  Then all interested parties are
        !            95:  notified that we are moving to that new state.  When they have acknowledged, we call the controlling driver to assume
        !            96:  that state and we wait for power to settle.  Then we acknowledge our preparedness to our parent.  When all its interested
        !            97:  parties have acknowledged, it lowers power and then notifies its interested parties again.  When we get this call, we notify
        !            98:  our interested parties that the power state has changed, and when they have all acknowledged, we're done.
        !            99: 
        !           100:  This is how a change to a higher power domain state initiated by the parent is handled:
        !           101:  We figure out what power state we will be in when the new domain state is reached.  If it is different from our current
        !           102:  state we notify all our interested parties.  When they have all acknowledged, we acknowledge the parent.  When all the
        !           103:  parent's interested parties have acknowledged, it raises power in the domain and waits for power to settle.  Then it
        !           104:  notifies everyone that the new state has been reached.  When we get this call, we call the controlling driver, instructing it
        !           105:  to assume the new state, and wait for power to settle.  Then we notify our interested parties.  When they all acknowledge
        !           106:  we are done.
        !           107: 
        !           108:  In either of the two cases above, it is possible that we will not be changing state even though the domain is.  Examples:
        !           109:  A change to a lower domain state may not affect us because we are already in a low enough state, and
        !           110:  We will not take advantage of a change to a higher domain state, because we have no need of the higher power.
        !           111:  In such a case, there is nothing to do but acknowledge the parent.  So when the parent calls our powerDomainWillChange
        !           112:  method, and we decide that we will not be changing state, we merely acknowledge the parent, via return code, and wait.
        !           113:  When the parent subsequently calls powerStateDidChange, we acknowledge again via return code, and the change is complete.
        !           114: 
        !           115:  Power state changes are processed in a state machine, and since there are four varieties of power state changes, there are
        !           116:  four major paths through the state machine:
        !           117: 
        !           118:  The fourth is nearly trivial.  In this path, the parent is changing the domain state, but we are not changing the device state.
        !           119:  The change starts when the parent calls powerDomainWillChange.  All we do is acknowledge the parent and enter the "IOPMparent_postchange" state.  We wait there until the parent calls powerStateDidChange.  Then we acknowledge the parent
        !           120:  again, and we're done.
        !           121: 
        !           122:  The first is fairly simple.  It starts when a power domain child calls requestDomainState and we decide to change power states
        !           123:  to accomodate the child, or if our power-controlling driver calls changeStateTo, or if some other driver which is using our
        !           124:  device calls makeUsable, or if a subclassed object calls changeStateToPriv.  These are all power changes initiated by us, not
        !           125:  forced upon us by the parent.  We start by notifying interested parties.  If they all acknowledge via return code, we can go
        !           126:  on to state "our_prechange_1".  Otherwise, we start the ack timer and wait for the stragglers to acknowlege by calling
        !           127:  acknowledgePowerChange.  We move on to state "our_prechange_1" when all the stragglers have acknowledged,
        !           128:  or when the ack timer expires on all those which didn't acknowledge.  In "our_prechange_1" we call the power-controlling
        !           129:  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".
        !           130:  Otherwise, we have to wait for it, so we set the ack timer and wait.  When it calls acknowledgeSetPowerState, or when the
        !           131:  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
        !           132:  when changing from our current state to the new state.  If not, we go right away to "our_prechange_3".  Otherwise, we
        !           133:  set the settle timer and wait.  When it expires, we move on.  In "our_prechange_3" state, we notify all our interested parties
        !           134:  via their powerStateDidChange methods that we have finished changing power state.  If they all acknowledge via return
        !           135:  code, we move on to "our_prechange_4".  Otherwise we set the ack timer and wait.  When they have all acknowledged, or
        !           136:  when the ack timer has expired for those that didn't, we move on to "our_prechange_4", where we remove the used
        !           137:  change note from the head of the queue and start the next one if one exists.
        !           138: 
        !           139:  Parent-initiated changes are more complex in the state machine.  First, power going up and power going down are handled
        !           140:  differently, so they have different paths throught the state machine.  Second, we can acknowledge the parent's notification
        !           141:  in two different ways, so each of the parent paths is really two.
        !           142: 
        !           143:  When the parent calls our powerDomainWillChange method, notifying us that it will lower power in the domain, we decide
        !           144:  what state that will put our device in.  Then we embark on the state machine path "IOPMparent_prechange_down_1"
        !           145:  and "IOPMparent_prechange_down_2", in which we notify interested parties of the upcoming change,
        !           146:  instruct our driver to make the change, and check for settle time.  If we get to the end of this path without
        !           147:  stalling due to an interested party which didn't acknowledge via return code, due to the controlling driver not able to change
        !           148:  state right away, or due to a non-zero settling time, then we return IOPMAckImplied to the parent and enter
        !           149:  "IOPMparent_postchange_down_1".  If we do stall in any of those states, we return IOPMWillAckLater to the parent
        !           150:  and enter the parallel path "IOPMparent_prechange_down_4", "IOPMparent_prechange_down_5", and "IOPMparent_prechange_down_3", where we continue with the same processing, except that at the end we
        !           151:  acknowledge the parent explicitly via acknowledgePowerChange and enter "IOPMparent_postchange_down_1".
        !           152:  In "IOPMparent_postchange_down_1" we wait for the parent to lower power in the domain.  When it calls us at
        !           153:  powerStateDidChange, we notify all our interested parties of the new power state.  If they all acknowledge via return
        !           154:  code, we return to the parent, also acknowledging via return code.  Otherwise we enter "parent_postchange_down_2",
        !           155:  waiting for acknowledgements.  When they all arrive, or when the acknowledgement timer expires for all stragglers, we
        !           156:  explicitly acknowledge the parent via acknowledgePowerChange.  In either case, we are done, and we remove the used
        !           157:  change note from the head of the queue and start on the next one.
        !           158: 
        !           159:  The case of the parent raising power in the domain is handled similarly in that there are parallel paths, one for no-stall
        !           160:  that ends in implicit acknowleging the parent, and one that has stalled at least once that ends in explicit acknowledging
        !           161:  the parent.  This case is different, though in that our device changes state in the second half, after the parent calls
        !           162:  powerStateDidChange rather than before, as in the power-lowering case.
        !           163: 
        !           164:  As usual, we start by notifying our interested parties.  If they all acknowledge via return code, we acknowledge the parent
        !           165:  via return code and enter "IOPMparent_postchange_up_1".  If they don't, we wait in "parent_prechange_up_1" for them to
        !           166:  acknowledge or for the ack timer to expire on the stragglers.  Then we acknowledge the parent via acknowledgePowerChange
        !           167:  and enter "IOPMparent_postchange_up_1", waiting for the parent to raise power and notify us.  When the parent calls us
        !           168:  at powerStateDidChange, we instruct the power-controlling driver to change to the new higher state, we check for any
        !           169:  necessary settling time in "IOPMparent_postchange_up_2", and we notify all interested parties that power has changed
        !           170:  in "IOPMparent_postchange_up_3".  If none of these operations stall, we acknowledge the parent via return code, release
        !           171:  the change note, and start the next, if there is one.  If one of them does stall, we enter the parallel path
        !           172:  "IOPMparent_postchange_up_4", "IOPMparent_postchange_up_5", and "IOPMparent_postchange_up_6", which ends with
        !           173:  our explicit acknowledgement to the parent.
        !           174: 
        !           175: */
        !           176: 
        !           177: 
        !           178: const char priv_key[ ] = "Power Management private data";
        !           179: const char prot_key[ ] = "Power Management protected data";
        !           180: 
        !           181: 
        !           182: void IOService::PMinit ( void )
        !           183: {
        !           184:     if ( ! initialized ) {
        !           185: 
        !           186:         pm_vars =  new IOPMprot;                                       // make space for our variables
        !           187:         priv = new IOPMpriv;
        !           188:         pm_vars->init();
        !           189:         priv->init();
        !           190:         
        !           191:         setProperty(prot_key, (OSObject *) pm_vars);                   // add these to the properties
        !           192:         setProperty(priv_key, (OSObject *) priv);
        !           193: 
        !           194:         initialized = true;
        !           195:         priv->owner = this;
        !           196:         pm_vars->theNumberOfPowerStates = 0;                           // then initialize them
        !           197:         pm_vars->myParent = NULL;
        !           198:         priv->we_are_root = false;
        !           199:         pm_vars->theControllingDriver = NULL;
        !           200:         priv->our_lock = IOLockAlloc();
        !           201:         priv->interestedDrivers = new IOPMinformeeList;
        !           202:         priv->interestedDrivers->initialize();
        !           203:         priv->children = new IOPMinformeeList;
        !           204:         priv->children->initialize();
        !           205:         priv->numberOfInformees = 0;
        !           206:         priv->changeList = new IOPMchangeNoteList;
        !           207:         priv->changeList->initialize();
        !           208:         pm_vars->aggressiveness = 0;
        !           209:         pm_vars->myCurrentState =  0;
        !           210:         priv->imminentState = 0;
        !           211:         priv->askingFor = 0;
        !           212:         priv->ourDesiredPowerState = 0;
        !           213:         pm_vars->parentCurrentPowerFlags = 0;
        !           214:         pm_vars->maxCapability = 0;
        !           215:         priv->driverDesire = 0;
        !           216:         priv->deviceDesire = 0;
        !           217:         priv->initial_change = true;
        !           218:         priv->need_to_become_usable = false;
        !           219:         priv->previousRequest = 0;
        !           220:         priv->device_overrides = false;
        !           221:         priv->machine_state = IOPMfinished;
        !           222:         pm_vars->commandQueue = NULL;
        !           223:         priv->timerEventSrc = NULL;
        !           224:         pm_vars->PMworkloop = NULL;
        !           225:         priv->activityLock = NULL;
        !           226:         pm_vars->ourName = getName();
        !           227:         pm_vars->thePlatform = getPlatform();
        !           228:         assert( pm_vars->thePlatform != 0 );
        !           229:     }
        !           230: }
        !           231: 
        !           232: 
        !           233: //*********************************************************************************
        !           234: // PMstop
        !           235: //
        !           236: // Free up the data created in PMinit.
        !           237: //*********************************************************************************
        !           238: void IOService::PMstop ( void )
        !           239: {
        !           240:     initialized = false;
        !           241: 
        !           242:     removeProperty(prot_key);          // remove the properties
        !           243:     removeProperty(priv_key);
        !           244:     priv->interestedDrivers->release();                // remove lists
        !           245:     priv->children->release();
        !           246:     priv->changeList->release();
        !           247:     pm_vars->release();                        // remove the instance variables
        !           248:     priv->release();
        !           249:     pm_vars = NULL;
        !           250:     priv = NULL;
        !           251: }
        !           252: 
        !           253: 
        !           254: //*********************************************************************************
        !           255: // joinPMtree
        !           256: //
        !           257: // A policy-maker calls its nub here when initializing, to be attached into
        !           258: // the power management hierarchy.  The default function is to call the
        !           259: // platform expert, which knows how to do it.  This method is overridden
        !           260: // by a nub subclass which may either know how to do it, or may need
        !           261: // to take other action.
        !           262: //
        !           263: // This may be the only "power management" method used in a nub,
        !           264: // meaning it may not be initialized for power management.
        !           265: //*********************************************************************************
        !           266: void IOService::joinPMtree ( IOService * driver )
        !           267: {
        !           268:     IOPlatformExpert * thePlatform;
        !           269: 
        !           270:     thePlatform = getPlatform();
        !           271:     assert(thePlatform != 0 );
        !           272:     thePlatform->PMRegisterDevice(this,driver);
        !           273: }
        !           274: 
        !           275: 
        !           276: //*********************************************************************************
        !           277: // youAreRoot
        !           278: //
        !           279: // Power Managment is informing us that we are the root power domain.
        !           280: // The only difference between us and any other power domain is that
        !           281: // we have no parent and therefore never call it.
        !           282: //*********************************************************************************
        !           283: IOReturn IOService::youAreRoot ( void )
        !           284: {
        !           285:     priv-> we_are_root = true;
        !           286:     pm_vars->myParent = (IOService *)1;                // we won't use this, but keep it non-NULL
        !           287:     return IOPMNoErr;
        !           288: }
        !           289: 
        !           290: 
        !           291: //*********************************************************************************
        !           292: // setParent
        !           293: //
        !           294: // Power Management is informing us who our parent is.
        !           295: // If we have a controlling driver, find out, given our newly-informed
        !           296: // power domain state, what state it would be in, and then tell it
        !           297: // to assume that state.
        !           298: //*********************************************************************************
        !           299: IOReturn IOService::setParent ( IOService * theParent, IOPMPowerFlags currentState )
        !           300: {
        !           301:     unsigned long tempDesire;
        !           302: 
        !           303:     pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogSetParent,(unsigned long)currentState,0);
        !           304: 
        !           305:     attachToParent( theParent, gIOPowerPlane);
        !           306:     pm_vars->myParent = theParent;
        !           307:     pm_vars->parentCurrentPowerFlags = currentState;
        !           308:     if ( pm_vars->theControllingDriver != NULL ) {
        !           309:         pm_vars->maxCapability = pm_vars->theControllingDriver->maxCapabilityForDomainState(pm_vars->parentCurrentPowerFlags);
        !           310:         tempDesire = priv->deviceDesire;                       // initially change into the state we are already in
        !           311:         priv->deviceDesire = pm_vars->theControllingDriver->initialPowerStateForDomainState(pm_vars->parentCurrentPowerFlags);
        !           312:         changeState();
        !           313:         priv->deviceDesire = tempDesire;                       // put this back like before
        !           314:     }
        !           315:    return IOPMNoErr;
        !           316: }
        !           317: 
        !           318: 
        !           319: //*********************************************************************************
        !           320: // addChild
        !           321: //
        !           322: // Power Management is informing us who our children are.
        !           323: //*********************************************************************************
        !           324: IOReturn IOService::addChild ( IOService * theChild )
        !           325: {
        !           326:     IOPMinformee * newChild;
        !           327:     IOPMPowerFlags capability;
        !           328: 
        !           329:     pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogAddChild,0,0);
        !           330: 
        !           331:     theChild->retain();
        !           332:     
        !           333:     newChild = new IOPMpmChild;
        !           334:     newChild->initialize(theChild);                            // make a new child
        !           335:     priv->children->addToList(newChild);                       // add it to list of children
        !           336:     priv->numberOfInformees = priv->children->numberOfItems() +  priv->interestedDrivers->numberOfItems();
        !           337:     if ( pm_vars->theControllingDriver == NULL ) {             // tell it the current state of the power domain
        !           338:         capability = 0;
        !           339:     }
        !           340:     else {
        !           341:         capability =  pm_vars->thePowerStates[pm_vars->myCurrentState].outputPowerCharacter;
        !           342:     }
        !           343:     theChild->setParent(this,capability);
        !           344:     theChild->setAggressiveness (kPMGeneralAggressiveness,pm_vars->aggressiveness);    // tell it the current aggressiveness
        !           345:     add_to_active_change(newChild, true);                      // catch it up if change is in progress
        !           346:     return IOPMNoErr;
        !           347: }
        !           348: 
        !           349: 
        !           350: //*********************************************************************************
        !           351: // removeChild
        !           352: //
        !           353: //*********************************************************************************
        !           354: IOReturn IOService::removeChild ( IOService * theChild )
        !           355: {
        !           356:     pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogRemoveChild,0,0);
        !           357: 
        !           358:     priv->children->removeFromList(theChild);    // remove the departing child
        !           359:     priv->numberOfInformees = priv->children->numberOfItems() +  priv->interestedDrivers->numberOfItems();
        !           360:     
        !           361:     if ( (pm_vars->theControllingDriver == NULL) ||    // if not fully initialized
        !           362:          (pm_vars->myParent == NULL) ) {
        !           363:         return IOPMNoErr;                              // we can do no more
        !           364:     }
        !           365: 
        !           366:     changeState();                                     // change state if we can now tolerate lower power
        !           367: 
        !           368:     return IOPMNoErr;
        !           369: }
        !           370: 
        !           371: 
        !           372: //*********************************************************************************
        !           373: // registerControllingDriver
        !           374: //
        !           375: // A driver has called us volunteering to control power to our device.
        !           376: // If the power state array it provides is richer than the one we already
        !           377: // know about (supplied by an earlier volunteer), then accept the offer.
        !           378: // Notify all interested parties of our power state, which we now know.
        !           379: //*********************************************************************************
        !           380: 
        !           381: IOReturn IOService::registerControllingDriver ( IOService * controllingDriver, IOPMPowerState* powerStates, unsigned long numberOfStates  )
        !           382: {
        !           383:     unsigned long i;
        !           384:     unsigned long tempDesire;
        !           385: 
        !           386:     if ( (numberOfStates > pm_vars->theNumberOfPowerStates) && (numberOfStates > 1) ) {
        !           387:         if (  priv->changeList->currentChange() == -1 ) {
        !           388:             if ( controllingDriver != NULL ) {
        !           389:                 if ( numberOfStates <= IOPMMaxPowerStates ) {
        !           390:                     switch ( powerStates[0].version  ) {
        !           391:                         case 1:
        !           392:                             pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogControllingDriver,
        !           393:                                                                     (unsigned long)numberOfStates, (unsigned long)powerStates[0].version);
        !           394:                             for ( i = 0; i < numberOfStates; i++ ) {
        !           395:                                 pm_vars->thePowerStates[i] = powerStates[i];
        !           396:                             }
        !           397:                                 break;
        !           398:                         case 2:
        !           399:                             pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogControllingDriver,
        !           400:                                                                     (unsigned long) numberOfStates,(unsigned long) powerStates[0].version);
        !           401:                             for ( i = 0; i < numberOfStates; i++ ) {
        !           402:                                 pm_vars->thePowerStates[i].version = powerStates[i].version;
        !           403:                                 pm_vars->thePowerStates[i].capabilityFlags = powerStates[i].capabilityFlags;
        !           404:                                 pm_vars->thePowerStates[i].outputPowerCharacter = powerStates[i].outputPowerCharacter;
        !           405:                                 pm_vars->thePowerStates[i].inputPowerRequirement = powerStates[i].inputPowerRequirement;
        !           406:                                 pm_vars->thePowerStates[i].staticPower = powerStates[i].staticPower;
        !           407:                                 pm_vars->thePowerStates[i].unbudgetedPower = powerStates[i].unbudgetedPower;
        !           408:                                 pm_vars->thePowerStates[i].powerToAttain = powerStates[i].powerToAttain;
        !           409:                                 pm_vars->thePowerStates[i].timeToAttain = powerStates[i].timeToAttain;
        !           410:                                 pm_vars->thePowerStates[i].settleUpTime = powerStates[i].settleUpTime;
        !           411:                                 pm_vars->thePowerStates[i].timeToLower = powerStates[i].timeToLower;
        !           412:                                 pm_vars->thePowerStates[i].settleDownTime = powerStates[i].settleDownTime;
        !           413:                                 pm_vars->thePowerStates[i].powerDomainBudget = powerStates[i].powerDomainBudget;
        !           414:                             }
        !           415:                                 break;
        !           416:                         default:
        !           417:                             pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogControllingDriverErr1,
        !           418:                                                                     (unsigned long)powerStates[0].version,0);
        !           419:                             return IOPMNoErr;
        !           420:                     }
        !           421: 
        !           422:                     pm_vars->theNumberOfPowerStates = numberOfStates;
        !           423:                     pm_vars->theControllingDriver = controllingDriver;
        !           424:                     if ( priv->interestedDrivers->findItem(controllingDriver) == NULL ) {      // register it as interested
        !           425:                         registerInterestedDriver (controllingDriver );                         // unless already done
        !           426:                     }
        !           427:                     if ( priv->need_to_become_usable ) {
        !           428:                         priv->need_to_become_usable = false;
        !           429:                         priv->deviceDesire = pm_vars->theNumberOfPowerStates - 1;
        !           430:                     }
        !           431:                     if ( pm_vars->myParent != NULL ) {
        !           432:                         pm_vars->maxCapability = pm_vars->theControllingDriver->maxCapabilityForDomainState(pm_vars->parentCurrentPowerFlags);
        !           433:                         tempDesire = priv->deviceDesire;                       // initially change into the state we are already in
        !           434:                         priv->deviceDesire = pm_vars->theControllingDriver->initialPowerStateForDomainState(pm_vars->parentCurrentPowerFlags);
        !           435:                         changeState();
        !           436:                         priv->deviceDesire = tempDesire;                       // put this back like before
        !           437:                     }
        !           438:                 }
        !           439:                 else {
        !           440:                     pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogControllingDriverErr2,(unsigned long)numberOfStates,0);
        !           441:                 }
        !           442:             }
        !           443:             else {
        !           444:                 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogControllingDriverErr4,0,0);
        !           445:             }
        !           446:         }
        !           447:     }
        !           448:     else {
        !           449:         pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogControllingDriverErr5,(unsigned long)numberOfStates,0);
        !           450:     }
        !           451:     return IOPMNoErr;
        !           452: }
        !           453: 
        !           454: //*********************************************************************************
        !           455: // registerInterestedDriver
        !           456: //
        !           457: // Add the caller to our list of interested drivers and return our current
        !           458: // power state.  If we don't have a power-controlling driver yet, we will
        !           459: // call this interested driver again later when we do get a driver and find
        !           460: // out what the current power state of the device is.
        !           461: //*********************************************************************************
        !           462: 
        !           463: IOPMPowerFlags IOService::registerInterestedDriver ( IOService * theDriver )
        !           464: {
        !           465:     IOPMinformee * newInformee;
        !           466:     IOPMPowerFlags futureCapability;
        !           467: 
        !           468:     if (theDriver == NULL ) {
        !           469:         return 0;                                                      // can't tell it a state yet
        !           470:     }
        !           471: 
        !           472:     theDriver->retain();
        !           473:     
        !           474:     newInformee = new IOPMinformee;                            // make new driver node
        !           475:     newInformee->initialize(theDriver);
        !           476:     priv->interestedDrivers->addToList(newInformee);                   // add it to list of drivers
        !           477:     priv->numberOfInformees = priv->children->numberOfItems() +  priv->interestedDrivers->numberOfItems();
        !           478: 
        !           479:     if ( (pm_vars->theControllingDriver == NULL) || (pm_vars->myParent == NULL) ) {
        !           480:         pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogInterestedDriver,0,0);
        !           481:         return 0;                                                      // can't tell it a state yet
        !           482:     }
        !           483: 
        !           484:     switch (priv->machine_state) {                                     // can we notify new driver of a change in progress?
        !           485:         case IOPMour_prechange_1:
        !           486:         case IOPMour_prechange_4:
        !           487:         case IOPMparent_prechange_down_4:
        !           488:         case IOPMparent_postchange_down_2:
        !           489:         case IOPMparent_prechange_up_1:
        !           490:         case IOPMparent_postchange_up_6:
        !           491:             futureCapability = priv->head_note_capabilityFlags;                        // yes, remember what we tell it
        !           492:             pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogInterestedDriver,(unsigned long)futureCapability,0);
        !           493:             add_to_active_change(newInformee,false);                           // notify it
        !           494:             return futureCapability;                                           // and return the same thing
        !           495:     }
        !           496:     pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogInterestedDriver,
        !           497:                                             (unsigned long) pm_vars->thePowerStates[pm_vars->myCurrentState].capabilityFlags,0);
        !           498:     return  pm_vars->thePowerStates[pm_vars->myCurrentState].capabilityFlags;  // no, return current capability
        !           499: }
        !           500: 
        !           501: 
        !           502: //*********************************************************************************
        !           503: // deRegisterInterestedDriver
        !           504: //
        !           505: //*********************************************************************************
        !           506: IOReturn IOService::deRegisterInterestedDriver ( IOService * theDriver )
        !           507: {
        !           508:     pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogRemoveDriver,0,0);
        !           509: 
        !           510:     priv->interestedDrivers->removeFromList(theDriver);                                  // remove the departing driver
        !           511:     priv->numberOfInformees = priv->children->numberOfItems() +  priv->interestedDrivers->numberOfItems();
        !           512: 
        !           513:     theDriver->release();
        !           514: 
        !           515:     return IOPMNoErr;
        !           516: }
        !           517: 
        !           518: 
        !           519: //*********************************************************************************
        !           520: // acknowledgePowerChange
        !           521: //
        !           522: // After we notified one of the interested drivers or a power-domain child
        !           523: // of an impending change in power, it has called to say it is now
        !           524: // prepared for the change.  If this object is the last to
        !           525: // acknowledge this change, we take whatever action we have been waiting
        !           526: // for.
        !           527: // That may include acknowledging to our parent.  In this case, we do it
        !           528: // last of all to insure that this doesn't cause the parent to call us some-
        !           529: // where else and alter data we are relying on here (like the very existance
        !           530: // of a "current change note".)
        !           531: //*********************************************************************************
        !           532: 
        !           533: IOReturn IOService::acknowledgePowerChange ( IOService * whichObject )
        !           534: {
        !           535:    IOPMinformee *      ackingObject;
        !           536: 
        !           537:     ackingObject =  priv->interestedDrivers->findItem(whichObject);                    // one of our interested drivers?
        !           538:    if ( ackingObject == NULL ) {
        !           539:        ackingObject = priv->children->findItem(whichObject);                   // no, one of our children?
        !           540:        if ( ackingObject == NULL ) {
        !           541:            pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogAcknowledgeErr1,0,0);
        !           542:            return IOPMNoErr;                                                   // no, just return
        !           543:        }
        !           544:        else {
        !           545:            pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogChildAcknowledge,0,0);
        !           546:        }
        !           547:    }
        !           548:    else {
        !           549:        pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogDriverAcknowledge,0,0);
        !           550:    }
        !           551: 
        !           552:    if (! acquire_lock() ) {
        !           553:        return IOPMNoErr;
        !           554:    }
        !           555: 
        !           556:    if (priv->head_note_pendingAcks != 0 ) {                                    // yes, make sure we're expecting acks
        !           557:        if ( ackingObject->timer != 0 ) {                                               // make sure we're expecting this ack
        !           558:            ackingObject->timer = 0;                                            // mark it acked
        !           559:            priv->head_note_pendingAcks -= 1;                                   // that's one fewer to worry about
        !           560:            if ( priv->head_note_pendingAcks == 0 ) {                                   // is that the last?
        !           561:                stop_ack_timer();                                                       // yes, stop the timer
        !           562:                IOUnlock(priv->our_lock);
        !           563:                all_acked();                                                    // and now we can continue
        !           564:                return IOPMNoErr;
        !           565:            }
        !           566:        }
        !           567:        else {
        !           568:            pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogAcknowledgeErr2,0,0);     // this object has already acked
        !           569:        }
        !           570:    }
        !           571:    else {
        !           572:        pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogAcknowledgeErr3,0,0); // not expecting anybody to ack
        !           573:    }
        !           574:    IOUnlock(priv->our_lock);
        !           575:    return IOPMNoErr;
        !           576: }
        !           577: 
        !           578: //*********************************************************************************
        !           579: // acknowledgeSetPowerState
        !           580: //
        !           581: // After we instructed our controlling driver to change power states,
        !           582: // it has called to say it has finished doing so.
        !           583: // We continue to process the power state change.
        !           584: //*********************************************************************************
        !           585: 
        !           586: IOReturn IOService::acknowledgeSetPowerState ( void )
        !           587: {
        !           588:     if (! acquire_lock() ) {
        !           589:         return IOPMNoErr;
        !           590:     }
        !           591:     if ( priv->driver_timer == -1 ) {
        !           592:         priv->driver_timer = 0;                                // driver is acking instead of using return code
        !           593:     }
        !           594:     else {
        !           595:         if ( priv->driver_timer > 0 ) {                        // are we expecting this?
        !           596:             stop_ack_timer();                          // yes, stop the timer
        !           597:             priv->driver_timer = 0;
        !           598:             IOUnlock(priv->our_lock);
        !           599:             pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogDriverAcknowledgeSet,0,0);
        !           600:             driver_acked();
        !           601:             return IOPMNoErr;
        !           602:         }
        !           603:         else {
        !           604:             pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogAcknowledgeErr4,0,0);            // no
        !           605:         }
        !           606:     }
        !           607:     IOUnlock(priv->our_lock);
        !           608:     return IOPMNoErr;
        !           609: }
        !           610: 
        !           611: 
        !           612: //*********************************************************************************
        !           613: // driver_acked
        !           614: //
        !           615: // Either the controlling driver has called acknowledgeSetPowerState
        !           616: // or the acknowledgement timer has expired while waiting for that.
        !           617: // We carry on processing the current change note.
        !           618: //*********************************************************************************
        !           619: 
        !           620: void IOService::driver_acked ( void )
        !           621: {
        !           622:     switch (priv->machine_state) {
        !           623:         case IOPMour_prechange_2:
        !           624:             our_prechange_2();
        !           625:             break;
        !           626:         case IOPMparent_prechange_down_5:
        !           627:             parent_prechange_down_5();
        !           628:             break;
        !           629:         case IOPMparent_postchange_up_4:
        !           630:             parent_postchange_up_4();
        !           631:             break;
        !           632:     }
        !           633: }
        !           634: 
        !           635: 
        !           636: //*********************************************************************************
        !           637: // powerDomainWillChangeTo
        !           638: //
        !           639: // Called by the power-hierarchy parent notifying of a new power state
        !           640: // in the power domain.
        !           641: // If power is going lower, we notify our interested parties that power
        !           642: // will lower.  When they have all acked, we lower the state of our device
        !           643: // to the state appropriate for the coming domain level.  Then we ack the parent.
        !           644: // Later, when the domain has lowered, we notify everyone that power has dropped.
        !           645: //
        !           646: // If power is going higher and we will take advantage of this by raising our
        !           647: // own power state, we notify our interested parties that power
        !           648: // will raise.  When they have all acked, we ack the parent.  Later, when
        !           649: // the domain has raised, we raise our power level.  When power has
        !           650: // settled, we inform our interested parties.  When they have all acked,
        !           651: // we ack the parent.
        !           652: //*********************************************************************************
        !           653: 
        !           654: IOReturn IOService::powerDomainWillChangeTo ( IOPMPowerFlags newPowerStateFlags )
        !           655: {
        !           656:    unsigned long       newStateNumber;
        !           657: 
        !           658:     pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogWillChange,(unsigned long)newPowerStateFlags,0);
        !           659: 
        !           660:     if ( pm_vars->myParent == NULL ) {
        !           661:         return IOPMAckImplied;                                         // somebody goofed
        !           662:     }
        !           663: 
        !           664:     if  ( pm_vars->theControllingDriver == NULL ) {
        !           665:         pm_vars->parentCurrentPowerFlags = newPowerStateFlags;         // we can't take any action except note the change
        !           666:         return IOPMAckImplied;
        !           667:     }
        !           668:     newStateNumber = pm_vars->theControllingDriver->maxCapabilityForDomainState(newPowerStateFlags);
        !           669:     return enqueuePowerChange(IOPMParentInitiated, newStateNumber,newPowerStateFlags); // tell interested parties about it
        !           670: }
        !           671: 
        !           672: 
        !           673: //*********************************************************************************
        !           674: // powerDomainDidChangeTo
        !           675: //
        !           676: // Called by the power-hierarchy parent after the power state of the power domain
        !           677: // has settled at a new level.  We must notify our interested drivers and children.
        !           678: // If they all acknowledge immediately, so do we.  Otherwise, we'll acknowledge
        !           679: // when the last of them does.
        !           680: //*********************************************************************************
        !           681: 
        !           682: IOReturn IOService::powerDomainDidChangeTo ( IOPMPowerFlags newPowerStateFlags )
        !           683: {
        !           684: 
        !           685:     pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogDidChange,(unsigned long)newPowerStateFlags,0);
        !           686: 
        !           687:     if ( (pm_vars->myParent == NULL) || (pm_vars->theControllingDriver == NULL) ) {
        !           688:         return IOPMAckImplied;                                 // somebody goofed
        !           689:     }
        !           690: 
        !           691:     switch (priv->machine_state) {
        !           692:         case IOPMparent_postchange_down_1:
        !           693:             return parent_postchange_down_1();                         // life-style 2 continues
        !           694:         case IOPMparent_postchange_up_1:
        !           695:             return parent_postchange_up_1();                           // life-style 3 continues
        !           696:         case IOPMparent_postchange_null:
        !           697:             all_done();
        !           698:             return IOPMAckImplied;                                     // life-style 4 done
        !           699:     }
        !           700: 
        !           701:     return IOPMAckImplied;                                     // something wrong
        !           702: }
        !           703: 
        !           704: 
        !           705: //*********************************************************************************
        !           706: // requestDomainState
        !           707: //
        !           708: //
        !           709: //*********************************************************************************
        !           710: IOReturn IOService::requestDomainState ( IOPMPowerFlags desiredState, IOService* whichChild, unsigned long specification )
        !           711: {
        !           712:     unsigned long      i;
        !           713:     IOPMinformee *     nextChild;
        !           714: 
        !           715:     pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogRequestDomain,
        !           716:                                 (unsigned long)desiredState,(unsigned long)specification);
        !           717: 
        !           718:     if ( pm_vars->theControllingDriver == NULL) {
        !           719:         return IOPMNotYetInitialized;
        !           720:     }
        !           721: 
        !           722:     switch (specification) {
        !           723:         case IOPMLowestState:
        !           724:             i = 0;
        !           725:             while ( i < pm_vars->theNumberOfPowerStates ) {
        !           726:                 if ( ( pm_vars->thePowerStates[i].outputPowerCharacter & desiredState) == desiredState ) {
        !           727:                     break;
        !           728:                 }
        !           729:                 i++;
        !           730:             }
        !           731:                 if ( i >= pm_vars->theNumberOfPowerStates ) {
        !           732:                 return IOPMNoSuchState;
        !           733:            }
        !           734:             break;
        !           735: 
        !           736:         case IOPMNextLowerState:
        !           737:             i = pm_vars->myCurrentState - 1;
        !           738:             while ( i >= 0 ) {
        !           739:                 if ( ( pm_vars->thePowerStates[i].outputPowerCharacter & desiredState) == desiredState ) {
        !           740:                     break;
        !           741:                 }
        !           742:                 i--;
        !           743:             }
        !           744:             if ( i < 0 ) {
        !           745:                 return IOPMNoSuchState;
        !           746:             }
        !           747:             break;
        !           748: 
        !           749:         case IOPMHighestState:
        !           750:             i = pm_vars->theNumberOfPowerStates;
        !           751:             while ( i >= 0 ) {
        !           752:                 i--;
        !           753:                 if ( ( pm_vars->thePowerStates[i].outputPowerCharacter & desiredState) == desiredState ) {
        !           754:                     break;
        !           755:                 }
        !           756:             }
        !           757:             if ( i < 0 ) {
        !           758:                 return IOPMNoSuchState;
        !           759:             }
        !           760:             break;
        !           761: 
        !           762:         case IOPMNextHigherState:
        !           763:             i = pm_vars->myCurrentState + 1;
        !           764:             while ( i < pm_vars->theNumberOfPowerStates ) {
        !           765:                 if ( ( pm_vars->thePowerStates[i].outputPowerCharacter & desiredState) == desiredState ) {
        !           766:                     break;
        !           767:                 }
        !           768:             i++;
        !           769:             }
        !           770:                 if ( i == pm_vars->theNumberOfPowerStates ) {
        !           771:                 return IOPMNoSuchState;
        !           772:             }
        !           773:             break;
        !           774: 
        !           775:         default:
        !           776:             return IOPMBadSpecification;
        !           777:     }
        !           778: 
        !           779: // Now loop through the children.  When we encounter the calling child, save
        !           780: // the new state as this child's desire.  Then, compute a new maximum
        !           781: // of everybody's desires.
        !           782: 
        !           783:     nextChild = priv->children->firstInList();
        !           784: 
        !           785:    if ( nextChild == NULL ) {                  // we're not a power domain
        !           786:        return IOPMNoErr;
        !           787:    }
        !           788: 
        !           789:    while ( nextChild != NULL ) {
        !           790:        if ( whichChild == (IOService*)nextChild->whatObject ) {
        !           791:            ((IOPMpmChild *)nextChild)->desiredDomainState = i;
        !           792:            break;
        !           793:        }
        !           794:        nextChild = priv->children->nextInList(nextChild);
        !           795:    }
        !           796: 
        !           797:    if ( pm_vars->myParent != NULL ) {
        !           798:        changeState();                                  // change state if all children can now tolerate lower power
        !           799:    }
        !           800: 
        !           801:    return IOPMNoErr;
        !           802: }
        !           803: 
        !           804: 
        !           805: //*********************************************************************************
        !           806: // makeUsable
        !           807: //
        !           808: // Some client of our device is asking that we become usable.  Although
        !           809: // this has not come from a subclassed device object, treat it exactly
        !           810: // as if it had.  In this way, subsequent requests for lower power from
        !           811: // a subclassed device object will pre-empt this request.
        !           812: //
        !           813: // We treat this as a subclass object request to switch to the
        !           814: // highest power state.
        !           815: //*********************************************************************************
        !           816: 
        !           817: IOReturn IOService::makeUsable ( void )
        !           818: {
        !           819:     pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogMakeUsable,0,0);
        !           820: 
        !           821:     if ( pm_vars->theControllingDriver == NULL ) {
        !           822:         priv->need_to_become_usable = true;
        !           823:         return IOPMNoErr;
        !           824:     }
        !           825:     priv->deviceDesire = pm_vars->theNumberOfPowerStates - 1;
        !           826:     if ( pm_vars->myParent == NULL  ) {
        !           827:         return IOPMNoErr;
        !           828:     }
        !           829:    return changeState();
        !           830: }
        !           831: 
        !           832: 
        !           833: //*********************************************************************************
        !           834: // currentCapability
        !           835: //
        !           836: //*********************************************************************************
        !           837: 
        !           838: IOPMPowerFlags IOService::currentCapability ( void )
        !           839: {
        !           840:     if ( pm_vars->theControllingDriver == NULL ) {
        !           841:         return 0;
        !           842:     }
        !           843:     else {
        !           844:         return   pm_vars->thePowerStates[pm_vars->myCurrentState].capabilityFlags;
        !           845:     }
        !           846: }
        !           847: 
        !           848: 
        !           849: //*********************************************************************************
        !           850: // changeStateTo
        !           851: //
        !           852: // For some reason, our power-controlling driver has decided it needs to change
        !           853: // power state.  We enqueue the power change so that appropriate parties
        !           854: // will be notified, and then we will instruct the driver to make the change.
        !           855: //*********************************************************************************
        !           856: 
        !           857: IOReturn IOService::changeStateTo ( unsigned long ordinal )
        !           858: {
        !           859:     pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogChangeStateTo,ordinal,0);
        !           860: 
        !           861:     if ( ordinal >= pm_vars->theNumberOfPowerStates ) {
        !           862:         return IOPMParameterError;
        !           863:     }
        !           864:     priv->driverDesire = ordinal;
        !           865:     if ( pm_vars->myParent == NULL ) {
        !           866:         return IOPMNoErr;
        !           867:     }
        !           868:     return changeState();
        !           869: }
        !           870: 
        !           871: //*********************************************************************************
        !           872: // changeStateToPriv
        !           873: //
        !           874: // For some reason, a subclassed device object has decided it needs to change
        !           875: // power state.  We enqueue the power change so that appropriate parties
        !           876: // will be notified, and then we will instruct the driver to make the change.
        !           877: //*********************************************************************************
        !           878: 
        !           879: IOReturn IOService::changeStateToPriv ( unsigned long ordinal )
        !           880: {
        !           881:     pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogChangeStateToPriv,ordinal,0);
        !           882: 
        !           883:     if ( pm_vars->theControllingDriver == NULL) {
        !           884:         return IOPMNotYetInitialized;
        !           885:     }
        !           886:     if ( ordinal >= pm_vars->theNumberOfPowerStates ) {
        !           887:         return IOPMParameterError;
        !           888:     }
        !           889:     priv->deviceDesire = ordinal;
        !           890:     if ( pm_vars->myParent == NULL ) {
        !           891:         return IOPMNoErr;
        !           892:     }
        !           893:     return changeState();
        !           894: }
        !           895: 
        !           896: 
        !           897: //*********************************************************************************
        !           898: // changeState
        !           899: //
        !           900: // A subclass object, our controlling driver, or a power domain child
        !           901: // has asked for a different power state.  Here we compute what new
        !           902: // state we should enter and enqueue the change (or start it).
        !           903: //*********************************************************************************
        !           904: 
        !           905: IOReturn IOService::changeState ( void )
        !           906: {
        !           907:     unsigned long      newDesiredState = 0;
        !           908:     IOPMinformee * nextChild;
        !           909: 
        !           910:     // Compute the maximum  of our children's desires, our controlling driver's desire, and the subclass device's desire.
        !           911: 
        !           912:     if ( !  priv->device_overrides ) {
        !           913:         nextChild = priv->children->firstInList();
        !           914: 
        !           915:         while ( nextChild != NULL ) {
        !           916:             if ( (( IOPMpmChild *)nextChild)->desiredDomainState > newDesiredState ) {
        !           917:                 newDesiredState =(( IOPMpmChild *)nextChild)->desiredDomainState;
        !           918:             }
        !           919:             nextChild = priv->children->nextInList(nextChild);
        !           920:         }
        !           921:         if (  priv->driverDesire > newDesiredState ) {
        !           922:             newDesiredState =  priv->driverDesire;
        !           923:         }
        !           924:     }
        !           925: 
        !           926:     if ( priv->deviceDesire > newDesiredState ) {
        !           927:         newDesiredState = priv->deviceDesire;
        !           928:     }
        !           929: 
        !           930:     priv->ourDesiredPowerState = newDesiredState;
        !           931: 
        !           932:     return enqueuePowerChange(IOPMWeInitiated,newDesiredState,0);
        !           933: }
        !           934: 
        !           935: 
        !           936: //*********************************************************************************
        !           937: // currentPowerConsumption
        !           938: //
        !           939: //*********************************************************************************
        !           940: 
        !           941: unsigned long IOService::currentPowerConsumption ( void )
        !           942: {
        !           943:     if ( pm_vars->theControllingDriver == NULL ) {
        !           944:         return 0;
        !           945:     }
        !           946:     else {
        !           947:         return  pm_vars->thePowerStates[pm_vars->myCurrentState].staticPower;
        !           948:     }
        !           949: }
        !           950: 
        !           951: //*********************************************************************************
        !           952: // activityTickle
        !           953: //
        !           954: // The activity tickle with parameter kIOPMSubclassPolicyis not handled
        !           955: // here and should have been intercepted by the subclass.
        !           956: // The tickle with parameter kIOPMSuperclassPolicy1 causes the activity
        !           957: // flag to be set, and the device state checked.  If the device has been
        !           958: // powered down, it is powered up again.
        !           959: //*********************************************************************************
        !           960: 
        !           961: bool IOService::activityTickle ( unsigned long type, unsigned long stateNumber=0 )
        !           962: {
        !           963:     if ( type == kIOPMSuperclassPolicy1 ) {
        !           964:         if ( (priv->activityLock == NULL) ||
        !           965:              (pm_vars->theControllingDriver == NULL) ||
        !           966:              ( pm_vars->commandQueue == NULL) ) {
        !           967:             return true;
        !           968:         }
        !           969:         IOTakeLock(priv->activityLock);
        !           970:         priv->device_active = true;
        !           971:         if ( pm_vars->myCurrentState >= stateNumber) {
        !           972:             IOUnlock(priv->activityLock);
        !           973:             return true;
        !           974:         }
        !           975:         IOUnlock(priv->activityLock);                          // send a message on the command queue
        !           976:         pm_vars->commandQueue->enqueueCommand(true, (void *)kPMunIdleDevice, (void *)stateNumber);
        !           977:         return false;
        !           978:     }
        !           979:     return true;
        !           980: }
        !           981: 
        !           982: //*********************************************************************************
        !           983: // getPMworkloop
        !           984: //
        !           985: // A child is calling to get a pointer to the Power Management workloop.
        !           986: // We got it or get it from our parent.
        !           987: //*********************************************************************************
        !           988: 
        !           989: IOWorkLoop * IOService::getPMworkloop ( void )
        !           990: {
        !           991:     if ( pm_vars->myParent == NULL ) {
        !           992:         return NULL;
        !           993:     }
        !           994:     if ( pm_vars->PMworkloop == NULL ) {
        !           995:         pm_vars->PMworkloop =  pm_vars->myParent->getPMworkloop();
        !           996:     }
        !           997:     return  pm_vars->PMworkloop;
        !           998: }
        !           999: 
        !          1000: 
        !          1001: //*********************************************************************************
        !          1002: // setIdleTimerPeriod
        !          1003: //
        !          1004: // A subclass policy-maker is going to use our standard idleness
        !          1005: // detection service.  Make a command queue and an idle timer and
        !          1006: // connect them to the power management workloop.  Finally,
        !          1007: // start the timer.
        !          1008: //*********************************************************************************
        !          1009: 
        !          1010: IOReturn  IOService::setIdleTimerPeriod ( unsigned long period )
        !          1011: {
        !          1012:     pm_vars->thePlatform->PMLog(pm_vars->ourName,PMsetIdleTimerPeriod,period, 0);
        !          1013: 
        !          1014:     priv->idle_timer_period = period;
        !          1015: 
        !          1016:     if ( period > 0 ) {
        !          1017:         if ( getPMworkloop() == NULL ) {
        !          1018:             return kIOReturnError;
        !          1019:         }
        !          1020: 
        !          1021:         if (pm_vars->commandQueue == NULL ) {          // make the command queue
        !          1022:             pm_vars->commandQueue = IOCommandQueue::commandQueue(this, PMreceiveCmd);
        !          1023:             if (!  pm_vars->commandQueue ||
        !          1024:                 (  pm_vars->PMworkloop->addEventSource( pm_vars->commandQueue) != kIOReturnSuccess) ) {
        !          1025:                 return kIOReturnError;
        !          1026:             }
        !          1027:         }
        !          1028:                                                         // make the timer event
        !          1029:         if (  priv->timerEventSrc == NULL ) {
        !          1030:             priv->timerEventSrc = IOTimerEventSource::timerEventSource(this,
        !          1031:                                                     PM_idle_timer_expired);
        !          1032:             if ( !  priv->timerEventSrc ||
        !          1033:                  ( pm_vars->PMworkloop->addEventSource(  priv->timerEventSrc) != kIOReturnSuccess) ) {
        !          1034:                 return kIOReturnError;
        !          1035:             }
        !          1036:         }
        !          1037: 
        !          1038:         if ( priv->activityLock == NULL ) {
        !          1039:             priv->activityLock = IOLockAlloc();
        !          1040:         }
        !          1041: 
        !          1042:         start_PM_idle_timer();
        !          1043:     }
        !          1044:     return IOPMNoErr;
        !          1045: }
        !          1046: 
        !          1047: 
        !          1048: //*********************************************************************************
        !          1049: // start_PM_idle_timer
        !          1050: //
        !          1051: // The parameter is a pointer to us.  Use it to call our timeout method.
        !          1052: //*********************************************************************************
        !          1053: void IOService::start_PM_idle_timer ( void )
        !          1054: {
        !          1055:     priv->timerEventSrc->setTimeout(priv->idle_timer_period, NSEC_PER_SEC);
        !          1056: }
        !          1057: 
        !          1058: 
        !          1059: //*********************************************************************************
        !          1060: // PM_idle_timer_expired
        !          1061: //
        !          1062: // The parameter is a pointer to us.  Use it to call our timeout method.
        !          1063: //*********************************************************************************
        !          1064: 
        !          1065: void PM_idle_timer_expired(OSObject * ourSelves, IOTimerEventSource *)
        !          1066: {
        !          1067:    ((IOService *)ourSelves)->PM_idle_timer_expiration();
        !          1068: }
        !          1069: 
        !          1070: 
        !          1071: //*********************************************************************************
        !          1072: // PM_idle_timer_expiration
        !          1073: //
        !          1074: // The idle timer has expired.  If there has been activity since the last
        !          1075: // expiration, just restart the timer and return.  If there has not been
        !          1076: // activity, switch to the next lower power state and restart the timer.
        !          1077: //*********************************************************************************
        !          1078: 
        !          1079: void IOService::PM_idle_timer_expiration ( void )
        !          1080: {
        !          1081:     if (  priv->idle_timer_period > 0 ) {
        !          1082:         IOTakeLock(priv->activityLock);
        !          1083:         if ( priv->device_active ) {
        !          1084:             priv->device_active = false;
        !          1085:             IOUnlock(priv->activityLock);
        !          1086:             start_PM_idle_timer();
        !          1087:             return;
        !          1088:         }
        !          1089:         if (pm_vars->myCurrentState > 0 ) {
        !          1090:             IOUnlock(priv->activityLock);
        !          1091:             priv->askingFor = pm_vars->myCurrentState - 1;
        !          1092:             changeStateToPriv(pm_vars->myCurrentState - 1);
        !          1093:             start_PM_idle_timer();
        !          1094:             return;
        !          1095:         }
        !          1096:         IOUnlock(priv->activityLock);
        !          1097:         start_PM_idle_timer();
        !          1098:     }
        !          1099: }
        !          1100: 
        !          1101: 
        !          1102: 
        !          1103: // **********************************************************************************
        !          1104: // PMreceiveCmd
        !          1105: //
        !          1106: //
        !          1107: //
        !          1108: // **********************************************************************************
        !          1109: void PMreceiveCmd ( OSObject * theDriver,  void * command, void * param1, void * param2, void *param3 )
        !          1110: {
        !          1111:    ((IOService *)theDriver)->command_received(command,param1,param2,param3);
        !          1112: }
        !          1113: 
        !          1114: 
        !          1115: // **********************************************************************************
        !          1116: // command_received
        !          1117: //
        !          1118: // We have received a command from ourselves on the command queue.
        !          1119: // This is to prevent races with timer-expiration code.
        !          1120: // **********************************************************************************
        !          1121: void IOService::command_received ( void * command, void *stateNumber , void * , void *)
        !          1122: {
        !          1123:     if ( command == (void *)kPMunIdleDevice ) {
        !          1124:         if ((pm_vars->myCurrentState < (unsigned long)stateNumber) &&
        !          1125:             (priv->imminentState < (unsigned long)stateNumber ) &&
        !          1126:             ((unsigned long)stateNumber > priv->askingFor) ) {
        !          1127:             priv->askingFor = (unsigned long)stateNumber;
        !          1128:             changeStateToPriv((unsigned long)stateNumber);
        !          1129:         }
        !          1130:     }
        !          1131: }
        !          1132: 
        !          1133: 
        !          1134: //*********************************************************************************
        !          1135: // setAggressiveness
        !          1136: //
        !          1137: // Pass on the input parameters to all power domain children. All those which are
        !          1138: // power domains will pass it on to their children, etc.
        !          1139: //*********************************************************************************
        !          1140: 
        !          1141: IOReturn IOService::setAggressiveness ( unsigned long type, unsigned long newLevel )
        !          1142: {
        !          1143:     IOPMinformee * nextChild;
        !          1144: 
        !          1145:     pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogSetAggressiveness,type, newLevel);
        !          1146: 
        !          1147:     if ( type == kPMGeneralAggressiveness ) {
        !          1148:         pm_vars->aggressiveness = newLevel;
        !          1149:     }
        !          1150: 
        !          1151:     nextChild = priv->children->firstInList();
        !          1152: 
        !          1153:     while (  nextChild != NULL ) {
        !          1154:         nextChild->whatObject->setAggressiveness(type, newLevel);
        !          1155:         nextChild = priv->children->nextInList(nextChild);
        !          1156:     }
        !          1157: 
        !          1158:     return IOPMNoErr;
        !          1159: }
        !          1160: 
        !          1161: 
        !          1162: //*********************************************************************************
        !          1163: // systemWake
        !          1164: //
        !          1165: // Pass this to all power domain children. All those which are
        !          1166: // power domains will pass it on to their children, etc.
        !          1167: //*********************************************************************************
        !          1168: 
        !          1169: IOReturn IOService::systemWake ( void )
        !          1170: {
        !          1171:     IOPMinformee * nextChild;
        !          1172: 
        !          1173:     pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogSystemWake,0, 0);
        !          1174: 
        !          1175:     nextChild = priv->children->firstInList();
        !          1176: 
        !          1177:     while (  nextChild != NULL ) {
        !          1178:         nextChild->whatObject->systemWake();
        !          1179:         nextChild = priv->children->nextInList(nextChild);
        !          1180:     }
        !          1181: 
        !          1182:     return IOPMNoErr;
        !          1183: }
        !          1184: 
        !          1185: 
        !          1186: //*********************************************************************************
        !          1187: // temperatureCriticalForZone
        !          1188: //
        !          1189: //*********************************************************************************
        !          1190: 
        !          1191: IOReturn IOService::temperatureCriticalForZone ( IOService * whichZone )
        !          1192: {
        !          1193:     pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogCriticalTemp,0,0);
        !          1194: 
        !          1195:     if ( (pm_vars->myParent != NULL) &&
        !          1196:          ( !  priv->we_are_root) ) {
        !          1197:         pm_vars->myParent->temperatureCriticalForZone(whichZone);
        !          1198:     }
        !          1199:     return IOPMNoErr;
        !          1200: }
        !          1201: 
        !          1202: 
        !          1203: //*********************************************************************************
        !          1204: // overrideOnPriv
        !          1205: //
        !          1206: //*********************************************************************************
        !          1207: 
        !          1208: 
        !          1209: IOReturn IOService::overrideOnPriv ( void )
        !          1210: {
        !          1211:     pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogOverrideOn,0,0);
        !          1212: 
        !          1213:     priv->device_overrides = true;     // turn on the override
        !          1214:     return changeState();              // change state if that changed something
        !          1215: }
        !          1216: 
        !          1217: 
        !          1218: //*********************************************************************************
        !          1219: // overrideOffPriv
        !          1220: //
        !          1221: //*********************************************************************************
        !          1222: IOReturn IOService::overrideOffPriv ( void )
        !          1223: {
        !          1224:     pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogOverrideOff,0,0);
        !          1225: 
        !          1226:     priv->device_overrides = false;    // turn off the override
        !          1227:     return changeState();              // change state if that changed something
        !          1228: }
        !          1229: 
        !          1230: 
        !          1231: //*********************************************************************************
        !          1232: // enqueuePowerChange
        !          1233: //
        !          1234: // Allocate a new state change notification, initialize it with fields from the
        !          1235: // caller, and add it to the tail of the list of pending power changes.
        !          1236: //
        !          1237: // If it is early enough in the list, and almost all the time it is the only one in
        !          1238: // the list, start the power change.
        !          1239: //
        !          1240: // In rare instances, this change will preempt the previous change in the list.
        !          1241: // If the previous change is un-actioned in any way (because we are still
        !          1242: // processing an even earlier power change), and if both the previous change
        !          1243: // in the list and this change are initiated by us (not the parent), then we
        !          1244: // needn't perform the previous change, so we collapse the list a little.
        !          1245: //*********************************************************************************
        !          1246: 
        !          1247: IOReturn IOService::enqueuePowerChange ( unsigned long flags,  unsigned long whatStateOrdinal, unsigned long domainState )
        !          1248: {
        !          1249:     long       newNote;
        !          1250:     long       previousNote;
        !          1251: 
        !          1252: // Create and initialize the new change note
        !          1253: 
        !          1254:     newNote = priv->changeList->createChangeNote();
        !          1255:     if ( newNote == -1 ) {
        !          1256:         pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogEnqueueErr,0,0);
        !          1257:         return IOPMAckImplied;                 // uh-oh, our list is full
        !          1258:     }
        !          1259: 
        !          1260:     priv->changeList->changeNote[newNote].newStateNumber = whatStateOrdinal;
        !          1261:     priv->changeList->changeNote[newNote].outputPowerCharacter =  pm_vars->thePowerStates[whatStateOrdinal].outputPowerCharacter;
        !          1262:     priv->changeList->changeNote[newNote].inputPowerRequirement =  pm_vars->thePowerStates[whatStateOrdinal].inputPowerRequirement;
        !          1263:     priv->changeList->changeNote[newNote].capabilityFlags =  pm_vars->thePowerStates[whatStateOrdinal].capabilityFlags;
        !          1264:     priv->changeList->changeNote[newNote].flags = flags;
        !          1265:     if (flags & IOPMParentInitiated ) {
        !          1266:         priv->changeList->changeNote[newNote].domainState =  domainState;
        !          1267:     }
        !          1268: 
        !          1269:     previousNote = priv->changeList->previousChangeNote(newNote);
        !          1270: 
        !          1271:     if ( previousNote == -1 ) {
        !          1272: 
        !          1273:         // Queue is empty, we can start this change.
        !          1274: 
        !          1275:         if (flags & IOPMWeInitiated ) {
        !          1276:             start_our_change(newNote);
        !          1277:             return 0;
        !          1278:         }
        !          1279:         else {
        !          1280:             return start_parent_change(newNote);
        !          1281:         }
        !          1282:     }
        !          1283: 
        !          1284:     // The queue is not empty.  Try to collapse this new change and the previous one in queue into one change.
        !          1285:     // This is possible only if both changes are initiated by us, and neither has been started yet.
        !          1286:     // Do this more than once if possible.
        !          1287: 
        !          1288:     // (A change is started iff it is at the head of the queue)
        !          1289: 
        !          1290:     while ( (previousNote != priv->head_note) &&  (previousNote != -1) &&
        !          1291:             (priv->changeList->changeNote[newNote].flags &  priv->changeList->changeNote[previousNote].flags &  IOPMWeInitiated)  ) {
        !          1292:         priv->changeList->changeNote[previousNote].outputPowerCharacter = priv->changeList->changeNote[newNote].outputPowerCharacter;
        !          1293:         priv->changeList->changeNote[previousNote].inputPowerRequirement = priv->changeList->changeNote[newNote].inputPowerRequirement;
        !          1294:         priv->changeList->changeNote[previousNote].capabilityFlags =priv-> changeList->changeNote[newNote].capabilityFlags;
        !          1295:         priv->changeList->changeNote[previousNote].newStateNumber = priv->changeList->changeNote[newNote].newStateNumber;
        !          1296:         priv->changeList->releaseTailChangeNote();
        !          1297:         newNote = previousNote;
        !          1298:         previousNote = priv->changeList->previousChangeNote(newNote);
        !          1299:         pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogCollapseQueue,0,0);
        !          1300:     }
        !          1301:     return IOPMWillAckLater;                           // in any case, we can't start yet
        !          1302: }
        !          1303: 
        !          1304: 
        !          1305: //*********************************************************************************
        !          1306: // notifyAll
        !          1307: //
        !          1308: // Notify all interested parties either that a change is impending or that the
        !          1309: // previously-notified change is done and power has settled.
        !          1310: // The parameter identifies whether this is the
        !          1311: // pre-change notification or the post-change notification.
        !          1312: //
        !          1313: //*********************************************************************************
        !          1314: 
        !          1315: IOReturn IOService::notifyAll ( bool is_prechange )
        !          1316: {
        !          1317:     IOPMinformee *     nextObject;
        !          1318:     bool               start_timer = false;
        !          1319: 
        !          1320:     // To prevent acknowledgePowerChange from finishing the change note and removing it from the queue if
        !          1321:     // some driver calls it, we inflate the number of pending acks so it cannot become zero.  We'll fix it later.
        !          1322: 
        !          1323:     priv->head_note_pendingAcks = priv->numberOfInformees + 1;
        !          1324: 
        !          1325:     // OK, we will go through the lists of interested drivers and power domain children
        !          1326:     // and notify each one of this change.
        !          1327: 
        !          1328:     nextObject =  priv->interestedDrivers->firstInList();              // notify interested drivers
        !          1329:     while (  nextObject != NULL ) {
        !          1330:         if (! notifyObject( nextObject, is_prechange, false) ) {
        !          1331:             start_timer = true;
        !          1332:         }
        !          1333:         nextObject  =  priv->interestedDrivers->nextInList(nextObject);
        !          1334:     }
        !          1335:     if ( start_timer ) {                                       // start ack timer if any drivers didn't ack
        !          1336:         pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogStartAckTimer,0,0);
        !          1337:         start_ack_timer();
        !          1338:     }
        !          1339: 
        !          1340:     nextObject = priv->children->firstInList();                        // notify power domain children
        !          1341:     while (  nextObject != NULL ) {
        !          1342:         notifyObject(nextObject, is_prechange, true);
        !          1343:         nextObject  = priv->children->nextInList(nextObject);
        !          1344:     }
        !          1345: 
        !          1346:     priv->head_note_pendingAcks -= 1;                          // fix this
        !          1347:     if (priv->head_note_pendingAcks == 0 ) {                   // is it all acked?
        !          1348:         return IOPMAckImplied;                         // return ack to parent
        !          1349:     }
        !          1350:     return IOPMWillAckLater;
        !          1351: }
        !          1352: 
        !          1353: 
        !          1354: //*********************************************************************************
        !          1355: // notifyObject
        !          1356: //
        !          1357: // Notify an interested driver or a power domain child of an upcoming
        !          1358: // power change.
        !          1359: //
        !          1360: // If the object acknowledges the current change, we return TRUE.
        !          1361: //*********************************************************************************
        !          1362: 
        !          1363: bool IOService::notifyObject ( IOPMinformee * nextObject, bool is_prechange, bool is_child )
        !          1364: {
        !          1365:     IOReturn k = IOPMAckImplied;
        !          1366: 
        !          1367:    nextObject->timer = -1;                                     // initialize this
        !          1368: 
        !          1369:    if ( is_prechange ) {
        !          1370:        if ( is_child ) {
        !          1371:            k =nextObject->whatObject->powerDomainWillChangeTo( priv->head_note_outputFlags);
        !          1372:        }
        !          1373:        else {
        !          1374:            pm_vars->thePlatform->PMLog (pm_vars->ourName,PMlogInformDriverPreChange,
        !          1375:                                    (unsigned long)priv->head_note_capabilityFlags,(unsigned long)priv->head_note_state);
        !          1376:            k = nextObject->whatObject->powerStateWillChangeTo( priv->head_note_capabilityFlags,priv->head_note_state,this);
        !          1377:        }
        !          1378:    }
        !          1379:    else {
        !          1380:        if ( is_child ) {
        !          1381:            k = nextObject->whatObject->powerDomainDidChangeTo(priv->head_note_outputFlags);
        !          1382:        }
        !          1383:        else {
        !          1384:            pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogInformDriverPostChange,
        !          1385:                                   (unsigned long)priv->head_note_capabilityFlags,(unsigned long)priv->head_note_state);
        !          1386:            k = nextObject->whatObject->powerStateDidChangeTo(priv->head_note_capabilityFlags,priv->head_note_state,this);
        !          1387:        }
        !          1388:    }
        !          1389: 
        !          1390:    if ( nextObject->timer == 0 ) {                             // did it ack behind our back?
        !          1391:        return true;                                            // yes
        !          1392:    }
        !          1393:    if ( k ==IOPMAckImplied ) {                         // no, did the return code ack?
        !          1394:        nextObject->timer = 0;                                  // yes
        !          1395:        priv->head_note_pendingAcks -= 1;
        !          1396:        return true;
        !          1397:    }
        !          1398:    if ( k < 0 ) {
        !          1399:        nextObject->timer = 0;                                  // somebody goofed
        !          1400:        priv-> head_note_pendingAcks -= 1;
        !          1401:        return true;
        !          1402:   }
        !          1403:    nextObject->timer = (k * ns_per_us / ACK_TIMER_PERIOD) + 1; // no, it's a timer
        !          1404:    return false;
        !          1405: }
        !          1406: 
        !          1407: 
        !          1408: //*********************************************************************************
        !          1409: // our_prechange_1
        !          1410: //
        !          1411: // All parties have acknowledged our pre-change notification of a power
        !          1412: // change we initiated.  Here we instruct our controlling driver to make
        !          1413: // the change to the hardware.  If it does so, we continue processing
        !          1414: // (waiting for settle and notifying interested parties post-change.)
        !          1415: // If it doesn't, we have to wait for it to acknowledge and then continue.
        !          1416: //*********************************************************************************
        !          1417: 
        !          1418: void IOService::our_prechange_1 ( void )
        !          1419: {
        !          1420:     if ( instruct_driver(priv->head_note_state) == IOPMAckImplied ) {
        !          1421:         our_prechange_2();                                     // it's done, carry on
        !          1422:     }
        !          1423:     else {
        !          1424:         priv->machine_state = IOPMour_prechange_2;             // it's not, wait for it
        !          1425:         pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogStartAckTimer,0,0);
        !          1426:         start_ack_timer();
        !          1427:     }
        !          1428: }
        !          1429: 
        !          1430: 
        !          1431: //*********************************************************************************
        !          1432: // our_prechange_2
        !          1433: //
        !          1434: // Our controlling driver has changed power state on the hardware
        !          1435: // during a power change we initiated.  Here we see if we need to wait
        !          1436: // for power to settle before continuing.  If not, we continue processing
        !          1437: // (notifying interested parties post-change).  If so, we wait and
        !          1438: // continue later.
        !          1439: //*********************************************************************************
        !          1440: 
        !          1441: void IOService::our_prechange_2 ( void )
        !          1442: {
        !          1443:     priv->settle_time = compute_settle_time();
        !          1444:     if ( priv->settle_time == 0 ) {
        !          1445:        our_prechange_3();
        !          1446:     }
        !          1447:     else {
        !          1448:         priv->machine_state = IOPMour_prechange_3;
        !          1449:         startSettleTimer(priv->settle_time);
        !          1450:     }
        !          1451: }
        !          1452: 
        !          1453: 
        !          1454: //*********************************************************************************
        !          1455: // our_prechange_3
        !          1456: //
        !          1457: // Power has settled on a power change we initiated.  Here we notify
        !          1458: // all our interested parties post-change.  If they all acknowledge, we're
        !          1459: // done with this change note, and we can start on the next one.
        !          1460: // Otherwise we have to wait for acknowledgements and finish up later.
        !          1461: //*********************************************************************************
        !          1462: 
        !          1463: void IOService::our_prechange_3 ( void )
        !          1464: {
        !          1465:     priv->machine_state = IOPMour_prechange_4;         // in case they don't all ack
        !          1466:     if ( notifyAll(false) == IOPMAckImplied ) {
        !          1467:         our_prechange_4();
        !          1468:     }
        !          1469: }
        !          1470: 
        !          1471: 
        !          1472: //*********************************************************************************
        !          1473: // our_prechange_4
        !          1474: //
        !          1475: // Power has settled on a power change we initiated, and
        !          1476: // all our interested parties have acknowledged.  We're
        !          1477: // done with this change note, and we can start on the next one.
        !          1478: //*********************************************************************************
        !          1479: 
        !          1480: void IOService::our_prechange_4 ( void )
        !          1481: {
        !          1482:     all_done();
        !          1483: }
        !          1484: 
        !          1485: 
        !          1486: //*********************************************************************************
        !          1487: // parent_prechange_down_1
        !          1488: //
        !          1489: // All parties have acknowledged our pre-change notification of a power
        !          1490: // lowering initiated by the parent.  Here we instruct our controlling driver
        !          1491: // to put the hardware in the state it needs to be in when the domain is
        !          1492: // lowered.  If it does so, we continue processing
        !          1493: // (waiting for settle and acknowledging the parent.)
        !          1494: // If it doesn't, we have to wait for it to acknowledge and then continue.
        !          1495: //*********************************************************************************
        !          1496: 
        !          1497: IOReturn IOService::parent_prechange_down_1 ( void )
        !          1498: {
        !          1499:     if ( instruct_driver(priv->head_note_state) == IOPMAckImplied ) {
        !          1500:         return parent_prechange_down_2();                      // it's done, carry on
        !          1501:     }
        !          1502:     priv->machine_state = IOPMparent_prechange_down_5; // it's not, wait for it
        !          1503:     pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogStartAckTimer,0,0);
        !          1504:     start_ack_timer();
        !          1505:     return IOPMWillAckLater;
        !          1506: }
        !          1507: 
        !          1508: 
        !          1509: //*********************************************************************************
        !          1510: // parent_prechange_down_4
        !          1511: //
        !          1512: // We had to wait for it, but all parties have acknowledged our pre-change
        !          1513: // notification of a power lowering initiated by the parent.
        !          1514: // Here we instruct our controlling driver
        !          1515: // to put the hardware in the state it needs to be in when the domain is
        !          1516: // lowered.  If it does so, we continue processing
        !          1517: // (waiting for settle and acknowledging the parent.)
        !          1518: // If it doesn't, we have to wait for it to acknowledge and then continue.
        !          1519: //*********************************************************************************
        !          1520: 
        !          1521: void IOService::parent_prechange_down_4 ( void )
        !          1522: {
        !          1523:     if ( instruct_driver(priv->head_note_state) == IOPMAckImplied ) {
        !          1524:         parent_prechange_down_5();                             // it's done, carry on
        !          1525:     }
        !          1526:     else {
        !          1527:         priv-> machine_state = IOPMparent_prechange_down_5;    // it's not, wait for it
        !          1528:         pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogStartAckTimer,0,0);
        !          1529:         start_ack_timer();
        !          1530:     }
        !          1531: }
        !          1532: 
        !          1533: 
        !          1534: //*********************************************************************************
        !          1535: // parent_prechange_down_2
        !          1536: //
        !          1537: // Our controlling driver has changed power state on the hardware
        !          1538: // during a power change initiated by our parent.  Here we see if we need
        !          1539: // to wait for power to settle before continuing.  If not, we continue
        !          1540: // processing (acknowledging our preparedness to the parent).
        !          1541: // If so, we wait and continue later.
        !          1542: //*********************************************************************************
        !          1543: 
        !          1544: IOReturn IOService::parent_prechange_down_2 ( void )
        !          1545: {
        !          1546:     priv->settle_time = compute_settle_time();
        !          1547:     if ( priv->settle_time == 0 ) {
        !          1548:        priv->machine_state = IOPMparent_postchange_down_1;
        !          1549:        return IOPMAckImplied;
        !          1550:    }
        !          1551:    else {
        !          1552:        priv->machine_state = IOPMparent_prechange_down_3;
        !          1553:        startSettleTimer(priv->settle_time);
        !          1554:        return IOPMWillAckLater;
        !          1555:    }
        !          1556: }
        !          1557: 
        !          1558: 
        !          1559: //*********************************************************************************
        !          1560: // parent_prechange_down_5
        !          1561: //
        !          1562: // Our controlling driver has changed power state on the hardware
        !          1563: // during a power change initiated by our parent.  We have had to wait
        !          1564: // for acknowledgement from interested parties, or we have had to wait
        !          1565: // for the controlling driver to change the state.  Here we see if we need
        !          1566: // to wait for power to settle before continuing.  If not, we continue
        !          1567: // processing (acknowledging our preparedness to the parent).
        !          1568: // If so, we wait and continue later.
        !          1569: //*********************************************************************************
        !          1570: 
        !          1571: void IOService::parent_prechange_down_5 ( void )
        !          1572: {
        !          1573:     priv->settle_time = compute_settle_time();
        !          1574:     if ( priv->settle_time == 0 ) {
        !          1575:       parent_prechange_down_3();
        !          1576:    }
        !          1577:    else {
        !          1578:        priv->machine_state = IOPMparent_prechange_down_3;
        !          1579:        startSettleTimer(priv->settle_time);
        !          1580:    }
        !          1581: }
        !          1582: 
        !          1583: 
        !          1584: //*********************************************************************************
        !          1585: // parent_prechange_down_3
        !          1586: //
        !          1587: // Power has settled on a power change initiated by our parent.  Here we
        !          1588: // acknowledge the parent.  There is nothing more to do until the
        !          1589: // parent lowers power in the domain and calls us at powerStateDidChange.
        !          1590: //*********************************************************************************
        !          1591: 
        !          1592: void IOService::parent_prechange_down_3 ( void )
        !          1593: {
        !          1594:     priv->machine_state = IOPMparent_postchange_down_1;
        !          1595:     pm_vars->myParent->acknowledgePowerChange(this);
        !          1596: }
        !          1597: 
        !          1598: 
        !          1599: //*********************************************************************************
        !          1600: // parent_prechange_up_1
        !          1601: //
        !          1602: // All parties have acknowledged our pre-change notification of a power
        !          1603: // raising initiated by the parent.  Here we acknowledge the parent.
        !          1604: // There is nothing more to do until the parent raises power in the domain
        !          1605: // and calls us at powerStateDidChange.
        !          1606: //*********************************************************************************
        !          1607: 
        !          1608: void IOService::parent_prechange_up_1 ( void )
        !          1609: {
        !          1610:     priv->machine_state = IOPMparent_postchange_up_1;
        !          1611:     pm_vars->myParent->acknowledgePowerChange(this);
        !          1612: }
        !          1613: 
        !          1614: 
        !          1615: //*********************************************************************************
        !          1616: // parent_postchange_down_1
        !          1617: //
        !          1618: // Our parent is lowering power, and has called us at powerStateDidChange
        !          1619: // to tell us the domain power has now settled in the new lower state.
        !          1620: // We notify our interested parties.  When they have all acked, we're done
        !          1621: //*********************************************************************************
        !          1622: 
        !          1623: IOReturn IOService::parent_postchange_down_1 ( void )
        !          1624: {
        !          1625:     priv->machine_state = IOPMparent_postchange_down_2;        // in case they don't all ack
        !          1626:     if ( notifyAll(false) == IOPMAckImplied ) {
        !          1627:         all_done();
        !          1628:         return IOPMAckImplied;
        !          1629:     }
        !          1630:     return IOPMWillAckLater;                   // they didn't
        !          1631: }
        !          1632: 
        !          1633: 
        !          1634: //*********************************************************************************
        !          1635: // parent_postchange_down_2
        !          1636: //
        !          1637: // We had to wait for it, but all parties have acknowledged our post-change
        !          1638: // notification of a power  lowering initiated by the parent.
        !          1639: // Here we acknowledge the parent.
        !          1640: // We are done with this change note, and we can start on the next one.
        !          1641: //*********************************************************************************
        !          1642: 
        !          1643: void IOService::parent_postchange_down_2 ( void )
        !          1644: {
        !          1645:     all_done();
        !          1646:     pm_vars->myParent->acknowledgePowerChange(this);
        !          1647: }
        !          1648: 
        !          1649: 
        !          1650: //*********************************************************************************
        !          1651: // parent_postchange_up_1
        !          1652: //
        !          1653: // Our parent has informed us via powerStateDidChange that it has
        !          1654: // raised the power in our power domain.  Here we instruct our controlling
        !          1655: // driver to program the hardware to take advantage of the higher domain
        !          1656: // power.  If it does so, we continue processing
        !          1657: // (waiting for settle and notifying interested parties post-change.)
        !          1658: // If it doesn't, we have to wait for it to acknowledge and then continue.
        !          1659: //*********************************************************************************
        !          1660: 
        !          1661: IOReturn IOService::parent_postchange_up_1 ( void )
        !          1662: {
        !          1663:     if ( instruct_driver(priv->head_note_state) == IOPMAckImplied ) {
        !          1664:         return parent_postchange_up_2();                       // it did it, carry on
        !          1665:     }
        !          1666:     else {
        !          1667:         priv->machine_state = IOPMparent_postchange_up_4;      // it didn't, wait for it
        !          1668:         pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogStartAckTimer,0,0);
        !          1669:         start_ack_timer();
        !          1670:         return IOPMWillAckLater;
        !          1671:     }
        !          1672: }
        !          1673: 
        !          1674: 
        !          1675: //*********************************************************************************
        !          1676: // parent_postchange_up_2
        !          1677: //
        !          1678: // Our controlling driver has changed power state on the hardware
        !          1679: // during a power raise initiated by the parent.  Here we see if we need to wait
        !          1680: // for power to settle before continuing.  If not, we continue processing
        !          1681: // (notifying interested parties post-change).  If so, we wait and
        !          1682: // continue later.
        !          1683: //*********************************************************************************
        !          1684: 
        !          1685: IOReturn IOService::parent_postchange_up_2 ( void )
        !          1686: {
        !          1687:     priv->settle_time = compute_settle_time();
        !          1688:     if ( priv->settle_time == 0 ) {
        !          1689:       return parent_postchange_up_3();
        !          1690:   }
        !          1691:   else {
        !          1692:       priv->machine_state = IOPMparent_postchange_up_5;
        !          1693:       startSettleTimer(priv->settle_time);
        !          1694:       return IOPMWillAckLater;
        !          1695:   }
        !          1696: }
        !          1697: 
        !          1698: 
        !          1699: //*********************************************************************************
        !          1700: // parent_postchange_up_4
        !          1701: //
        !          1702: // Our controlling driver has changed power state on the hardware
        !          1703: // during a power raise initiated by the parent, but we had to wait for it.
        !          1704: // Here we see if we need to wait for power to settle before continuing.
        !          1705: // If not, we continue processing  (notifying interested parties post-change).
        !          1706: // If so, we wait and continue later.
        !          1707: //*********************************************************************************
        !          1708: 
        !          1709: void IOService::parent_postchange_up_4 ( void )
        !          1710: {
        !          1711:     priv->settle_time = compute_settle_time();
        !          1712:     if ( priv->settle_time == 0 ) {
        !          1713:      parent_postchange_up_5();
        !          1714:   }
        !          1715:   else {
        !          1716:       priv->machine_state = IOPMparent_postchange_up_5;
        !          1717:       startSettleTimer(priv->settle_time);
        !          1718:   }
        !          1719: }
        !          1720: 
        !          1721: 
        !          1722: //*********************************************************************************
        !          1723: // parent_postchange_up_3
        !          1724: //
        !          1725: // No power settling was required on a power raise initiated by the parent.
        !          1726: // Here we notify all our interested parties post-change.  If they all acknowledge,
        !          1727: // we're done with this change note, and we can start on the next one.
        !          1728: // Otherwise we have to wait for acknowledgements and finish up later.
        !          1729: //*********************************************************************************
        !          1730: 
        !          1731: IOReturn IOService::parent_postchange_up_3 ( void )
        !          1732: {
        !          1733:     priv->machine_state = IOPMparent_postchange_up_6;  // in case they don't all ack
        !          1734:     if ( notifyAll(false) == IOPMAckImplied ) {
        !          1735:         all_done();
        !          1736:         return IOPMAckImplied;
        !          1737:     }
        !          1738:     return IOPMWillAckLater;                   // they didn't
        !          1739: }
        !          1740: 
        !          1741: 
        !          1742: //*********************************************************************************
        !          1743: // parent_postchange_up_5
        !          1744: //
        !          1745: // Power has settled on a power raise initiated by the parent.
        !          1746: // Here we notify all our interested parties post-change.  If they all acknowledge,
        !          1747: // we're done with this change note, and we can start on the next one.
        !          1748: // Otherwise we have to wait for acknowledgements and finish up later.
        !          1749: //*********************************************************************************
        !          1750: 
        !          1751: void IOService::parent_postchange_up_5 ( void )
        !          1752: {
        !          1753:     priv->machine_state = IOPMparent_postchange_up_6;  // in case they don't all ack
        !          1754:     if ( notifyAll(false) == IOPMAckImplied ) {
        !          1755:         parent_postchange_up_6();
        !          1756:     }
        !          1757: }
        !          1758: 
        !          1759: 
        !          1760: //*********************************************************************************
        !          1761: // parent_postchange_up_6
        !          1762: //
        !          1763: // All parties have acknowledged our post-change notification of a power
        !          1764: // raising initiated by the parent.  Here we acknowledge the parent.
        !          1765: // We are done with this change note, and we can start on the next one.
        !          1766: //*********************************************************************************
        !          1767: 
        !          1768: void IOService::parent_postchange_up_6 ( void )
        !          1769: {
        !          1770:     all_done();
        !          1771:     pm_vars->myParent->acknowledgePowerChange(this);
        !          1772: }
        !          1773: 
        !          1774: 
        !          1775: //*********************************************************************************
        !          1776: // all_done
        !          1777: //
        !          1778: // A power change is complete, and the used post-change note is at
        !          1779: // the head of the queue.  Remove it and set myCurrentState to the result
        !          1780: // of the change.  Start up the next change in queue.
        !          1781: //*********************************************************************************
        !          1782: 
        !          1783: void IOService::all_done ( void )
        !          1784: {
        !          1785:     priv->machine_state = IOPMfinished;
        !          1786: 
        !          1787:     if ( priv->head_note_flags & IOPMWeInitiated ) {
        !          1788:         if ( !( priv->head_note_flags & IOPMNotDone) ) {                               // could our driver switch to the new state?
        !          1789:             pm_vars->myCurrentState = priv-> head_note_state;                  // yes
        !          1790:             pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogChangeDone,(unsigned long)pm_vars->myCurrentState,0);
        !          1791:         }
        !          1792:         else {                                                         // no
        !          1793:             pm_vars->myCurrentState = pm_vars->theControllingDriver->powerStateForDomainState(pm_vars->parentCurrentPowerFlags);
        !          1794:         }
        !          1795:     }
        !          1796:     if ( priv->head_note_flags & IOPMParentInitiated ) {
        !          1797:         pm_vars->myCurrentState = priv->head_note_state;
        !          1798:         pm_vars->maxCapability = pm_vars->theControllingDriver->maxCapabilityForDomainState(priv->head_note_domainState);
        !          1799:         pm_vars->parentCurrentPowerFlags = priv->head_note_domainState;
        !          1800:         pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogChangeDone,(unsigned long)pm_vars->myCurrentState,0);
        !          1801:     }
        !          1802: 
        !          1803:     priv->changeList->releaseHeadChangeNote();                                 // either way, we're done with this
        !          1804: 
        !          1805:     priv->head_note = priv->changeList->currentChange();                               // start next one in queue
        !          1806:     if ( priv->head_note != -1 ) {
        !          1807: 
        !          1808:         if (priv->changeList->changeNote[priv->head_note].flags & IOPMWeInitiated ) {
        !          1809:             start_our_change(priv->head_note);
        !          1810:         }
        !          1811:         else {
        !          1812:             if ( start_parent_change(priv->head_note) == IOPMAckImplied ) {
        !          1813:                 pm_vars->myParent->acknowledgePowerChange(this);
        !          1814:             }
        !          1815:         }
        !          1816:     }
        !          1817: }
        !          1818: 
        !          1819: 
        !          1820: 
        !          1821: //*********************************************************************************
        !          1822: // all_acked
        !          1823: //
        !          1824: // A driver or child has acknowledged our notification of an upcoming power
        !          1825: // change, and this acknowledgement is the last one pending
        !          1826: // before we change power or after changing power.
        !          1827: //
        !          1828: //*********************************************************************************
        !          1829: 
        !          1830: void IOService::all_acked ( void )
        !          1831: {
        !          1832:     switch (priv->machine_state) {
        !          1833:        case IOPMour_prechange_1:
        !          1834:            our_prechange_1();
        !          1835:            break;
        !          1836:        case IOPMour_prechange_4:
        !          1837:            our_prechange_4();
        !          1838:            break;
        !          1839:        case IOPMparent_prechange_down_4:
        !          1840:            parent_prechange_down_4();  
        !          1841:            break;
        !          1842:        case IOPMparent_postchange_down_2:
        !          1843:            parent_postchange_down_2();
        !          1844:            break;
        !          1845:        case IOPMparent_prechange_up_1:
        !          1846:            parent_prechange_up_1();
        !          1847:            break;
        !          1848:        case IOPMparent_postchange_up_6:
        !          1849:            parent_postchange_up_6();
        !          1850:            break;
        !          1851:    }
        !          1852: }
        !          1853: 
        !          1854: 
        !          1855: //*********************************************************************************
        !          1856: // settleTimerExpired
        !          1857: //
        !          1858: // Power has settled after our last change.  Notify interested parties that
        !          1859: // there is a new power state.
        !          1860: //*********************************************************************************
        !          1861: 
        !          1862: void IOService::settleTimerExpired ( void )
        !          1863: {
        !          1864:     switch (priv->machine_state) {
        !          1865:         case IOPMour_prechange_3:
        !          1866:             our_prechange_3();
        !          1867:             break;
        !          1868:         case IOPMparent_prechange_down_3:
        !          1869:             parent_prechange_down_3();
        !          1870:             break;
        !          1871:         case IOPMparent_postchange_up_5:
        !          1872:             parent_postchange_up_5();
        !          1873:             break;
        !          1874:     }
        !          1875: }
        !          1876: 
        !          1877: 
        !          1878: //*********************************************************************************
        !          1879: // compute_settle_time
        !          1880: //
        !          1881: // Compute the power-settling delay in microseconds for the
        !          1882: // change from myCurrentState to head_note_state.
        !          1883: //*********************************************************************************
        !          1884: 
        !          1885: unsigned long IOService::compute_settle_time ( void )
        !          1886: {
        !          1887:     unsigned long totalTime;
        !          1888:     unsigned long i;
        !          1889: 
        !          1890:     totalTime = 0;                                             // compute total time to attain the new state
        !          1891:     i = pm_vars->myCurrentState;
        !          1892:     if ( priv->head_note_state < pm_vars->myCurrentState ) {   // we're lowering power
        !          1893:         while ( i > priv->head_note_state ) {
        !          1894:             totalTime +=  pm_vars->thePowerStates[i].settleDownTime;
        !          1895:             i--;
        !          1896:         }
        !          1897:     }
        !          1898: 
        !          1899:     if ( priv->head_note_state > pm_vars->myCurrentState ) {   // we're raising power
        !          1900:         while ( i < priv->head_note_state ) {
        !          1901:             totalTime +=  pm_vars->thePowerStates[i+1].settleUpTime;
        !          1902:             i++;
        !          1903:         }
        !          1904:     }
        !          1905: 
        !          1906:     return totalTime;
        !          1907: }
        !          1908: 
        !          1909: 
        !          1910: //*********************************************************************************
        !          1911: // startSettleTimer
        !          1912: //
        !          1913: // Enter with a power-settling delay in microseconds and start a nano-second
        !          1914: // timer for that delay.
        !          1915: //*********************************************************************************
        !          1916: 
        !          1917: IOReturn IOService::startSettleTimer ( unsigned long delay )
        !          1918: {
        !          1919:     AbsoluteTime       deadline;
        !          1920:     
        !          1921:     clock_interval_to_deadline(delay, kMicrosecondScale, &deadline);
        !          1922:     thread_call_func_delayed(settle_timer_expired, (void *)this, deadline);
        !          1923:     return IOPMNoErr;
        !          1924: }
        !          1925: 
        !          1926: //*********************************************************************************
        !          1927: // ack_timer_ticked
        !          1928: //
        !          1929: // The acknowledgement timeout periodic timer has ticked.
        !          1930: // If we are awaiting acks for a power change notification,
        !          1931: // we decrement the timer word of each interested driver which hasn't acked.
        !          1932: // If a timer word becomes zero, we pretend the driver aknowledged.
        !          1933: // If we are waiting for the controlling driver to change the power
        !          1934: // state of the hardware, we decrement its timer word, and if it becomes
        !          1935: // zero, we pretend the driver acknowledged.
        !          1936: //*********************************************************************************
        !          1937: 
        !          1938: void IOService::ack_timer_ticked ( void )
        !          1939: {
        !          1940:     IOPMinformee * nextObject;
        !          1941: 
        !          1942:     if (! acquire_lock() ) {
        !          1943:         return;
        !          1944:     }
        !          1945: 
        !          1946:     if ( priv->driver_timer != 0 ) {                                   // are we waiting for our driver to make its change?
        !          1947:         priv->driver_timer -= 1;                                               // yes, tick once
        !          1948:         if ( priv->driver_timer == 0 ) {                                       // it's tardy, we'll go on without it
        !          1949:             IOUnlock(priv->our_lock);
        !          1950:             pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogCtrlDriverTardy,0,0);
        !          1951:             driver_acked();
        !          1952:         }
        !          1953:         else {                                                 // still waiting, set timer again
        !          1954:             start_ack_timer();
        !          1955:             IOUnlock(priv->our_lock);
        !          1956:         }
        !          1957:         return;
        !          1958:     }
        !          1959: 
        !          1960:     if (priv->head_note_pendingAcks != 0 ) {                           // are we waiting for interested parties to acknowledge?
        !          1961:         nextObject =  priv->interestedDrivers->firstInList();          // yes, go through the list of interested drivers
        !          1962:         while (  nextObject != NULL ) {                                        // and check each one
        !          1963:             if ( nextObject->timer > 0 ) {
        !          1964:                 nextObject->timer -= 1;
        !          1965:                 if ( nextObject->timer == 0 ) {                                // this one should have acked by now
        !          1966:                     pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogIntDriverTardy,0,0);
        !          1967:                     priv->head_note_pendingAcks -= 1;
        !          1968:                 }
        !          1969:             }
        !          1970:             nextObject  =  priv->interestedDrivers->nextInList(nextObject);
        !          1971:         }
        !          1972:         if ( priv->head_note_pendingAcks == 0 ) {                      // is that the last?
        !          1973:             IOUnlock(priv->our_lock);
        !          1974:             all_acked();                                                       // yes, we can continue
        !          1975:         }
        !          1976:         else {                                                         // no, set timer again
        !          1977:             start_ack_timer();
        !          1978:             IOUnlock(priv->our_lock);
        !          1979:         }
        !          1980:         return;
        !          1981:     }
        !          1982:     IOUnlock(priv->our_lock);                                          // not waiting for acks
        !          1983: }
        !          1984: 
        !          1985: 
        !          1986: //*********************************************************************************
        !          1987: // start_ack_timer
        !          1988: //
        !          1989: //*********************************************************************************
        !          1990: 
        !          1991: void IOService::start_ack_timer ( void )
        !          1992: {
        !          1993:     AbsoluteTime       deadline;
        !          1994: 
        !          1995:     clock_interval_to_deadline(ACK_TIMER_PERIOD, kNanosecondScale, &deadline);
        !          1996:     thread_call_func_delayed(ack_timer_expired, (void *)this, deadline);
        !          1997: }
        !          1998: 
        !          1999: 
        !          2000: //*********************************************************************************
        !          2001: // stop_ack_timer
        !          2002: //
        !          2003: //*********************************************************************************
        !          2004: 
        !          2005: void IOService::stop_ack_timer ( void )
        !          2006: {
        !          2007:     thread_call_func_cancel(ack_timer_expired, (void *)this, true);
        !          2008: }
        !          2009: 
        !          2010: 
        !          2011: //*********************************************************************************
        !          2012: // c-language timer expiration functions
        !          2013: //
        !          2014: //*********************************************************************************
        !          2015: 
        !          2016: static void ack_timer_expired ( thread_call_param_t us, thread_call_param_t )
        !          2017: {
        !          2018:     ((IOService *)us)->ack_timer_ticked();
        !          2019: }
        !          2020: 
        !          2021: 
        !          2022: static void settle_timer_expired ( thread_call_param_t us, thread_call_param_t )
        !          2023: {
        !          2024:     ((IOService *)us)->settleTimerExpired();
        !          2025: }
        !          2026: 
        !          2027: 
        !          2028: //*********************************************************************************
        !          2029: // add_to_active_change
        !          2030: //
        !          2031: // A child or interested driver has just registered with us.  If there is
        !          2032: // currently a change in progress, get the new party involved: if we
        !          2033: // have notified all parties and are waiting for acks, notify the new
        !          2034: // party.
        !          2035: //*********************************************************************************
        !          2036: 
        !          2037: IOReturn IOService::add_to_active_change ( IOPMinformee * newObject, bool is_child )
        !          2038: {
        !          2039:     if (! acquire_lock() ) {
        !          2040:         return IOPMNoErr;
        !          2041:     }
        !          2042: 
        !          2043:     switch (priv->machine_state) {
        !          2044:         case IOPMour_prechange_1:
        !          2045:             priv->head_note_pendingAcks += 1;
        !          2046:             IOUnlock(priv->our_lock);
        !          2047:             notifyObject(newObject, true, is_child);
        !          2048:             return IOPMNoErr;
        !          2049:         case IOPMour_prechange_4:
        !          2050:             priv->head_note_pendingAcks += 1;
        !          2051:             IOUnlock(priv->our_lock);
        !          2052:             notifyObject(newObject, false, is_child);
        !          2053:             return IOPMNoErr;
        !          2054:         case IOPMparent_prechange_down_4:
        !          2055:             priv->head_note_pendingAcks += 1;
        !          2056:             IOUnlock(priv->our_lock);
        !          2057:             notifyObject(newObject, true, is_child);
        !          2058:             return IOPMNoErr;
        !          2059:         case IOPMparent_postchange_down_2:
        !          2060:             priv->head_note_pendingAcks += 1;
        !          2061:             IOUnlock(priv->our_lock);
        !          2062:             notifyObject(newObject, false, is_child);
        !          2063:             return IOPMNoErr;
        !          2064:         case IOPMparent_prechange_up_1:
        !          2065:             priv->head_note_pendingAcks += 1;
        !          2066:             IOUnlock(priv->our_lock);
        !          2067:             notifyObject(newObject, true, is_child);
        !          2068:             return IOPMNoErr;
        !          2069:         case IOPMparent_postchange_up_6:
        !          2070:             priv-> head_note_pendingAcks += 1;
        !          2071:             IOUnlock(priv->our_lock);
        !          2072:             notifyObject(newObject, false, is_child);
        !          2073:             return IOPMNoErr;
        !          2074:     }
        !          2075:     IOUnlock(priv->our_lock);
        !          2076:     return IOPMNoErr;
        !          2077: }
        !          2078: 
        !          2079: 
        !          2080: //*********************************************************************************
        !          2081: // start_parent_change
        !          2082: //
        !          2083: // Here we begin the processing of a change note  initiated by our parent
        !          2084: // which is at the head of the queue.
        !          2085: //
        !          2086: // It is possible for the change to be processed to completion and removed from the queue.
        !          2087: // There are several possible interruptions to the processing, though, and they are:
        !          2088: // we may have to wait for interested parties to acknowledge our pre-change notification,
        !          2089: // changes initiated by the parent will wait in the middle for powerStateDidChange,
        !          2090: // we may have to wait for our controlling driver to change the hardware power state,
        !          2091: // there may be a settling time after changing the hardware power state,
        !          2092: // we may have to wait for interested parties to acknowledge our post-change notification,
        !          2093: // we may have to wait for the acknowledgement timer expiration to substitute for the
        !          2094: // acknowledgement from a failing driver.
        !          2095: // We identify which of the following three possible lives the note
        !          2096: // will have and then start the life:
        !          2097: // 2.  The parent initiated the change, and it is lowering power,
        !          2098: // 3.  The parent initiated the change, and it is raising power,
        !          2099: // 4.  The parent initiated the change, and the power state is not changing.
        !          2100: //
        !          2101: // In life-style 2, if all interested parties acknowledge our pre-change notification,
        !          2102: // our controlling driver changes power states immediately without having to call us back later,
        !          2103: // and there is no settling time required, we return IOPMAckImplied.
        !          2104: // In life-style 3, if all interested parties acknowledge our pre-change notification, we return IOPMAckImplied.
        !          2105: // In life-style 4, we always return IOPMAckImplied.
        !          2106: // In any other case, we return IOPMWillAckLater.
        !          2107: // If our caller is ultimately our powerDomainWillChange method, it will return our return code to the parent.
        !          2108: // Otherwise, this new notification was dequeued from the queue after we finished a previous one.
        !          2109: // In this case, an IOPMAckImplied return from here will cause the caller to explicitly acknowledge
        !          2110: // the parent by calling its acknowledgePowerChange method.
        !          2111: //*********************************************************************************
        !          2112: 
        !          2113: IOReturn IOService::start_parent_change ( unsigned long queue_head )
        !          2114: {
        !          2115:     priv->head_note = queue_head;
        !          2116:     priv-> head_note_flags = priv-> changeList->changeNote[priv->head_note].flags;
        !          2117:     priv-> head_note_state =  priv->changeList->changeNote[priv->head_note].newStateNumber;
        !          2118:     priv-> head_note_outputFlags =  priv->changeList->changeNote[priv->head_note].outputPowerCharacter;
        !          2119:     priv->head_note_domainState = priv->changeList->changeNote[priv->head_note].domainState;
        !          2120:     priv->head_note_capabilityFlags =  priv->changeList->changeNote[priv->head_note].capabilityFlags;
        !          2121: 
        !          2122:     pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogStartParentChange,(unsigned long)priv->head_note_state,0);
        !          2123: 
        !          2124:     ask_parent( priv->ourDesiredPowerState);                   // if we need something and haven't told the parent, do so
        !          2125: 
        !          2126:     if ( priv->head_note_state < pm_vars->myCurrentState ) {
        !          2127:        priv->initial_change = false;                           // life-style 2
        !          2128:        priv->machine_state = IOPMparent_prechange_down_4;      // in case they don't all ack
        !          2129:         if ( notifyAll(true) == IOPMAckImplied ) {
        !          2130:             return parent_prechange_down_1();
        !          2131:         }
        !          2132:         return IOPMWillAckLater;                               // they didn't
        !          2133:     }
        !          2134: 
        !          2135:     if ( priv->head_note_state > pm_vars->myCurrentState ) {   // if the parent is raising power, we may or may not
        !          2136:         if ( priv->ourDesiredPowerState > pm_vars->myCurrentState ) {
        !          2137:            if ( priv->ourDesiredPowerState < priv->head_note_state ) {
        !          2138:                priv->head_note_state = priv->ourDesiredPowerState;     // we do, but not all the way
        !          2139:                priv->head_note_outputFlags =   pm_vars->thePowerStates[priv->head_note_state].outputPowerCharacter;
        !          2140:                priv->head_note_capabilityFlags =   pm_vars->thePowerStates[priv->head_note_state].capabilityFlags;
        !          2141:                pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogAmendParentChange,(unsigned long)priv->head_note_state,0);
        !          2142:             }
        !          2143:         }
        !          2144:         else {
        !          2145:             priv-> head_note_state = pm_vars->myCurrentState;  // we don't
        !          2146:             priv->head_note_outputFlags =   pm_vars->thePowerStates[priv->head_note_state].outputPowerCharacter;
        !          2147:             priv->head_note_capabilityFlags =   pm_vars->thePowerStates[priv->head_note_state].capabilityFlags;
        !          2148:             pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogAmendParentChange,(unsigned long)priv->head_note_state,0);
        !          2149:         }
        !          2150:     }
        !          2151: 
        !          2152:     if ( priv->head_note_state > pm_vars->myCurrentState ) {
        !          2153:        priv->initial_change = false;                           // life-style 3
        !          2154:        priv->machine_state = IOPMparent_prechange_up_1;                // in case they don't all ack
        !          2155:        if (  notifyAll(true) == IOPMAckImplied ) {
        !          2156:            priv->machine_state = IOPMparent_postchange_up_1;
        !          2157:            return IOPMAckImplied;
        !          2158:        }
        !          2159:        return IOPMWillAckLater;                                // they didn't
        !          2160:    }
        !          2161: 
        !          2162:     if ( priv->head_note_state == pm_vars->myCurrentState ) {
        !          2163:         priv->machine_state = IOPMparent_postchange_null;              // life-style 4
        !          2164:         return IOPMAckImplied;
        !          2165:     }
        !          2166: return IOPMAckImplied;                         // something wrong
        !          2167: }
        !          2168: 
        !          2169: 
        !          2170: //*********************************************************************************
        !          2171: // start_our_change
        !          2172: //
        !          2173: // Here we begin the processing of a change note  initiated by us
        !          2174: // which is at the head of the queue.
        !          2175: //
        !          2176: // It is possible for the change to be processed to completion and removed from the queue.
        !          2177: // There are several possible interruptions to the processing, though, and they are:
        !          2178: // we may have to wait for interested parties to acknowledge our pre-change notification,
        !          2179: // changes initiated by the parent will wait in the middle for powerStateDidChange,
        !          2180: // we may have to wait for our controlling driver to change the hardware power state,
        !          2181: // there may be a settling time after changing the hardware power state,
        !          2182: // we may have to wait for interested parties to acknowledge our post-change notification,
        !          2183: // we may have to wait for the acknowledgement timer expiration to substitute for the
        !          2184: // acknowledgement from a failing driver.
        !          2185: //*********************************************************************************
        !          2186: 
        !          2187: void IOService::start_our_change ( unsigned long queue_head )
        !          2188: {
        !          2189:     priv->head_note = queue_head;
        !          2190:     priv->head_note_flags =  priv->changeList->changeNote[priv->head_note].flags;
        !          2191:     priv->head_note_state =  priv->changeList->changeNote[priv->head_note].newStateNumber;
        !          2192:     priv->head_note_outputFlags =  priv->changeList->changeNote[priv->head_note].outputPowerCharacter;
        !          2193:     priv->head_note_capabilityFlags =  priv->changeList->changeNote[priv->head_note].capabilityFlags;
        !          2194: 
        !          2195:     pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogStartDeviceChange,(unsigned long)priv->head_note_state,0);
        !          2196: 
        !          2197:     if ( !  priv->we_are_root ) {
        !          2198:         ask_parent(priv->head_note_state);                     // if this changes our power requirement, tell the parent
        !          2199:     }
        !          2200: 
        !          2201:     if ( priv->head_note_capabilityFlags & IOPMNotAttainable ) {       // can our driver switch to the new state?
        !          2202:         priv-> head_note_flags |= IOPMNotDone;                 // no, mark the change note un-actioned
        !          2203:         all_done();                                            // and we're done
        !          2204:         return;                                                // let the parent make the change for us
        !          2205:     }
        !          2206:     if ( (pm_vars->maxCapability < priv->head_note_state) && (!  priv->we_are_root) ) {        // is there enough power in the domain?
        !          2207:         priv->head_note_flags |= IOPMNotDone;                                          // no, mark the change note un-actioned
        !          2208:         all_done();                                                                    // and we're done
        !          2209:         return;                                                                        // till the parent raises power
        !          2210:     }
        !          2211: 
        !          2212:     if ( !  priv->initial_change ) {
        !          2213:         if ( priv->head_note_state == pm_vars->myCurrentState ) {
        !          2214:             all_done();                                                // we initiated a null change; forget it
        !          2215:             return;
        !          2216:         }
        !          2217:     }
        !          2218:     priv->initial_change = false;
        !          2219: 
        !          2220:     priv->machine_state = IOPMour_prechange_1;         // in case they don't all ack
        !          2221:     if ( notifyAll(true) == IOPMAckImplied ) {                 // in life-style 1
        !          2222:         our_prechange_1();
        !          2223:     }
        !          2224: }
        !          2225: 
        !          2226: 
        !          2227: //*********************************************************************************
        !          2228: // ask_parent
        !          2229: //
        !          2230: // Call the power domain parent to ask for a higher power state in the domain
        !          2231: // or to suggest a lower power state.
        !          2232: //*********************************************************************************
        !          2233: 
        !          2234: IOReturn IOService::ask_parent ( unsigned long requestedState )
        !          2235: {
        !          2236:     unsigned long savedPreviousRequest;
        !          2237:     IOReturn return_code;
        !          2238: 
        !          2239:     if ( priv->previousRequest ==  pm_vars->thePowerStates[requestedState].inputPowerRequirement ) {   // is this a new desire?
        !          2240:         return IOPMNoErr;                                                      // no, the parent knows already, just return
        !          2241:     }
        !          2242: 
        !          2243:     if (  priv->we_are_root ) {
        !          2244:         return IOPMNoErr;
        !          2245:     }
        !          2246:     savedPreviousRequest = priv->previousRequest;                              // yes, remember our previous request for a second
        !          2247:     priv->previousRequest =  pm_vars->thePowerStates[requestedState].inputPowerRequirement;
        !          2248:     return_code = pm_vars->myParent->requestDomainState( priv->previousRequest,this,IOPMLowestState);
        !          2249: 
        !          2250:     if ( return_code != IOPMNoErr ) {                                  // if that was not ok with the parent,
        !          2251: 
        !          2252:         pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogRequestDenied,(unsigned long)priv->previousRequest,0);
        !          2253:         priv->previousRequest = savedPreviousRequest;                  // remember our previous desire
        !          2254:     }
        !          2255:     return return_code;
        !          2256: }
        !          2257: 
        !          2258: 
        !          2259: //*********************************************************************************
        !          2260: // instruct_driver
        !          2261: //
        !          2262: // Call the controlling driver and have it change the power state of the
        !          2263: // hardware.  If it returns IOPMAckImplied, the change is complete, and
        !          2264: // we return IOPMAckImplied.  Otherwise, it will ack when the change
        !          2265: // is done; we return IOPMWillAckLater.
        !          2266: //*********************************************************************************
        !          2267: 
        !          2268: IOReturn IOService::instruct_driver ( unsigned long newState )
        !          2269: {
        !          2270:     IOReturn return_code;
        !          2271: 
        !          2272:     if (  pm_vars->thePowerStates[newState].capabilityFlags & IOPMNotAttainable ) {    // can our driver switch to the desired state?
        !          2273:         return IOPMAckImplied;                                         // no, so don't try
        !          2274:     }
        !          2275:     priv->driver_timer = -1;
        !          2276:     pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogProgramHardware,newState,0);
        !          2277:     return_code = pm_vars->theControllingDriver->setPowerState(  newState,this );      // yes, instruct it
        !          2278:     if ( return_code == IOPMAckImplied ) {                                     // it finished
        !          2279:         priv->driver_timer = 0;
        !          2280:         return IOPMAckImplied;
        !          2281:     }
        !          2282: 
        !          2283:     if ( priv->driver_timer == 0 ) {                                           // it acked behind our back
        !          2284:         return IOPMAckImplied;
        !          2285:     }
        !          2286: 
        !          2287:     if ( return_code < 0 ) {                                                   // somebody goofed
        !          2288:         return IOPMAckImplied;
        !          2289:     }
        !          2290: 
        !          2291:     priv->driver_timer = (return_code / 1000) + 1;                                     // it didn't finish
        !          2292:     return IOPMWillAckLater;
        !          2293: }
        !          2294: 
        !          2295: 
        !          2296: //*********************************************************************************
        !          2297: // acquire_lock
        !          2298: //
        !          2299: // We are acquiring the lock we use to protect our queue head from
        !          2300: // simutaneous access by a thread which calls acknowledgePowerStateChange
        !          2301: // or acknowledgeSetPowerState and the ack timer expiration thread.
        !          2302: // Return TRUE if we acquire the lock, and the queue head didn't change
        !          2303: // while we were acquiring the lock (and maybe blocked).
        !          2304: // If there is no queue head, or it changes while we are blocked,
        !          2305: // return FALSE with the lock unlocked.
        !          2306: //*********************************************************************************
        !          2307: 
        !          2308: bool IOService::acquire_lock ( void )
        !          2309: {
        !          2310:     long current_change_note;
        !          2311: 
        !          2312:     current_change_note = priv->head_note;
        !          2313:     if ( current_change_note == -1 ) {
        !          2314:         return FALSE;
        !          2315:     }
        !          2316: 
        !          2317:     IOTakeLock(priv->our_lock);
        !          2318:     if ( current_change_note == priv->head_note ) {
        !          2319:         return TRUE;
        !          2320:     }
        !          2321:     else {                                     // we blocked and something changed radically
        !          2322:         IOUnlock(priv->our_lock);              // so there's nothing to do any more
        !          2323:         return FALSE;
        !          2324:     }
        !          2325: }
        !          2326: 
        !          2327: 
        !          2328: //*********************************************************************************
        !          2329: // foundDevice
        !          2330: //
        !          2331: // Does nothing here.  This should be implemented in a subclass driver.
        !          2332: //*********************************************************************************
        !          2333: #if BREAK
        !          2334: IOReturn IOService::foundDevice ( IOService *  yourDevice )
        !          2335: {
        !          2336:     return IOPMNoErr;
        !          2337: }
        !          2338: #endif
        !          2339: 
        !          2340: //*********************************************************************************
        !          2341: // setPowerState
        !          2342: //
        !          2343: // Does nothing here.  This should be implemented in a subclass driver.
        !          2344: //*********************************************************************************
        !          2345: 
        !          2346: IOReturn IOService::setPowerState ( unsigned long powerStateOrdinal, IOService* whatDevice )
        !          2347: {
        !          2348:     return IOPMNoErr;
        !          2349: }
        !          2350: 
        !          2351: 
        !          2352: //*********************************************************************************
        !          2353: // maxCapabilityForDomainState
        !          2354: //
        !          2355: // Finds the highest power state in the array whose input power
        !          2356: // requirement is equal to the input parameter.  Where a more intelligent
        !          2357: // decision is possible, override this in the subclassed driver.
        !          2358: //*********************************************************************************
        !          2359: 
        !          2360: unsigned long IOService::maxCapabilityForDomainState ( IOPMPowerFlags domainState )
        !          2361: {
        !          2362:    int i;
        !          2363: 
        !          2364:    if (pm_vars->theNumberOfPowerStates == 0 ) {
        !          2365:        return 0;
        !          2366:    }
        !          2367:    for ( i = (pm_vars->theNumberOfPowerStates)-1; i >= 0; i-- ) {
        !          2368:        if (  pm_vars->thePowerStates[i].inputPowerRequirement == domainState ) {
        !          2369:            return i;
        !          2370:        }
        !          2371:    }
        !          2372:    return 0;
        !          2373: }
        !          2374: 
        !          2375: 
        !          2376: //*********************************************************************************
        !          2377: // initialPowerStateForDomainState
        !          2378: //
        !          2379: // Finds the highest power state in the array whose input power
        !          2380: // requirement is equal to the input parameter.  Where a more intelligent
        !          2381: // decision is possible, override this in the subclassed driver.
        !          2382: //*********************************************************************************
        !          2383: 
        !          2384: unsigned long IOService::initialPowerStateForDomainState ( IOPMPowerFlags domainState )
        !          2385: {
        !          2386:   int i;
        !          2387: 
        !          2388:    if (pm_vars->theNumberOfPowerStates == 0 ) {
        !          2389:       return 0;
        !          2390:   }
        !          2391:    for ( i = (pm_vars->theNumberOfPowerStates)-1; i >= 0; i-- ) {
        !          2392:       if ( pm_vars->thePowerStates[i].inputPowerRequirement == domainState ) {
        !          2393:           return i;
        !          2394:       }
        !          2395:   }
        !          2396:   return 0;
        !          2397: }
        !          2398: 
        !          2399: 
        !          2400: //*********************************************************************************
        !          2401: // powerStateForDomainState
        !          2402: //
        !          2403: // Finds the highest power state in the array whose input power
        !          2404: // requirement is equal to the input parameter.  Where a more intelligent
        !          2405: // decision is possible, override this in the subclassed driver.
        !          2406: //*********************************************************************************
        !          2407: 
        !          2408: unsigned long IOService::powerStateForDomainState ( IOPMPowerFlags domainState )
        !          2409: {
        !          2410:   int i;
        !          2411: 
        !          2412:    if (pm_vars->theNumberOfPowerStates == 0 ) {
        !          2413:       return 0;
        !          2414:   }
        !          2415:    for ( i = (pm_vars->theNumberOfPowerStates)-1; i >= 0; i-- ) {
        !          2416:       if ( pm_vars->thePowerStates[i].inputPowerRequirement == domainState ) {
        !          2417:           return i;
        !          2418:       }
        !          2419:   }
        !          2420:   return 0;
        !          2421: }
        !          2422: 
        !          2423: 
        !          2424: //*********************************************************************************
        !          2425: // powerStateWillChangeTo
        !          2426: //
        !          2427: // Does nothing here.  This should be implemented in a subclass driver.
        !          2428: //*********************************************************************************
        !          2429: 
        !          2430: IOReturn IOService::powerStateWillChangeTo ( IOPMPowerFlags, unsigned long, IOService*)
        !          2431: {
        !          2432:     return 0;
        !          2433: }
        !          2434: 
        !          2435: 
        !          2436: //*********************************************************************************
        !          2437: // powerStateDidChangeTo
        !          2438: //
        !          2439: // Does nothing here.  This should be implemented in a subclass driver.
        !          2440: //*********************************************************************************
        !          2441: 
        !          2442: IOReturn IOService::powerStateDidChangeTo ( IOPMPowerFlags, unsigned long, IOService*)
        !          2443: {
        !          2444:     return 0;
        !          2445: }
        !          2446: 
        !          2447: 
        !          2448: //*********************************************************************************
        !          2449: // newTemperature
        !          2450: //
        !          2451: // Does nothing here.  This should be implemented in a subclass driver.
        !          2452: //*********************************************************************************
        !          2453: 
        !          2454: IOReturn IOService::newTemperature ( long currentTemp, IOService * whichZone )
        !          2455: 
        !          2456: {
        !          2457:     return IOPMNoErr;
        !          2458: }
        !          2459: 
        !          2460: 
        !          2461: #undef super
        !          2462: #define super OSObject
        !          2463: 
        !          2464: OSDefineMetaClassAndStructors(IOPMprot, OSObject)
        !          2465: //*********************************************************************************
        !          2466: // serialize
        !          2467: //
        !          2468: // Serialize protected instance variables for debug output.
        !          2469: //*********************************************************************************
        !          2470: bool IOPMprot::serialize(OSSerialize *s) const
        !          2471: {
        !          2472:     OSString * theOSString;
        !          2473:     char * buffer;
        !          2474:     char * ptr;
        !          2475:     int i;
        !          2476:     bool       rtn_code;
        !          2477: 
        !          2478:     buffer = ptr = IONew(char, 2000);
        !          2479:     if(!buffer)
        !          2480:         return false;
        !          2481: 
        !          2482:     ptr += sprintf(ptr,"{ theNumberOfPowerStates = %d, ",(unsigned int)theNumberOfPowerStates);
        !          2483: 
        !          2484:     if ( theNumberOfPowerStates != 0 ) {
        !          2485:         ptr += sprintf(ptr,"version %d, ",(unsigned int)thePowerStates[0].version);
        !          2486:     }
        !          2487: 
        !          2488:     if ( theNumberOfPowerStates != 0 ) {
        !          2489:         for ( i = 0; i < (int)theNumberOfPowerStates; i++ ) {
        !          2490:             ptr += sprintf(ptr,"power state %d = { ",i);
        !          2491:             ptr += sprintf(ptr,"capabilityFlags %08x, ",(unsigned int)thePowerStates[i].capabilityFlags);
        !          2492:             ptr += sprintf(ptr,"outputPowerCharacter %08x, ",(unsigned int)thePowerStates[i].outputPowerCharacter);
        !          2493:             ptr += sprintf(ptr,"inputPowerRequirement %08x, ",(unsigned int)thePowerStates[i].inputPowerRequirement);
        !          2494:             ptr += sprintf(ptr,"staticPower %d, ",(unsigned int)thePowerStates[i].staticPower);
        !          2495:             ptr += sprintf(ptr,"unbudgetedPower %d, ",(unsigned int)thePowerStates[i].unbudgetedPower);
        !          2496:             ptr += sprintf(ptr,"powerToAttain %d, ",(unsigned int)thePowerStates[i].powerToAttain);
        !          2497:             ptr += sprintf(ptr,"timeToAttain %d, ",(unsigned int)thePowerStates[i].timeToAttain);
        !          2498:             ptr += sprintf(ptr,"settleUpTime %d, ",(unsigned int)thePowerStates[i].settleUpTime);
        !          2499:             ptr += sprintf(ptr,"timeToLower %d, ",(unsigned int)thePowerStates[i].timeToLower);
        !          2500:             ptr += sprintf(ptr,"settleDownTime %d, ",(unsigned int)thePowerStates[i].settleDownTime);
        !          2501:             ptr += sprintf(ptr,"powerDomainBudget %d }, ",(unsigned int)thePowerStates[i].powerDomainBudget);
        !          2502:         }
        !          2503:     }
        !          2504: 
        !          2505:     ptr += sprintf(ptr,"aggressiveness = %d, ",(unsigned int)aggressiveness);
        !          2506:     ptr += sprintf(ptr,"myCurrentState = %d, ",(unsigned int)myCurrentState);
        !          2507:     ptr += sprintf(ptr,"parentCurrentPowerFlags = %08x, ",(unsigned int)parentCurrentPowerFlags);
        !          2508:     ptr += sprintf(ptr,"maxCapability = %d }",(unsigned int)maxCapability);
        !          2509: 
        !          2510:     theOSString = OSString::withCString(buffer);
        !          2511:     rtn_code = theOSString->serialize(s);
        !          2512:     theOSString->release();
        !          2513:     IODelete(buffer, char, 2000);
        !          2514: 
        !          2515:     return rtn_code;
        !          2516: }
        !          2517: 
        !          2518: 
        !          2519: #undef super
        !          2520: #define super OSObject
        !          2521: 
        !          2522: OSDefineMetaClassAndStructors(IOPMpriv, OSObject)
        !          2523: //*********************************************************************************
        !          2524: // serialize
        !          2525: //
        !          2526: // Serialize private instance variables for debug output.
        !          2527: //*********************************************************************************
        !          2528: bool IOPMpriv::serialize(OSSerialize *s) const
        !          2529: {
        !          2530:     OSString * theOSString;
        !          2531:     char * buffer;
        !          2532:     char * ptr;
        !          2533:     IOPMinformee * nextObject;
        !          2534:     bool       rtn_code;
        !          2535: 
        !          2536:     buffer = ptr = IONew(char, 2000);
        !          2537:     if(!buffer)
        !          2538:         return false;
        !          2539: 
        !          2540:     ptr += sprintf(ptr,"{ this object = %08x",(unsigned int)owner);
        !          2541:     if ( we_are_root ) {
        !          2542:         ptr += sprintf(ptr," (root)");
        !          2543:     }
        !          2544:     ptr += sprintf(ptr,", ");
        !          2545: 
        !          2546:     nextObject = interestedDrivers->firstInList();                     // display interested drivers
        !          2547:     while (  nextObject != NULL ) {
        !          2548:         ptr += sprintf(ptr,"interested driver = %08x, ",(unsigned int)nextObject->whatObject);
        !          2549:         nextObject  =  interestedDrivers->nextInList(nextObject);
        !          2550:     }
        !          2551: 
        !          2552:     nextObject =children->firstInList();                               // display power domain children
        !          2553:     while (  nextObject != NULL ) {
        !          2554:         ptr += sprintf(ptr,"child = %08x, ",(unsigned int)nextObject->whatObject);
        !          2555:             nextObject  = children->nextInList(nextObject);
        !          2556:     }
        !          2557: 
        !          2558:     ptr += sprintf(ptr,"numberOfInformees = %d, ",(unsigned int)numberOfInformees);
        !          2559: 
        !          2560:     if ( machine_state != IOPMfinished ) {
        !          2561:         ptr += sprintf(ptr,"machine_state = %d, ",(unsigned int)machine_state);
        !          2562:         ptr += sprintf(ptr,"driver_timer = %d, ",(unsigned int)driver_timer);
        !          2563:         ptr += sprintf(ptr,"settle_time = %d, ",(unsigned int)settle_time);
        !          2564:         ptr += sprintf(ptr,"head_note_flags = %08x, ",(unsigned int)head_note_flags);
        !          2565:         ptr += sprintf(ptr,"head_note_state = %d, ",(unsigned int)head_note_state);
        !          2566:         ptr += sprintf(ptr,"head_note_outputFlags = %08x, ",(unsigned int)head_note_outputFlags);
        !          2567:         ptr += sprintf(ptr,"head_note_domainState = %08x, ",(unsigned int)head_note_domainState);
        !          2568:         ptr += sprintf(ptr,"head_note_capabilityFlags = %08x, ",(unsigned int)head_note_capabilityFlags);
        !          2569:         ptr += sprintf(ptr,"head_note_pendingAcks = %d, ",(unsigned int)head_note_pendingAcks);
        !          2570:     }
        !          2571: 
        !          2572:     if ( device_overrides ) {
        !          2573:         ptr += sprintf(ptr,"device overrides, ");
        !          2574:     }
        !          2575:     ptr += sprintf(ptr,"driverDesire = %d, ",(unsigned int)driverDesire);
        !          2576:     ptr += sprintf(ptr,"deviceDesire = %d, ",(unsigned int)deviceDesire);
        !          2577:     ptr += sprintf(ptr,"ourDesiredPowerState = %d, ",(unsigned int)ourDesiredPowerState);
        !          2578:     ptr += sprintf(ptr,"previousRequest = %d }",(unsigned int)previousRequest);
        !          2579: 
        !          2580:     theOSString =  OSString::withCString(buffer);
        !          2581:     rtn_code = theOSString->serialize(s);
        !          2582:     theOSString->release();
        !          2583:     IODelete(buffer, char, 2000);
        !          2584: 
        !          2585:     return rtn_code;
        !          2586: }
        !          2587: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.