2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 #include <IOKit/IOService.h>
27 #include <IOKit/IOLib.h>
28 #include <IOKit/IOCommandGate.h>
29 #include <IOKit/IOTimerEventSource.h>
30 #include <IOKit/IOWorkLoop.h>
31 #include <IOKit/IOPlatformExpert.h>
32 #include <IOKit/assert.h>
33 #include <IOKit/IOMessage.h>
34 #include <IOKit/IOKitDebug.h>
35 #include <IOKit/IOTimeStamp.h>
36 #include <IOKit/pwr_mgt/RootDomain.h>
37 #include <IOKit/pwr_mgt/IOPMinformee.h>
38 #include "IOKit/pwr_mgt/IOPMinformeeList.h"
39 #include "IOKit/pwr_mgt/IOPMchangeNoteList.h"
40 #include "IOKit/pwr_mgt/IOPMlog.h"
41 #include "IOKit/pwr_mgt/IOPowerConnection.h"
42 #include <kern/clock.h>
44 #define super IORegistryEntry
46 // Some debug functions
48 ioSPMTrace(unsigned int csc
,
49 unsigned int a
= 0, unsigned int b
= 0,
50 unsigned int c
= 0, unsigned int d
= 0)
52 if (gIOKitDebug
& kIOLogTracePower
)
53 IOTimeStampConstant(IODBG_POWER(csc
), a
, b
, c
, d
);
57 ioSPMTraceStart(unsigned int csc
,
58 unsigned int a
= 0, unsigned int b
= 0,
59 unsigned int c
= 0, unsigned int d
= 0)
61 if (gIOKitDebug
& kIOLogTracePower
)
62 IOTimeStampConstant(IODBG_POWER(csc
)|DBG_FUNC_START
, a
, b
, c
, d
);
66 ioSPMTraceEnd(unsigned int csc
,
67 unsigned int a
= 0, unsigned int b
= 0,
68 unsigned int c
= 0, unsigned int d
= 0)
70 if (gIOKitDebug
& kIOLogTracePower
)
71 IOTimeStampConstant(IODBG_POWER(csc
)|DBG_FUNC_END
, a
, b
, c
, d
);
75 static void ack_timer_expired(thread_call_param_t
);
76 static void settle_timer_expired(thread_call_param_t
);
77 static void PM_idle_timer_expired(OSObject
*, IOTimerEventSource
*);
78 static void c_PM_Clamp_Timer_Expired (OSObject
* client
,IOTimerEventSource
*);
79 void tellAppWithResponse ( OSObject
* object
, void * context
);
80 void tellClientWithResponse ( OSObject
* object
, void * context
);
81 void tellClient ( OSObject
* object
, void * context
);
82 IOReturn
serializedAllowPowerChange ( OSObject
*, void *, void *, void *, void *);
83 IOReturn
serializedCancelPowerChange ( OSObject
*, void *, void *, void *, void *);
85 extern const IORegistryPlane
* gIOPowerPlane
;
88 // and there's 1000 nanoseconds in a microsecond:
89 #define ns_per_us 1000
92 // The current change note is processed by a state machine.
93 // Inputs are acks from interested parties, ack from the controlling driver,
94 // ack timeouts, settle timeout, and powerStateDidChange from the parent.
95 // These are the states:
97 kIOPM_OurChangeTellClientsPowerDown
= 1,
98 kIOPM_OurChangeTellPriorityClientsPowerDown
,
99 kIOPM_OurChangeNotifyInterestedDriversWillChange
,
100 kIOPM_OurChangeSetPowerState
,
101 kIOPM_OurChangeWaitForPowerSettle
,
102 kIOPM_OurChangeNotifyInterestedDriversDidChange
,
103 kIOPM_OurChangeFinish
,
104 kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate
,
105 kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
,
106 kIOPM_ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate
,
107 kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
,
108 kIOPM_ParentDownSetPowerState_Delayed
,
109 kIOPM_ParentDownWaitForPowerSettle_Delayed
,
110 kIOPM_ParentDownAcknowledgeChange_Delayed
,
111 kIOPM_ParentUpSetPowerState_Delayed
,
112 kIOPM_ParentUpSetPowerState_Immediate
,
113 kIOPM_ParentUpWaitForSettleTime_Delayed
,
114 kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed
,
115 kIOPM_ParentUpAcknowledgePowerChange_Delayed
,
119 // values of outofbandparameter
126 // used for applyToInterested
128 OSArray
* responseFlags
;
131 UInt32 maxTimeRequested
;
135 unsigned long stateNumber
;
136 IOPMPowerFlags stateFlags
;
139 // five minutes in microseconds
140 #define FIVE_MINUTES 5*60*1000000
141 #define k30seconds 30*1000000
144 There are two different kinds of power state changes. One is initiated by a subclassed device object which has either
145 decided to change power state, or its controlling driver has suggested it, or some other driver wants to use the
146 idle device and has asked it to become usable. The second kind of power state change is initiated by the power
147 domain parent. The two are handled slightly differently.
149 There is a queue of so-called change notifications, or change notes for short. Usually the queue is empty, and when
150 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
151 at one time, a queue is implemented. Example: the subclass device decides it's idle and initiates a change to a lower
152 power state. This causes interested parties to be notified, but they don't all acknowledge right away. This causes the
153 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
154 wants to raise power back up again. This change can't be started, however, because the previous one isn't complete yet,
155 so the second one waits in the queue. During this time, the parent decides to lower or raise the power state of the entire
156 power domain and notifies the device, and that notification goes into the queue, too, and can't be actioned until the
159 This is how a power change initiated by the subclass device is handled:
160 First, all interested parties are notified of the change via their powerStateWillChangeTo method. If they all don't
161 acknowledge via return code, then we have to wait. If they do, or when they finally all acknowledge via our
162 acknowledgePowerChange method, then we can continue. We call the controlling driver, instructing it to change to
163 the new state. Then we wait for power to settle. If there is no settling-time, or after it has passed, we notify
164 interested parties again, this time via their powerStateDidChangeTo methods. When they have all acked, we're done.
165 If we lowered power and don't need the power domain to be in its current power state, we suggest to the parent that
166 it lower the power domain state.
168 This is how a change to a lower power domain state initiated by the parent is handled:
169 First, we figure out what power state we will be in when the new domain state is reached. Then all interested parties are
170 notified that we are moving to that new state. When they have acknowledged, we call the controlling driver to assume
171 that state and we wait for power to settle. Then we acknowledge our preparedness to our parent. When all its interested
172 parties have acknowledged, it lowers power and then notifies its interested parties again. When we get this call, we notify
173 our interested parties that the power state has changed, and when they have all acknowledged, we're done.
175 This is how a change to a higher power domain state initiated by the parent is handled:
176 We figure out what power state we will be in when the new domain state is reached. If it is different from our current
177 state we acknowledge the parent. When all the parent's interested parties have acknowledged, it raises power in the
178 domain and waits for power to settle. Then it notifies everyone that the new state has been reached. When we get this call,
179 we call the controlling driver, instructing it to assume the new state, and wait for power to settle. Then we notify our interested
180 parties. When they all acknowledge we are done.
182 In either of the two cases above, it is possible that we will not be changing state even though the domain is. Examples:
183 A change to a lower domain state may not affect us because we are already in a low enough state, and
184 We will not take advantage of a change to a higher domain state, because we have no need of the higher power.
185 In such a case, there is nothing to do but acknowledge the parent. So when the parent calls our powerDomainWillChange
186 method, and we decide that we will not be changing state, we merely acknowledge the parent, via return code, and wait.
187 When the parent subsequently calls powerStateDidChange, we acknowledge again via return code, and the change is complete.
189 Power state changes are processed in a state machine, and since there are four varieties of power state changes, there are
190 four major paths through the state machine:
192 The fourth is nearly trivial. In this path, the parent is changing the domain state, but we are not changing the device state.
193 The change starts when the parent calls powerDomainWillChange. All we do is acknowledge the parent.
194 When the parent calls powerStateDidChange, we acknowledge the parent again, and we're done.
196 The first is fairly simple. It starts when a power domain child calls requestPowerDomainState and we decide to change power states
197 to accomodate the child, or if our power-controlling driver calls changePowerStateTo, or if some other driver which is using our
198 device calls makeUsable, or if a subclassed object calls changePowerStateToPriv. These are all power changes initiated by us, not
199 forced upon us by the parent. We start by notifying interested parties. If they all acknowledge via return code, we can go
200 on to state "OurChangeSetPowerState". Otherwise, we start the ack timer and wait for the stragglers to acknowlege by calling
201 acknowledgePowerChange. We move on to state "OurChangeSetPowerState" when all the stragglers have acknowledged,
202 or when the ack timer expires on all those which didn't acknowledge. In "OurChangeSetPowerState" we call the power-controlling
203 driver to change the power state of the hardware. If it returns saying it has done so, we go on to state "OurChangeWaitForPowerSettle".
204 Otherwise, we have to wait for it, so we set the ack timer and wait. When it calls acknowledgeSetPowerState, or when the
205 ack timer expires, we go on. In "OurChangeWaitForPowerSettle", we look in the power state array to see if there is any settle time required
206 when changing from our current state to the new state. If not, we go right away to "OurChangeNotifyInterestedDriversDidChange". Otherwise, we
207 set the settle timer and wait. When it expires, we move on. In "OurChangeNotifyInterestedDriversDidChange" state, we notify all our interested parties
208 via their powerStateDidChange methods that we have finished changing power state. If they all acknowledge via return
209 code, we move on to "OurChangeFinish". Otherwise we set the ack timer and wait. When they have all acknowledged, or
210 when the ack timer has expired for those that didn't, we move on to "OurChangeFinish", where we remove the used
211 change note from the head of the queue and start the next one if one exists.
213 Parent-initiated changes are more complex in the state machine. First, power going up and power going down are handled
214 differently, so they have different paths throught the state machine. Second, we can acknowledge the parent's notification
215 in two different ways, so each of the parent paths is really two.
217 When the parent calls our powerDomainWillChange method, notifying us that it will lower power in the domain, we decide
218 what state that will put our device in. Then we embark on the state machine path "IOPMParentDownSetPowerState_Immediate"
219 and "kIOPM_ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate", in which we notify interested parties of the upcoming change, instruct our driver to make
220 the change, check for settle time, and notify interested parties of the completed change. If we get to the end of this path without
221 stalling due to an interested party which didn't acknowledge via return code, due to the controlling driver not able to change
222 state right away, or due to a non-zero settling time, then we return IOPMAckImplied to the parent, and we're done with the change.
223 If we do stall in any of those states, we return IOPMWillAckLater to the parent and enter the parallel path "kIOPM_ParentDownSetPowerState_Delayed"
224 "kIOPM_ParentDownWaitForPowerSettle_Delayed", and "kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed", where we continue with the same processing, except that at the end we
225 acknowledge the parent explicitly via acknowledgePowerChange, and we're done with the change.
226 Then when the parent calls us at powerStateDidChange we acknowledging via return code, because we have already made
227 the power change. In any case, when we are done we remove the used change note from the head of the queue and start on the next one.
229 The case of the parent raising power in the domain is handled similarly in that there are parallel paths, one for no-stall
230 that ends in implicit acknowleging the parent, and one that has stalled at least once that ends in explicit acknowledging
231 the parent. This case is different, though in that our device changes state in the second half, after the parent calls
232 powerStateDidChange rather than before, as in the power-lowering case.
234 When the parent calls our powerDomainWillChange method, notifying us that it will raise power in the domain, we acknowledge
235 via return code, because there's really nothing we can do until the power is actually raised in the domain.
236 When the parent calls us at powerStateDidChange, we start by notifying our interested parties. If they all acknowledge via return code,
237 we go on to" kIOPM_ParentUpSetPowerState_Immediate" to instruct the driver to raise its power level. After that, we check for any
238 necessary settling time in "IOPMParentUpWaitForSettleTime_Immediate", and we notify all interested parties that power has changed
239 in "IOPMParentUpNotifyInterestedDriversDidChange_Immediate". If none of these operations stall, we acknowledge the parent via return code, release
240 the change note, and start the next, if there is one. If one of them does stall, we enter the parallel path "kIOPM_ParentUpSetPowerState_Delayed",
241 "kIOPM_ParentUpWaitForSettleTime_Delayed", "kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed", and "kIOPM_ParentUpAcknowledgePowerChange_Delayed", which ends with
242 our explicit acknowledgement to the parent.
247 const char priv_key
[ ] = "Power Management private data";
248 const char prot_key
[ ] = "Power Management protected data";
251 void IOService::PMinit ( void )
253 if ( ! initialized
) {
255 // make space for our variables
256 pm_vars
= new IOPMprot
;
262 // add pm_vars & priv to the properties
263 setProperty(prot_key
, (OSObject
*) pm_vars
);
264 setProperty(priv_key
, (OSObject
*) priv
);
266 // then initialize them
268 pm_vars
->theNumberOfPowerStates
= 0;
269 priv
->we_are_root
= false;
270 pm_vars
->theControllingDriver
= NULL
;
271 priv
->our_lock
= IOLockAlloc();
272 priv
->flags_lock
= IOLockAlloc();
273 priv
->queue_lock
= IOLockAlloc();
274 pm_vars
->childLock
= IOLockAlloc();
275 pm_vars
->parentLock
= IOLockAlloc();
276 priv
->interestedDrivers
= new IOPMinformeeList
;
277 priv
->interestedDrivers
->initialize();
278 priv
->changeList
= new IOPMchangeNoteList
;
279 priv
->changeList
->initialize();
280 pm_vars
->aggressiveness
= 0;
281 for (unsigned int i
= 0; i
<= kMaxType
; i
++)
283 pm_vars
->current_aggressiveness_values
[i
] = 0;
284 pm_vars
->current_aggressiveness_valid
[i
] = false;
286 pm_vars
->myCurrentState
= 0;
287 priv
->imminentState
= 0;
288 priv
->ourDesiredPowerState
= 0;
289 pm_vars
->parentsCurrentPowerFlags
= 0;
290 pm_vars
->maxCapability
= 0;
291 priv
->driverDesire
= 0;
292 priv
->deviceDesire
= 0;
293 priv
->initial_change
= true;
294 priv
->need_to_become_usable
= false;
295 priv
->previousRequest
= 0;
296 priv
->device_overrides
= false;
297 priv
->machine_state
= kIOPM_Finished
;
298 priv
->timerEventSrc
= NULL
;
299 priv
->clampTimerEventSrc
= NULL
;
300 pm_vars
->PMworkloop
= NULL
;
301 priv
->activityLock
= NULL
;
302 pm_vars
->ourName
= getName();
303 pm_vars
->thePlatform
= getPlatform();
304 pm_vars
->parentsKnowState
= false;
305 assert( pm_vars
->thePlatform
!= 0 );
306 priv
->clampOn
= false;
307 pm_vars
->serialNumber
= 0;
308 pm_vars
->responseFlags
= NULL
;
309 pm_vars
->doNotPowerDown
= true;
310 pm_vars
->PMcommandGate
= NULL
;
311 priv
->ackTimer
= thread_call_allocate((thread_call_func_t
)ack_timer_expired
, (thread_call_param_t
)this);
312 priv
->settleTimer
= thread_call_allocate((thread_call_func_t
)settle_timer_expired
, (thread_call_param_t
)this);
318 //*********************************************************************************
321 // Free up the data created in PMinit, if it exists.
322 //*********************************************************************************
323 void IOService::PMfree ( void )
326 if ( priv
->clampTimerEventSrc
!= NULL
) {
327 getPMworkloop()->removeEventSource(priv
->clampTimerEventSrc
);
328 priv
->clampTimerEventSrc
->release();
329 priv
->clampTimerEventSrc
= NULL
;
331 if ( priv
->timerEventSrc
!= NULL
) {
332 pm_vars
->PMworkloop
->removeEventSource(priv
->timerEventSrc
);
333 priv
->timerEventSrc
->release();
334 priv
->timerEventSrc
= NULL
;
336 if ( priv
->settleTimer
) {
337 thread_call_cancel(priv
->settleTimer
);
338 thread_call_free(priv
->settleTimer
);
339 priv
->settleTimer
= NULL
;
341 if ( priv
->ackTimer
) {
342 thread_call_cancel(priv
->ackTimer
);
343 thread_call_free(priv
->ackTimer
);
344 priv
->ackTimer
= NULL
;
346 if ( priv
->our_lock
) {
347 IOLockFree(priv
->our_lock
);
348 priv
->our_lock
= NULL
;
350 if ( priv
->flags_lock
) {
351 IOLockFree(priv
->flags_lock
);
352 priv
->flags_lock
= NULL
;
354 if ( priv
->activityLock
) {
355 IOLockFree(priv
->activityLock
);
356 priv
->activityLock
= NULL
;
358 priv
->interestedDrivers
->release();
359 priv
->changeList
->release();
360 // remove instance variables
365 if ( pm_vars
->PMcommandGate
) {
366 pm_vars
->PMcommandGate
->release();
367 pm_vars
->PMcommandGate
= NULL
;
369 if ( pm_vars
->PMworkloop
) {
370 // The work loop object returned from getPMworkLoop() is
371 // never retained, therefore it should not be released.
372 // pm_vars->PMworkloop->release();
373 pm_vars
->PMworkloop
= NULL
;
375 if ( pm_vars
->responseFlags
) {
376 pm_vars
->responseFlags
->release();
377 pm_vars
->responseFlags
= NULL
;
379 // remove instance variables
385 //*********************************************************************************
388 // Disconnect the node from its parents and children in the Power Plane.
389 //*********************************************************************************
390 void IOService::PMstop ( void )
394 IOPowerConnection
* connection
;
395 IOService
* theChild
;
396 IOService
* theParent
;
398 // remove the properties
399 removeProperty(prot_key
);
400 removeProperty(priv_key
);
403 iter
= getParentIterator(gIOPowerPlane
);
407 while ( (next
= iter
->getNextObject()) )
409 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
411 theParent
= (IOService
*)connection
->copyParentEntry(gIOPowerPlane
);
414 theParent
->removePowerChild(connection
);
415 theParent
->release();
422 // detach IOConnections
423 detachAbove( gIOPowerPlane
);
425 // no more power state changes
426 pm_vars
->parentsKnowState
= false;
429 iter
= getChildIterator(gIOPowerPlane
);
433 while ( (next
= iter
->getNextObject()) )
435 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
437 theChild
= ((IOService
*)(connection
->copyChildEntry(gIOPowerPlane
)));
440 // detach nub from child
441 connection
->detachFromChild(theChild
,gIOPowerPlane
);
444 // detach us from nub
445 detachFromChild(connection
,gIOPowerPlane
);
451 // Remove all interested drivers from the list, including the power
452 // controlling driver.
454 // Usually, the controlling driver and the policy-maker functionality
455 // are implemented by the same object, and without the deregistration,
456 // the object will be holding an extra retain on itself, and cannot
459 if ( priv
&& priv
->interestedDrivers
)
461 IOPMinformee
* informee
;
463 while (( informee
= priv
->interestedDrivers
->firstInList() ))
464 deRegisterInterestedDriver( informee
->whatObject
);
469 //*********************************************************************************
472 // A policy-maker calls its nub here when initializing, to be attached into
473 // the power management hierarchy. The default function is to call the
474 // platform expert, which knows how to do it. This method is overridden
475 // by a nub subclass which may either know how to do it, or may need
476 // to take other action.
478 // This may be the only "power management" method used in a nub,
479 // meaning it may not be initialized for power management.
480 //*********************************************************************************
481 void IOService::joinPMtree ( IOService
* driver
)
483 IOPlatformExpert
* thePlatform
;
485 thePlatform
= getPlatform();
486 assert(thePlatform
!= 0 );
487 thePlatform
->PMRegisterDevice(this,driver
);
491 //*********************************************************************************
494 // Power Managment is informing us that we are the root power domain.
495 // The only difference between us and any other power domain is that
496 // we have no parent and therefore never call it.
497 //*********************************************************************************
498 IOReturn
IOService::youAreRoot ( void )
500 priv
-> we_are_root
= true;
501 pm_vars
->parentsKnowState
= true;
502 attachToParent( getRegistryRoot(),gIOPowerPlane
);
508 //*********************************************************************************
511 // Power Management is informing us who our parent is.
512 // If we have a controlling driver, find out, given our newly-informed
513 // power domain state, what state it would be in, and then tell it
514 // to assume that state.
515 //*********************************************************************************
516 IOReturn
IOService::setPowerParent ( IOPowerConnection
* theParent
, bool stateKnown
, IOPMPowerFlags currentState
)
520 IOPowerConnection
* connection
;
521 unsigned long tempDesire
;
523 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogSetParent
,stateKnown
,currentState
);
525 IOLockLock(pm_vars
->parentLock
);
527 if ( stateKnown
&& ((pm_vars
->PMworkloop
== NULL
) || (pm_vars
->PMcommandGate
== NULL
)) )
529 // we have a path to the root
530 // find out the workloop
532 if ( pm_vars
->PMworkloop
!= NULL
)
534 if ( pm_vars
->PMcommandGate
== NULL
)
536 // and make our command gate
537 pm_vars
->PMcommandGate
= IOCommandGate::commandGate((OSObject
*)this);
538 if ( pm_vars
->PMcommandGate
!= NULL
)
540 pm_vars
->PMworkloop
->addEventSource(pm_vars
->PMcommandGate
);
546 IOLockUnlock(pm_vars
->parentLock
);
548 // set our connection data
549 theParent
->setParentCurrentPowerFlags(currentState
);
550 theParent
->setParentKnowsState(stateKnown
);
552 // combine parent knowledge
553 pm_vars
->parentsKnowState
= true;
554 pm_vars
->parentsCurrentPowerFlags
= 0;
556 iter
= getParentIterator(gIOPowerPlane
);
560 while ( (next
= iter
->getNextObject()) )
562 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
564 pm_vars
->parentsKnowState
&= connection
->parentKnowsState();
565 pm_vars
->parentsCurrentPowerFlags
|= connection
->parentCurrentPowerFlags();
571 if ( (pm_vars
->theControllingDriver
!= NULL
) &&
572 (pm_vars
->parentsKnowState
) )
574 pm_vars
->maxCapability
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(pm_vars
->parentsCurrentPowerFlags
);
575 // initially change into the state we are already in
576 tempDesire
= priv
->deviceDesire
;
577 priv
->deviceDesire
= pm_vars
->theControllingDriver
->initialPowerStateForDomainState(pm_vars
->parentsCurrentPowerFlags
);
578 computeDesiredState();
579 priv
->previousRequest
= 0xffffffff;
581 // put this back like before
582 priv
->deviceDesire
= tempDesire
;
589 //*********************************************************************************
592 // Power Management is informing us who our children are.
593 //*********************************************************************************
594 IOReturn
IOService::addPowerChild ( IOService
* theChild
)
596 IOPowerConnection
*connection
;
601 // we're not a power-managed IOService
602 return IOPMNotYetInitialized
;
605 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAddChild
,0,0);
607 // Put ourselves into a usable power state.
608 // We must be in an "on" power state, as our children must be able to access
609 // our hardware after joining the power plane.
613 connection
= new IOPowerConnection
;
616 connection
->start(this);
617 connection
->setAwaitingAck(false);
620 attachToChild( connection
,gIOPowerPlane
);
621 connection
->attachToChild( theChild
,gIOPowerPlane
);
622 connection
->release();
624 // tell it the current state of the power domain
625 if ( (pm_vars
->theControllingDriver
== NULL
) ||
626 ! (inPlane(gIOPowerPlane
)) ||
627 ! (pm_vars
->parentsKnowState
) )
629 theChild
->setPowerParent(connection
,false,0);
630 if ( inPlane(gIOPowerPlane
) )
632 for (i
= 0; i
<= kMaxType
; i
++) {
633 if ( pm_vars
->current_aggressiveness_valid
[i
] )
635 theChild
->setAggressiveness (i
, pm_vars
->current_aggressiveness_values
[i
]);
640 theChild
->setPowerParent(connection
,true,pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].outputPowerCharacter
);
641 for (i
= 0; i
<= kMaxType
; i
++)
643 if ( pm_vars
->current_aggressiveness_valid
[i
] )
645 theChild
->setAggressiveness (i
, pm_vars
->current_aggressiveness_values
[i
]);
648 // catch it up if change is in progress
649 add_child_to_active_change(connection
);
656 //*********************************************************************************
659 //*********************************************************************************
660 IOReturn
IOService::removePowerChild ( IOPowerConnection
* theNub
)
662 IORegistryEntry
*theChild
;
665 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRemoveChild
,0,0);
669 // detach nub from child
670 theChild
= theNub
->copyChildEntry(gIOPowerPlane
);
673 theNub
->detachFromChild(theChild
, gIOPowerPlane
);
676 // detach from the nub
677 detachFromChild(theNub
,gIOPowerPlane
);
679 // are we awaiting an ack from this child?
680 if ( theNub
->getAwaitingAck() )
682 // yes, pretend we got one
683 theNub
->setAwaitingAck(false);
684 if ( acquire_lock() )
686 if (priv
->head_note_pendingAcks
!= 0 )
688 // that's one fewer ack to worry about
689 priv
->head_note_pendingAcks
-= 1;
691 if ( priv
->head_note_pendingAcks
== 0 )
693 // yes, stop the timer
695 IOUnlock(priv
->our_lock
);
696 // and now we can continue our power change
699 IOUnlock(priv
->our_lock
);
702 IOUnlock(priv
->our_lock
);
709 // if not fully initialized
710 if ( (pm_vars
->theControllingDriver
== NULL
) ||
711 !(inPlane(gIOPowerPlane
)) ||
712 !(pm_vars
->parentsKnowState
) )
718 // Perhaps the departing child was holding up idle or system sleep - we need to re-evaluate our
719 // childrens' requests. Clear and re-calculate our kIOPMChildClamp and kIOPMChildClamp2 bits.
720 rebuildChildClampBits();
725 iter
= getChildIterator(gIOPowerPlane
);
726 if ( !iter
|| !iter
->getNextObject() )
728 // paired to match the makeUsable() call in addPowerChild()
729 changePowerStateToPriv(0);
731 if(iter
) iter
->release();
734 // this may be different now
735 computeDesiredState();
736 // change state if we can now tolerate lower power
743 //*********************************************************************************
744 // registerPowerDriver
746 // A driver has called us volunteering to control power to our device.
747 // If the power state array it provides is richer than the one we already
748 // know about (supplied by an earlier volunteer), then accept the offer.
749 // Notify all interested parties of our power state, which we now know.
750 //*********************************************************************************
752 IOReturn
IOService::registerPowerDriver ( IOService
* controllingDriver
, IOPMPowerState
* powerStates
, unsigned long numberOfStates
)
755 unsigned long tempDesire
;
757 if ( (numberOfStates
> pm_vars
->theNumberOfPowerStates
)
758 && (numberOfStates
> 1) )
760 if ( priv
->changeList
->currentChange() == -1 )
762 if ( controllingDriver
!= NULL
)
764 if ( numberOfStates
<= IOPMMaxPowerStates
)
766 switch ( powerStates
[0].version
)
769 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriver
,
770 (unsigned long)numberOfStates
, (unsigned long)powerStates
[0].version
);
771 for ( i
= 0; i
< numberOfStates
; i
++ )
773 pm_vars
->thePowerStates
[i
] = powerStates
[i
];
777 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriver
,
778 (unsigned long) numberOfStates
,(unsigned long) powerStates
[0].version
);
779 for ( i
= 0; i
< numberOfStates
; i
++ )
781 pm_vars
->thePowerStates
[i
].version
= powerStates
[i
].version
;
782 pm_vars
->thePowerStates
[i
].capabilityFlags
= powerStates
[i
].capabilityFlags
;
783 pm_vars
->thePowerStates
[i
].outputPowerCharacter
= powerStates
[i
].outputPowerCharacter
;
784 pm_vars
->thePowerStates
[i
].inputPowerRequirement
= powerStates
[i
].inputPowerRequirement
;
785 pm_vars
->thePowerStates
[i
].staticPower
= powerStates
[i
].staticPower
;
786 pm_vars
->thePowerStates
[i
].unbudgetedPower
= powerStates
[i
].unbudgetedPower
;
787 pm_vars
->thePowerStates
[i
].powerToAttain
= powerStates
[i
].powerToAttain
;
788 pm_vars
->thePowerStates
[i
].timeToAttain
= powerStates
[i
].timeToAttain
;
789 pm_vars
->thePowerStates
[i
].settleUpTime
= powerStates
[i
].settleUpTime
;
790 pm_vars
->thePowerStates
[i
].timeToLower
= powerStates
[i
].timeToLower
;
791 pm_vars
->thePowerStates
[i
].settleDownTime
= powerStates
[i
].settleDownTime
;
792 pm_vars
->thePowerStates
[i
].powerDomainBudget
= powerStates
[i
].powerDomainBudget
;
796 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr1
,
797 (unsigned long)powerStates
[0].version
,0);
801 // make a mask of all the character bits we know about
802 pm_vars
->myCharacterFlags
= 0;
803 for ( i
= 0; i
< numberOfStates
; i
++ ) {
804 pm_vars
->myCharacterFlags
|= pm_vars
->thePowerStates
[i
].outputPowerCharacter
;
807 pm_vars
->theNumberOfPowerStates
= numberOfStates
;
808 pm_vars
->theControllingDriver
= controllingDriver
;
809 if ( priv
->interestedDrivers
->findItem(controllingDriver
) == NULL
)
811 // register it as interested, unless already done
812 registerInterestedDriver (controllingDriver
);
814 if ( priv
->need_to_become_usable
) {
815 priv
->need_to_become_usable
= false;
816 priv
->deviceDesire
= pm_vars
->theNumberOfPowerStates
- 1;
819 if ( inPlane(gIOPowerPlane
) &&
820 (pm_vars
->parentsKnowState
) ) {
821 pm_vars
->maxCapability
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(pm_vars
->parentsCurrentPowerFlags
);
822 // initially change into the state we are already in
823 tempDesire
= priv
->deviceDesire
;
824 priv
->deviceDesire
= pm_vars
->theControllingDriver
->initialPowerStateForDomainState(pm_vars
->parentsCurrentPowerFlags
);
825 computeDesiredState();
827 // put this back like before
828 priv
->deviceDesire
= tempDesire
;
831 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr2
,(unsigned long)numberOfStates
,0);
834 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr4
,0,0);
839 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr5
,(unsigned long)numberOfStates
,0);
844 //*********************************************************************************
845 // registerInterestedDriver
847 // Add the caller to our list of interested drivers and return our current
848 // power state. If we don't have a power-controlling driver yet, we will
849 // call this interested driver again later when we do get a driver and find
850 // out what the current power state of the device is.
851 //*********************************************************************************
853 IOPMPowerFlags
IOService::registerInterestedDriver ( IOService
* theDriver
)
855 IOPMinformee
*newInformee
;
856 IOPMPowerFlags futureCapability
;
858 if (theDriver
== NULL
) {
862 // make new driver node
863 newInformee
= new IOPMinformee
;
864 newInformee
->initialize(theDriver
);
865 // add it to list of drivers
866 priv
->interestedDrivers
->addToList(newInformee
);
868 if ( (pm_vars
->theControllingDriver
== NULL
) ||
869 !(inPlane(gIOPowerPlane
)) ||
870 !(pm_vars
->parentsKnowState
) )
872 // can't tell it a state yet
873 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInterestedDriver
,IOPMNotPowerManaged
,0);
874 return IOPMNotPowerManaged
;
877 // can we notify new driver of a change in progress?
878 switch (priv
->machine_state
) {
879 case kIOPM_OurChangeSetPowerState
:
880 case kIOPM_OurChangeFinish
:
881 case kIOPM_ParentDownSetPowerState_Delayed
:
882 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
883 case kIOPM_ParentUpSetPowerState_Delayed
:
884 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
885 // yes, remember what we tell it
886 futureCapability
= priv
->head_note_capabilityFlags
;
887 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInterestedDriver
,(unsigned long)futureCapability
,1);
889 add_driver_to_active_change(newInformee
);
890 // and return the same thing
891 return futureCapability
;
894 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInterestedDriver
,
895 (unsigned long) pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
,2);
897 // no, return current capability
898 return pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
;
902 //*********************************************************************************
903 // deRegisterInterestedDriver
905 //*********************************************************************************
906 IOReturn
IOService::deRegisterInterestedDriver ( IOService
* theDriver
)
908 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRemoveDriver
,0,0);
910 // remove the departing driver
911 priv
->interestedDrivers
->removeFromList(theDriver
);
917 //*********************************************************************************
918 // acknowledgePowerChange
920 // After we notified one of the interested drivers or a power-domain child
921 // of an impending change in power, it has called to say it is now
922 // prepared for the change. If this object is the last to
923 // acknowledge this change, we take whatever action we have been waiting
925 // That may include acknowledging to our parent. In this case, we do it
926 // last of all to insure that this doesn't cause the parent to call us some-
927 // where else and alter data we are relying on here (like the very existance
928 // of a "current change note".)
929 //*********************************************************************************
931 IOReturn
IOService::acknowledgePowerChange ( IOService
* whichObject
)
933 IOPMinformee
*ackingObject
;
934 unsigned long childPower
= kIOPMUnknown
;
937 // one of our interested drivers?
938 ackingObject
= priv
->interestedDrivers
->findItem(whichObject
);
939 if ( ackingObject
== NULL
)
941 if ( ! isChild(whichObject
,gIOPowerPlane
) )
943 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr1
,0,0);
944 //kprintf("errant driver: %s\n",whichObject->getName());
948 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChildAcknowledge
,priv
->head_note_pendingAcks
,0);
951 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogDriverAcknowledge
,priv
->head_note_pendingAcks
,0);
954 if (! acquire_lock() )
959 if (priv
->head_note_pendingAcks
!= 0 )
961 // yes, make sure we're expecting acks
962 if ( ackingObject
!= NULL
)
964 // it's an interested driver
965 // make sure we're expecting this ack
966 if ( ackingObject
->timer
!= 0 )
969 ackingObject
->timer
= 0;
970 // that's one fewer to worry about
971 priv
->head_note_pendingAcks
-= 1;
973 if ( priv
->head_note_pendingAcks
== 0 )
975 // yes, stop the timer
977 IOUnlock(priv
->our_lock
);
978 // and now we can continue
983 // this driver has already acked
984 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr2
,0,0);
985 //kprintf("errant driver: %s\n",whichObject->getName());
989 // make sure we're expecting this ack
990 if ( ((IOPowerConnection
*)whichObject
)->getAwaitingAck() )
992 // that's one fewer to worry about
993 priv
->head_note_pendingAcks
-= 1;
994 ((IOPowerConnection
*)whichObject
)->setAwaitingAck(false);
995 theChild
= (IOService
*)whichObject
->copyChildEntry(gIOPowerPlane
);
998 childPower
= theChild
->currentPowerConsumption();
1001 if ( childPower
== kIOPMUnknown
)
1003 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
= kIOPMUnknown
;
1005 if ( pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
!= kIOPMUnknown
)
1007 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
+= childPower
;
1010 // is that the last?
1011 if ( priv
->head_note_pendingAcks
== 0 ) {
1012 // yes, stop the timer
1014 IOUnlock(priv
->our_lock
);
1015 // and now we can continue
1022 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr3
,0,0); // not expecting anybody to ack
1023 //kprintf("errant driver: %s\n",whichObject->getName());
1025 IOUnlock(priv
->our_lock
);
1029 //*********************************************************************************
1030 // acknowledgeSetPowerState
1032 // After we instructed our controlling driver to change power states,
1033 // it has called to say it has finished doing so.
1034 // We continue to process the power state change.
1035 //*********************************************************************************
1037 IOReturn
IOService::acknowledgeSetPowerState ( void )
1039 if (! acquire_lock() )
1044 ioSPMTrace(IOPOWER_ACK
, * (int *) this);
1046 if ( priv
->driver_timer
== -1 )
1048 // driver is acking instead of using return code
1049 priv
->driver_timer
= 0;
1051 // are we expecting this?
1052 if ( priv
->driver_timer
> 0 )
1054 // yes, stop the timer
1056 priv
->driver_timer
= 0;
1057 IOUnlock(priv
->our_lock
);
1058 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogDriverAcknowledgeSet
,0,0);
1062 // not expecting this
1063 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr4
,0,0);
1066 IOUnlock(priv
->our_lock
);
1071 //*********************************************************************************
1074 // Either the controlling driver has called acknowledgeSetPowerState
1075 // or the acknowledgement timer has expired while waiting for that.
1076 // We carry on processing the current change note.
1077 //*********************************************************************************
1079 void IOService::driver_acked ( void )
1081 switch (priv
->machine_state
) {
1082 case kIOPM_OurChangeWaitForPowerSettle
:
1083 OurChangeWaitForPowerSettle();
1085 case kIOPM_ParentDownWaitForPowerSettle_Delayed
:
1086 ParentDownWaitForPowerSettle_Delayed();
1088 case kIOPM_ParentUpWaitForSettleTime_Delayed
:
1089 ParentUpWaitForSettleTime_Delayed();
1095 //*********************************************************************************
1096 // powerDomainWillChangeTo
1098 // Called by the power-hierarchy parent notifying of a new power state
1099 // in the power domain.
1100 // We enqueue a parent power-change to our queue of power changes.
1101 // This may or may not cause us to change power, depending on what
1102 // kind of change is occuring in the domain.
1103 //*********************************************************************************
1105 IOReturn
IOService::powerDomainWillChangeTo ( IOPMPowerFlags newPowerStateFlags
, IOPowerConnection
* whichParent
)
1109 IOPowerConnection
*connection
;
1110 unsigned long newStateNumber
;
1111 IOPMPowerFlags combinedPowerFlags
;
1113 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogWillChange
,(unsigned long)newPowerStateFlags
,0);
1115 if ( ! inPlane(gIOPowerPlane
) )
1118 return IOPMAckImplied
;
1121 IOLockLock(pm_vars
->parentLock
);
1123 if ( (pm_vars
->PMworkloop
== NULL
) || (pm_vars
->PMcommandGate
== NULL
) )
1125 // we have a path to the root
1127 // so find out the workloop
1128 if ( pm_vars
->PMworkloop
!= NULL
)
1130 // and make our command gate
1131 if ( pm_vars
->PMcommandGate
== NULL
)
1133 pm_vars
->PMcommandGate
= IOCommandGate::commandGate((OSObject
*)this);
1134 if ( pm_vars
->PMcommandGate
!= NULL
)
1136 pm_vars
->PMworkloop
->addEventSource(pm_vars
->PMcommandGate
);
1142 IOLockUnlock(pm_vars
->parentLock
);
1144 // combine parents' power states
1145 // to determine our maximum state within the new power domain
1146 combinedPowerFlags
= 0;
1148 iter
= getParentIterator(gIOPowerPlane
);
1152 while ( (next
= iter
->getNextObject()) )
1154 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1156 if ( connection
== whichParent
){
1157 combinedPowerFlags
|= newPowerStateFlags
;
1159 combinedPowerFlags
|= connection
->parentCurrentPowerFlags();
1166 if ( pm_vars
->theControllingDriver
== NULL
)
1168 // we can't take any more action
1169 return IOPMAckImplied
;
1171 newStateNumber
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(combinedPowerFlags
);
1173 return enqueuePowerChange(IOPMParentInitiated
| IOPMDomainWillChange
,
1174 newStateNumber
,combinedPowerFlags
,whichParent
,newPowerStateFlags
);
1178 //*********************************************************************************
1179 // powerDomainDidChangeTo
1181 // Called by the power-hierarchy parent after the power state of the power domain
1182 // has settled at a new level.
1183 // We enqueue a parent power-change to our queue of power changes.
1184 // This may or may not cause us to change power, depending on what
1185 // kind of change is occuring in the domain.
1186 //*********************************************************************************
1188 IOReturn
IOService::powerDomainDidChangeTo ( IOPMPowerFlags newPowerStateFlags
, IOPowerConnection
* whichParent
)
1190 unsigned long newStateNumber
;
1192 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogDidChange
,newPowerStateFlags
,0);
1194 setParentInfo(newPowerStateFlags
,whichParent
);
1196 if ( pm_vars
->theControllingDriver
== NULL
) {
1197 return IOPMAckImplied
;
1200 newStateNumber
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(pm_vars
->parentsCurrentPowerFlags
);
1201 // tell interested parties about it
1202 return enqueuePowerChange(IOPMParentInitiated
| IOPMDomainDidChange
,
1203 newStateNumber
,pm_vars
->parentsCurrentPowerFlags
,whichParent
,0);
1207 //*********************************************************************************
1210 // Set our connection data for one specific parent, and then combine all the parent
1212 //*********************************************************************************
1214 void IOService::setParentInfo ( IOPMPowerFlags newPowerStateFlags
, IOPowerConnection
* whichParent
)
1218 IOPowerConnection
*connection
;
1220 // set our connection data
1221 whichParent
->setParentCurrentPowerFlags(newPowerStateFlags
);
1222 whichParent
->setParentKnowsState(true);
1224 IOLockLock(pm_vars
->parentLock
);
1226 // recompute our parent info
1227 pm_vars
->parentsCurrentPowerFlags
= 0;
1228 pm_vars
->parentsKnowState
= true;
1230 iter
= getParentIterator(gIOPowerPlane
);
1234 while ( (next
= iter
->getNextObject()) )
1236 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1238 pm_vars
->parentsKnowState
&= connection
->parentKnowsState();
1239 pm_vars
->parentsCurrentPowerFlags
|= connection
->parentCurrentPowerFlags();
1244 IOLockUnlock(pm_vars
->parentLock
);
1247 //*********************************************************************************
1248 // rebuildChildClampBits
1250 // The ChildClamp bits (kIOPMChildClamp & kIOPMChildClamp2) in our capabilityFlags
1251 // indicate that one of our children (or grandchildren or great-grandchildren or ...)
1252 // doesn't support idle or system sleep in its current state. Since we don't track the
1253 // origin of each bit, every time any child changes state we have to clear these bits
1254 // and rebuild them.
1255 //*********************************************************************************
1257 void IOService::rebuildChildClampBits(void)
1262 IOPowerConnection
*connection
;
1265 // A child's desires has changed. We need to rebuild the child-clamp bits in our
1266 // power state array. Start by clearing the bits in each power state.
1268 for ( i
= 0; i
< pm_vars
->theNumberOfPowerStates
; i
++ )
1270 pm_vars
->thePowerStates
[i
].capabilityFlags
&= ~(kIOPMChildClamp
| kIOPMChildClamp2
);
1273 // Now loop through the children. When we encounter the calling child, save
1274 // the computed state as this child's desire. And while we're at it, set the ChildClamp bits
1275 // in any of our states that some child has requested with clamp on.
1277 iter
= getChildIterator(gIOPowerPlane
);
1281 while ( (next
= iter
->getNextObject()) )
1283 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1285 if ( connection
->getPreventIdleSleepFlag() )
1286 pm_vars
->thePowerStates
[connection
->getDesiredDomainState()].capabilityFlags
|= kIOPMChildClamp
;
1287 if ( connection
->getPreventSystemSleepFlag() )
1288 pm_vars
->thePowerStates
[connection
->getDesiredDomainState()].capabilityFlags
|= kIOPMChildClamp2
;
1297 //*********************************************************************************
1298 // requestPowerDomainState
1300 // The kIOPMPreventIdleSleep and/or kIOPMPreventIdleSleep bits may be be set in the parameter.
1301 // It is not considered part of the state specification.
1302 //*********************************************************************************
1303 IOReturn
IOService::requestPowerDomainState ( IOPMPowerFlags desiredState
, IOPowerConnection
* whichChild
, unsigned long specification
)
1306 unsigned long computedState
;
1307 unsigned long theDesiredState
= desiredState
& ~(kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
1310 IOPowerConnection
*connection
;
1312 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRequestDomain
,
1313 (unsigned long)desiredState
,(unsigned long)specification
);
1315 if ( pm_vars
->theControllingDriver
== NULL
)
1317 return IOPMNotYetInitialized
;
1320 switch (specification
) {
1321 case IOPMLowestState
:
1323 while ( i
< pm_vars
->theNumberOfPowerStates
)
1325 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1331 if ( i
>= pm_vars
->theNumberOfPowerStates
)
1333 return IOPMNoSuchState
;
1337 case IOPMNextLowerState
:
1338 i
= pm_vars
->myCurrentState
- 1;
1341 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1349 return IOPMNoSuchState
;
1353 case IOPMHighestState
:
1354 i
= pm_vars
->theNumberOfPowerStates
;
1358 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1365 return IOPMNoSuchState
;
1369 case IOPMNextHigherState
:
1370 i
= pm_vars
->myCurrentState
+ 1;
1371 while ( i
< pm_vars
->theNumberOfPowerStates
)
1373 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1379 if ( i
== pm_vars
->theNumberOfPowerStates
)
1381 return IOPMNoSuchState
;
1386 return IOPMBadSpecification
;
1391 IOLockLock(pm_vars
->childLock
);
1393 // Now loop through the children. When we encounter the calling child, save
1394 // the computed state as this child's desire.
1395 iter
= getChildIterator(gIOPowerPlane
);
1399 while ( (next
= iter
->getNextObject()) )
1401 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1403 if ( connection
== whichChild
)
1405 connection
->setDesiredDomainState(computedState
);
1406 connection
->setPreventIdleSleepFlag(desiredState
& kIOPMPreventIdleSleep
);
1407 connection
->setPreventSystemSleepFlag(desiredState
& kIOPMPreventSystemSleep
);
1408 connection
->setChildHasRequestedPower();
1415 // Since a child's power requirements may have changed, clear and rebuild
1416 // kIOPMChildClamp and kIOPMChildClamp2 (idle and system sleep clamps)
1417 rebuildChildClampBits();
1419 IOLockUnlock(pm_vars
->childLock
);
1421 // this may be different now
1422 computeDesiredState();
1424 if ( inPlane(gIOPowerPlane
) &&
1425 (pm_vars
->parentsKnowState
) ) {
1426 // change state if all children can now tolerate lower power
1430 // are we clamped on, waiting for this child?
1431 if ( priv
->clampOn
) {
1432 // yes, remove the clamp
1433 priv
->clampOn
= false;
1434 changePowerStateToPriv(0);
1441 //*********************************************************************************
1442 // temporaryPowerClampOn
1444 // A power domain wants to clamp its power on till it has children which
1445 // will thendetermine the power domain state.
1447 // We enter the highest state until addPowerChild is called.
1448 //*********************************************************************************
1450 IOReturn
IOService::temporaryPowerClampOn ( void )
1452 priv
->clampOn
= true;
1458 //*********************************************************************************
1461 // Some client of our device is asking that we become usable. Although
1462 // this has not come from a subclassed device object, treat it exactly
1463 // as if it had. In this way, subsequent requests for lower power from
1464 // a subclassed device object will pre-empt this request.
1466 // We treat this as a subclass object request to switch to the
1467 // highest power state.
1468 //*********************************************************************************
1470 IOReturn
IOService::makeUsable ( void )
1472 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogMakeUsable
,0,0);
1474 if ( pm_vars
->theControllingDriver
== NULL
)
1476 priv
->need_to_become_usable
= true;
1479 priv
->deviceDesire
= pm_vars
->theNumberOfPowerStates
- 1;
1480 computeDesiredState();
1481 if ( inPlane(gIOPowerPlane
) && (pm_vars
->parentsKnowState
) )
1483 return changeState();
1489 //*********************************************************************************
1490 // currentCapability
1492 //*********************************************************************************
1494 IOPMPowerFlags
IOService::currentCapability ( void )
1496 if ( pm_vars
->theControllingDriver
== NULL
)
1500 return pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
;
1505 //*********************************************************************************
1506 // changePowerStateTo
1508 // For some reason, our power-controlling driver has decided it needs to change
1509 // power state. We enqueue the power change so that appropriate parties
1510 // will be notified, and then we will instruct the driver to make the change.
1511 //*********************************************************************************
1513 IOReturn
IOService::changePowerStateTo ( unsigned long ordinal
)
1515 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeStateTo
,ordinal
,0);
1517 if ( ordinal
>= pm_vars
->theNumberOfPowerStates
)
1519 return IOPMParameterError
;
1521 priv
->driverDesire
= ordinal
;
1522 computeDesiredState();
1523 if ( inPlane(gIOPowerPlane
) && (pm_vars
->parentsKnowState
) )
1525 return changeState();
1531 //*********************************************************************************
1532 // changePowerStateToPriv
1534 // For some reason, a subclassed device object has decided it needs to change
1535 // power state. We enqueue the power change so that appropriate parties
1536 // will be notified, and then we will instruct the driver to make the change.
1537 //*********************************************************************************
1539 IOReturn
IOService::changePowerStateToPriv ( unsigned long ordinal
)
1541 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeStateToPriv
,ordinal
,0);
1543 if ( pm_vars
->theControllingDriver
== NULL
)
1545 return IOPMNotYetInitialized
;
1547 if ( ordinal
>= pm_vars
->theNumberOfPowerStates
)
1549 return IOPMParameterError
;
1551 priv
->deviceDesire
= ordinal
;
1552 computeDesiredState();
1553 if ( inPlane(gIOPowerPlane
) && (pm_vars
->parentsKnowState
) )
1555 return changeState();
1562 //*********************************************************************************
1563 // computeDesiredState
1565 //*********************************************************************************
1567 void IOService::computeDesiredState ( void )
1571 IOPowerConnection
*connection
;
1572 unsigned long newDesiredState
= 0;
1574 // Compute the maximum of our children's desires, our controlling driver's desire, and the subclass device's desire.
1575 if ( ! priv
->device_overrides
)
1577 iter
= getChildIterator(gIOPowerPlane
);
1581 while ( (next
= iter
->getNextObject()) )
1583 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1585 if ( connection
->getDesiredDomainState() > newDesiredState
)
1587 newDesiredState
= connection
->getDesiredDomainState();
1594 if ( priv
->driverDesire
> newDesiredState
)
1596 newDesiredState
= priv
->driverDesire
;
1600 if ( priv
->deviceDesire
> newDesiredState
)
1602 newDesiredState
= priv
->deviceDesire
;
1605 priv
->ourDesiredPowerState
= newDesiredState
;
1609 //*********************************************************************************
1612 // A subclass object, our controlling driver, or a power domain child
1613 // has asked for a different power state. Here we compute what new
1614 // state we should enter and enqueue the change (or start it).
1615 //*********************************************************************************
1617 IOReturn
IOService::changeState ( void )
1619 // if not fully initialized
1620 if ( (pm_vars
->theControllingDriver
== NULL
) ||
1621 !(inPlane(gIOPowerPlane
)) ||
1622 !(pm_vars
->parentsKnowState
) )
1624 // we can do no more
1628 return enqueuePowerChange(IOPMWeInitiated
,priv
->ourDesiredPowerState
,0,0,0);
1632 //*********************************************************************************
1633 // currentPowerConsumption
1635 //*********************************************************************************
1637 unsigned long IOService::currentPowerConsumption ( void )
1639 if ( pm_vars
->theControllingDriver
== NULL
)
1641 return kIOPMUnknown
;
1643 if ( pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
& kIOPMStaticPowerValid
)
1645 return pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].staticPower
;
1647 return kIOPMUnknown
;
1650 //*********************************************************************************
1653 // The activity tickle with parameter kIOPMSubclassPolicyis not handled
1654 // here and should have been intercepted by the subclass.
1655 // The tickle with parameter kIOPMSuperclassPolicy1 causes the activity
1656 // flag to be set, and the device state checked. If the device has been
1657 // powered down, it is powered up again.
1658 //*********************************************************************************
1660 bool IOService::activityTickle ( unsigned long type
, unsigned long stateNumber
)
1662 IOPMrootDomain
*pmRootDomain
;
1663 AbsoluteTime uptime
;
1665 if ( type
== kIOPMSuperclassPolicy1
)
1667 if ( pm_vars
->theControllingDriver
== NULL
)
1672 if( priv
->activityLock
== NULL
)
1674 priv
->activityLock
= IOLockAlloc();
1677 IOTakeLock(priv
->activityLock
);
1678 priv
->device_active
= true;
1680 clock_get_uptime(&uptime
);
1681 priv
->device_active_timestamp
= uptime
;
1683 if ( pm_vars
->myCurrentState
>= stateNumber
)
1685 IOUnlock(priv
->activityLock
);
1688 IOUnlock(priv
->activityLock
);
1690 // Transfer execution to the PM workloop
1691 if( (pmRootDomain
= getPMRootDomain()) )
1692 pmRootDomain
->unIdleDevice(this, stateNumber
);
1699 //*********************************************************************************
1702 // A child is calling to get a pointer to the Power Management workloop.
1703 // We got it or get it from one of our parents.
1704 //*********************************************************************************
1706 IOWorkLoop
* IOService::getPMworkloop ( void )
1711 if ( ! inPlane(gIOPowerPlane
) )
1715 // we have no workloop yet
1716 if ( pm_vars
->PMworkloop
== NULL
)
1718 nub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
1721 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
1723 // ask one of our parents for the workloop
1726 pm_vars
->PMworkloop
= parent
->getPMworkloop();
1731 return pm_vars
->PMworkloop
;
1735 //*********************************************************************************
1736 // setIdleTimerPeriod
1738 // A subclass policy-maker is going to use our standard idleness
1739 // detection service. Make a command queue and an idle timer and
1740 // connect them to the power management workloop. Finally,
1742 //*********************************************************************************
1744 IOReturn
IOService::setIdleTimerPeriod ( unsigned long period
)
1746 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMsetIdleTimerPeriod
,period
, 0);
1748 priv
->idle_timer_period
= period
;
1752 if ( getPMworkloop() == NULL
)
1754 return kIOReturnError
;
1757 // make the timer event
1758 if ( priv
->timerEventSrc
== NULL
)
1760 priv
->timerEventSrc
= IOTimerEventSource::timerEventSource(this,
1761 PM_idle_timer_expired
);
1762 if ((!priv
->timerEventSrc
) ||
1763 (pm_vars
->PMworkloop
->addEventSource(priv
->timerEventSrc
) != kIOReturnSuccess
) )
1765 return kIOReturnError
;
1769 if ( priv
->activityLock
== NULL
)
1771 priv
->activityLock
= IOLockAlloc();
1774 start_PM_idle_timer();
1780 //*********************************************************************************
1781 // start_PM_idle_timer
1783 // The parameter is a pointer to us. Use it to call our timeout method.
1784 //*********************************************************************************
1785 void IOService::start_PM_idle_timer ( void )
1787 AbsoluteTime uptime
;
1793 IOLockLock(priv
->activityLock
);
1795 clock_get_uptime(&uptime
);
1797 // Calculate time difference using funky macro from clock.h.
1799 SUB_ABSOLUTETIME(&delta
, &(priv
->device_active_timestamp
));
1801 // Figure it in seconds.
1802 absolutetime_to_nanoseconds(delta
, &delta_ns
);
1803 delta_secs
= delta_ns
/ NSEC_PER_SEC
;
1805 // Be paranoid about delta somehow exceeding timer period.
1806 if (delta_secs
< priv
->idle_timer_period
)
1808 delay_secs
= priv
->idle_timer_period
- delta_secs
;
1810 delay_secs
= priv
->idle_timer_period
;
1813 priv
->timerEventSrc
->setTimeout(delay_secs
, NSEC_PER_SEC
);
1815 IOLockUnlock(priv
->activityLock
);
1820 //*********************************************************************************
1821 // PM_idle_timer_expired
1823 // The parameter is a pointer to us. Use it to call our timeout method.
1824 //*********************************************************************************
1826 void PM_idle_timer_expired(OSObject
* ourSelves
, IOTimerEventSource
*)
1828 ((IOService
*)ourSelves
)->PM_idle_timer_expiration();
1832 //*********************************************************************************
1833 // PM_idle_timer_expiration
1835 // The idle timer has expired. If there has been activity since the last
1836 // expiration, just restart the timer and return. If there has not been
1837 // activity, switch to the next lower power state and restart the timer.
1838 //*********************************************************************************
1840 void IOService::PM_idle_timer_expiration ( void )
1842 if ( ! initialized
)
1848 if ( priv
->idle_timer_period
> 0 )
1850 IOTakeLock(priv
->activityLock
);
1851 if ( priv
->device_active
)
1853 priv
->device_active
= false;
1854 IOUnlock(priv
->activityLock
);
1855 start_PM_idle_timer();
1858 if ( pm_vars
->myCurrentState
> 0 )
1860 IOUnlock(priv
->activityLock
);
1861 changePowerStateToPriv(pm_vars
->myCurrentState
- 1);
1862 start_PM_idle_timer();
1865 IOUnlock(priv
->activityLock
);
1866 start_PM_idle_timer();
1871 // **********************************************************************************
1874 // We are un-idling a device due to its activity tickle. This routine runs on the
1875 // PM workloop, and is initiated by IOService::activityTickle.
1876 // We process all activityTickle state requests on the list.
1877 // **********************************************************************************
1878 void IOService::command_received ( void *statePtr
, void *, void * , void * )
1880 unsigned long stateNumber
;
1882 stateNumber
= (unsigned long)statePtr
;
1884 // If not initialized, we're unloading
1885 if ( ! initialized
) return;
1887 if ( (pm_vars
->myCurrentState
< stateNumber
) &&
1888 (priv
->imminentState
< stateNumber
) )
1890 changePowerStateToPriv(stateNumber
);
1895 //*********************************************************************************
1896 // setAggressiveness
1898 // Pass on the input parameters to all power domain children. All those which are
1899 // power domains will pass it on to their children, etc.
1900 //*********************************************************************************
1902 IOReturn
IOService::setAggressiveness ( unsigned long type
, unsigned long newLevel
)
1906 IOPowerConnection
*connection
;
1909 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogSetAggressiveness
,type
, newLevel
);
1911 if ( type
<= kMaxType
)
1913 pm_vars
->current_aggressiveness_values
[type
] = newLevel
;
1914 pm_vars
->current_aggressiveness_valid
[type
] = true;
1917 iter
= getChildIterator(gIOPowerPlane
);
1921 while ( (next
= iter
->getNextObject()) )
1923 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1925 child
= ((IOService
*)(connection
->copyChildEntry(gIOPowerPlane
)));
1928 child
->setAggressiveness(type
, newLevel
);
1939 //*********************************************************************************
1940 // getAggressiveness
1942 // Called by the user client.
1943 //*********************************************************************************
1945 IOReturn
IOService::getAggressiveness ( unsigned long type
, unsigned long * currentLevel
)
1947 // if ( type > kMaxType )
1948 // return kIOReturnBadArgument;
1950 if ( !pm_vars
->current_aggressiveness_valid
[type
] )
1951 return kIOReturnInvalid
;
1953 *currentLevel
= pm_vars
->current_aggressiveness_values
[type
];
1955 return kIOReturnSuccess
;
1958 //*********************************************************************************
1961 // Pass this to all power domain children. All those which are
1962 // power domains will pass it on to their children, etc.
1963 //*********************************************************************************
1965 IOReturn
IOService::systemWake ( void )
1969 IOPowerConnection
*connection
;
1970 IOService
*theChild
;
1972 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogSystemWake
,0, 0);
1974 iter
= getChildIterator(gIOPowerPlane
);
1978 while ( (next
= iter
->getNextObject()) )
1980 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1982 theChild
= (IOService
*)connection
->copyChildEntry(gIOPowerPlane
);
1985 theChild
->systemWake();
1986 theChild
->release();
1993 if ( pm_vars
->theControllingDriver
!= NULL
)
1995 if ( pm_vars
->theControllingDriver
->didYouWakeSystem() )
2005 //*********************************************************************************
2006 // temperatureCriticalForZone
2008 //*********************************************************************************
2010 IOReturn
IOService::temperatureCriticalForZone ( IOService
* whichZone
)
2012 IOService
*theParent
;
2015 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogCriticalTemp
,0,0);
2017 if ( inPlane(gIOPowerPlane
) && !(priv
->we_are_root
) )
2019 theNub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
2022 theParent
= (IOService
*)theNub
->copyParentEntry(gIOPowerPlane
);
2026 theParent
->temperatureCriticalForZone(whichZone
);
2027 theParent
->release();
2035 //*********************************************************************************
2036 // powerOverrideOnPriv
2038 //*********************************************************************************
2041 IOReturn
IOService::powerOverrideOnPriv ( void )
2043 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogOverrideOn
,0,0);
2045 // turn on the override
2046 priv
->device_overrides
= true;
2047 computeDesiredState();
2049 // change state if that changed something
2050 return changeState();
2054 //*********************************************************************************
2055 // powerOverrideOffPriv
2057 //*********************************************************************************
2058 IOReturn
IOService::powerOverrideOffPriv ( void )
2060 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogOverrideOff
,0,0);
2062 // turn off the override
2063 priv
->device_overrides
= false;
2064 computeDesiredState();
2067 return makeUsable();
2069 // change state if that changed something
2070 return changeState();
2075 //*********************************************************************************
2076 // enqueuePowerChange
2078 // Allocate a new state change notification, initialize it with fields from the
2079 // caller, and add it to the tail of the list of pending power changes.
2081 // If it is early enough in the list, and almost all the time it is the only one in
2082 // the list, start the power change.
2084 // In rare instances, this change will preempt the previous change in the list.
2085 // If the previous change is un-actioned in any way (because we are still
2086 // processing an even earlier power change), and if both the previous change
2087 // in the list and this change are initiated by us (not the parent), then we
2088 // needn't perform the previous change, so we collapse the list a little.
2089 //*********************************************************************************
2091 IOReturn
IOService::enqueuePowerChange ( unsigned long flags
, unsigned long whatStateOrdinal
, unsigned long domainState
, IOPowerConnection
* whichParent
, unsigned long singleParentState
)
2096 // Create and initialize the new change note
2098 IOLockLock(priv
->queue_lock
);
2099 newNote
= priv
->changeList
->createChangeNote();
2100 if ( newNote
== -1 ) {
2101 // uh-oh, our list is full
2102 IOLockUnlock(priv
->queue_lock
);
2103 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogEnqueueErr
,0,0);
2104 return IOPMAckImplied
;
2107 priv
->changeList
->changeNote
[newNote
].newStateNumber
= whatStateOrdinal
;
2108 priv
->changeList
->changeNote
[newNote
].outputPowerCharacter
= pm_vars
->thePowerStates
[whatStateOrdinal
].outputPowerCharacter
;
2109 priv
->changeList
->changeNote
[newNote
].inputPowerRequirement
= pm_vars
->thePowerStates
[whatStateOrdinal
].inputPowerRequirement
;
2110 priv
->changeList
->changeNote
[newNote
].capabilityFlags
= pm_vars
->thePowerStates
[whatStateOrdinal
].capabilityFlags
;
2111 priv
->changeList
->changeNote
[newNote
].flags
= flags
;
2112 priv
->changeList
->changeNote
[newNote
].parent
= NULL
;
2113 if (flags
& IOPMParentInitiated
)
2115 priv
->changeList
->changeNote
[newNote
].domainState
= domainState
;
2116 priv
->changeList
->changeNote
[newNote
].parent
= whichParent
;
2117 whichParent
->retain();
2118 priv
->changeList
->changeNote
[newNote
].singleParentState
= singleParentState
;
2121 previousNote
= priv
->changeList
->previousChangeNote(newNote
);
2123 if ( previousNote
== -1 )
2126 // Queue is empty, we can start this change.
2128 if (flags
& IOPMWeInitiated
)
2130 IOLockUnlock(priv
->queue_lock
);
2131 start_our_change(newNote
);
2134 IOLockUnlock(priv
->queue_lock
);
2135 return start_parent_change(newNote
);
2139 // The queue is not empty. Try to collapse this new change and the previous one in queue into one change.
2140 // This is possible only if both changes are initiated by us, and neither has been started yet.
2141 // Do this more than once if possible.
2143 // (A change is started iff it is at the head of the queue)
2145 while ( (previousNote
!= priv
->head_note
) && (previousNote
!= -1) &&
2146 (priv
->changeList
->changeNote
[newNote
].flags
& priv
->changeList
->changeNote
[previousNote
].flags
& IOPMWeInitiated
) )
2148 priv
->changeList
->changeNote
[previousNote
].outputPowerCharacter
= priv
->changeList
->changeNote
[newNote
].outputPowerCharacter
;
2149 priv
->changeList
->changeNote
[previousNote
].inputPowerRequirement
= priv
->changeList
->changeNote
[newNote
].inputPowerRequirement
;
2150 priv
->changeList
->changeNote
[previousNote
].capabilityFlags
=priv
-> changeList
->changeNote
[newNote
].capabilityFlags
;
2151 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogCollapseQueue
,priv
->changeList
->changeNote
[newNote
].newStateNumber
,
2152 priv
->changeList
->changeNote
[previousNote
].newStateNumber
);
2153 priv
->changeList
->changeNote
[previousNote
].newStateNumber
= priv
->changeList
->changeNote
[newNote
].newStateNumber
;
2154 priv
->changeList
->releaseTailChangeNote();
2155 newNote
= previousNote
;
2156 previousNote
= priv
->changeList
->previousChangeNote(newNote
);
2158 IOLockUnlock(priv
->queue_lock
);
2159 // in any case, we can't start yet
2160 return IOPMWillAckLater
;
2163 //*********************************************************************************
2166 // Notify all interested parties either that a change is impending or that the
2167 // previously-notified change is done and power has settled.
2168 // The parameter identifies whether this is the
2169 // pre-change notification or the post-change notification.
2171 //*********************************************************************************
2173 IOReturn
IOService::notifyAll ( bool is_prechange
)
2175 IOPMinformee
* nextObject
;
2178 IOPowerConnection
* connection
;
2180 // To prevent acknowledgePowerChange from finishing the change note and removing it from the queue if
2181 // some driver calls it, we inflate the number of pending acks so it cannot become zero. We'll fix it later.
2183 priv
->head_note_pendingAcks
=1;
2185 // OK, we will go through the lists of interested drivers and power domain children
2186 // and notify each one of this change.
2188 nextObject
= priv
->interestedDrivers
->firstInList();
2189 while ( nextObject
!= NULL
) {
2190 priv
->head_note_pendingAcks
+=1;
2191 if (! inform(nextObject
, is_prechange
) )
2194 nextObject
= priv
->interestedDrivers
->nextInList(nextObject
);
2197 if (! acquire_lock() ) {
2200 // did they all ack?
2201 if ( priv
->head_note_pendingAcks
> 1 ) {
2203 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2207 IOUnlock(priv
->our_lock
);
2210 iter
= getChildIterator(gIOPowerPlane
);
2211 // summing their power consumption
2212 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
= 0;
2216 while ( (next
= iter
->getNextObject()) )
2218 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
2220 priv
->head_note_pendingAcks
+=1;
2221 notifyChild(connection
, is_prechange
);
2227 if (! acquire_lock() ) {
2230 // now make this real
2231 priv
->head_note_pendingAcks
-= 1;
2233 if (priv
->head_note_pendingAcks
== 0 ) {
2235 IOUnlock(priv
->our_lock
);
2236 // return ack to parent
2237 return IOPMAckImplied
;
2241 IOUnlock(priv
->our_lock
);
2242 return IOPMWillAckLater
;
2246 //*********************************************************************************
2249 // Notify a power domain child of an upcoming power change.
2251 // If the object acknowledges the current change, we return TRUE.
2252 //*********************************************************************************
2254 bool IOService::notifyChild ( IOPowerConnection
* theNub
, bool is_prechange
)
2256 IOReturn k
= IOPMAckImplied
;
2257 unsigned long childPower
;
2258 IOService
*theChild
= (IOService
*)(theNub
->copyChildEntry(gIOPowerPlane
));
2260 theNub
->setAwaitingAck(true); // in case they don't ack
2269 k
= theChild
->powerDomainWillChangeTo(priv
->head_note_outputFlags
,theNub
);
2271 k
= theChild
->powerDomainDidChangeTo(priv
->head_note_outputFlags
,theNub
);
2274 // did the return code ack?
2275 if ( k
== IOPMAckImplied
)
2278 priv
->head_note_pendingAcks
-=1;
2279 theNub
->setAwaitingAck(false);
2280 childPower
= theChild
->currentPowerConsumption();
2281 if ( childPower
== kIOPMUnknown
)
2283 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
= kIOPMUnknown
;
2285 if ( pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
!= kIOPMUnknown
)
2287 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
+= childPower
;
2290 theChild
->release();
2293 theChild
->release();
2298 //*********************************************************************************
2301 // Notify an interested driver of an upcoming power change.
2303 // If the object acknowledges the current change, we return TRUE.
2304 //*********************************************************************************
2306 bool IOService::inform ( IOPMinformee
* nextObject
, bool is_prechange
)
2308 IOReturn k
= IOPMAckImplied
;
2311 nextObject
->timer
= -1;
2315 pm_vars
->thePlatform
->PMLog (pm_vars
->ourName
,PMlogInformDriverPreChange
,
2316 (unsigned long)priv
->head_note_capabilityFlags
,(unsigned long)priv
->head_note_state
);
2317 k
= nextObject
->whatObject
->powerStateWillChangeTo( priv
->head_note_capabilityFlags
,priv
->head_note_state
,this);
2319 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInformDriverPostChange
,
2320 (unsigned long)priv
->head_note_capabilityFlags
,(unsigned long)priv
->head_note_state
);
2321 k
= nextObject
->whatObject
->powerStateDidChangeTo(priv
->head_note_capabilityFlags
,priv
->head_note_state
,this);
2324 // did it ack behind our back?
2325 if ( nextObject
->timer
== 0 )
2331 // no, did the return code ack?
2332 if ( k
==IOPMAckImplied
)
2335 nextObject
->timer
= 0;
2336 priv
->head_note_pendingAcks
-= 1;
2342 nextObject
->timer
= 0;
2343 priv
-> head_note_pendingAcks
-= 1;
2348 nextObject
->timer
= (k
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
2354 //*********************************************************************************
2355 // OurChangeTellClientsPowerDown
2357 // All registered applications and kernel clients have positively acknowledged our
2358 // intention of lowering power. Here we notify them all that we will definitely
2359 // lower the power. If we don't have to wait for any of them to acknowledge, we
2360 // carry on by notifying interested drivers. Otherwise, we do wait.
2361 //*********************************************************************************
2363 void IOService::OurChangeTellClientsPowerDown ( void )
2366 priv
->machine_state
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
2368 // are we waiting for responses?
2369 if ( tellChangeDown1(priv
->head_note_state
) )
2371 // no, notify priority clients
2372 OurChangeTellPriorityClientsPowerDown();
2374 // If we are waiting for responses, execution will resume via
2375 // allowCancelCommon() or ack timeout
2379 //*********************************************************************************
2380 // OurChangeTellPriorityClientsPowerDown
2382 // All registered applications and kernel clients have positively acknowledged our
2383 // intention of lowering power. Here we notify "priority" clients that we are
2384 // lowering power. If we don't have to wait for any of them to acknowledge, we
2385 // carry on by notifying interested drivers. Otherwise, we do wait.
2386 //*********************************************************************************
2388 void IOService::OurChangeTellPriorityClientsPowerDown ( void )
2391 priv
->machine_state
= kIOPM_OurChangeNotifyInterestedDriversWillChange
;
2392 // are we waiting for responses?
2393 if ( tellChangeDown2(priv
->head_note_state
) )
2395 // no, notify interested drivers
2396 return OurChangeNotifyInterestedDriversWillChange();
2398 // If we are waiting for responses, execution will resume via
2399 // allowCancelCommon() or ack timeout
2403 //*********************************************************************************
2404 // OurChangeNotifyInterestedDriversWillChange
2406 // All registered applications and kernel clients have acknowledged our notification
2407 // that we are lowering power. Here we notify interested drivers. If we don't have
2408 // to wait for any of them to acknowledge, we instruct our power driver to make the change.
2409 // Otherwise, we do wait.
2410 //*********************************************************************************
2412 void IOService::OurChangeNotifyInterestedDriversWillChange ( void )
2414 // no, in case they don't all ack
2415 priv
->machine_state
= kIOPM_OurChangeSetPowerState
;
2416 if ( notifyAll(true) == IOPMAckImplied
)
2418 // not waiting for responses
2419 OurChangeSetPowerState();
2421 // If we are waiting for responses, execution will resume via
2422 // all_acked() or ack timeout
2426 //*********************************************************************************
2427 // OurChangeSetPowerState
2429 // All interested drivers have acknowledged our pre-change notification of a power
2430 // change we initiated. Here we instruct our controlling driver to make
2431 // the change to the hardware. If it does so, we continue processing
2432 // (waiting for settle and notifying interested parties post-change.)
2433 // If it doesn't, we have to wait for it to acknowledge and then continue.
2434 //*********************************************************************************
2436 void IOService::OurChangeSetPowerState ( void )
2438 priv
->machine_state
= kIOPM_OurChangeWaitForPowerSettle
;
2440 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2442 // it's done, carry on
2443 OurChangeWaitForPowerSettle();
2445 // it's not, wait for it
2446 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2448 // execution will resume via ack_timer_ticked()
2453 //*********************************************************************************
2454 // OurChangeWaitForPowerSettle
2456 // Our controlling driver has changed power state on the hardware
2457 // during a power change we initiated. Here we see if we need to wait
2458 // for power to settle before continuing. If not, we continue processing
2459 // (notifying interested parties post-change). If so, we wait and
2461 //*********************************************************************************
2463 void IOService::OurChangeWaitForPowerSettle ( void )
2465 priv
->settle_time
= compute_settle_time();
2466 if ( priv
->settle_time
== 0 )
2468 OurChangeNotifyInterestedDriversDidChange();
2470 priv
->machine_state
= kIOPM_OurChangeNotifyInterestedDriversDidChange
;
2471 startSettleTimer(priv
->settle_time
);
2476 //*********************************************************************************
2477 // OurChangeNotifyInterestedDriversDidChange
2479 // Power has settled on a power change we initiated. Here we notify
2480 // all our interested parties post-change. If they all acknowledge, we're
2481 // done with this change note, and we can start on the next one.
2482 // Otherwise we have to wait for acknowledgements and finish up later.
2483 //*********************************************************************************
2485 void IOService::OurChangeNotifyInterestedDriversDidChange ( void )
2487 // in case they don't all ack
2488 priv
->machine_state
= kIOPM_OurChangeFinish
;
2489 if ( notifyAll(false) == IOPMAckImplied
)
2491 // not waiting for responses
2494 // If we are waiting for responses, execution will resume via
2495 // all_acked() or ack timeout
2499 //*********************************************************************************
2502 // Power has settled on a power change we initiated, and
2503 // all our interested parties have acknowledged. We're
2504 // done with this change note, and we can start on the next one.
2505 //*********************************************************************************
2507 void IOService::OurChangeFinish ( void )
2513 //*********************************************************************************
2514 // ParentDownTellPriorityClientsPowerDown_Immediate
2516 // All applications and kernel clients have been notified of a power lowering
2517 // initiated by the parent and we didn't have to wait for any responses. Here
2518 // we notify any priority clients. If they all ack, we continue with the power change.
2519 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2520 //*********************************************************************************
2522 IOReturn
IOService::ParentDownTellPriorityClientsPowerDown_Immediate ( void )
2524 // in case they don't all ack
2525 priv
->machine_state
= kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
;
2526 // are we waiting for responses?
2527 if ( tellChangeDown2(priv
->head_note_state
) )
2529 // no, notify interested drivers
2530 return ParentDownNotifyInterestedDriversWillChange_Immediate();
2532 // If we are waiting for responses, execution will resume via
2533 // allowCancelCommon() or ack timeout
2534 return IOPMWillAckLater
;
2538 //*********************************************************************************
2539 // ParentDownTellPriorityClientsPowerDown_Immediate2
2541 // All priority kernel clients have been notified of a power lowering
2542 // initiated by the parent and we didn't have to wait for any responses. Here
2543 // we notify any interested drivers and power domain children. If they all ack,
2544 // we continue with the power change.
2545 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2546 //*********************************************************************************
2548 IOReturn
IOService::ParentDownNotifyInterestedDriversWillChange_Immediate ( void )
2550 // in case they don't all ack
2551 priv
->machine_state
= kIOPM_ParentDownSetPowerState_Delayed
;
2552 if ( notifyAll(true) == IOPMAckImplied
)
2555 return ParentDownSetPowerState_Immediate();
2557 // If we are waiting for responses, execution will resume via
2558 // all_acked() or ack timeout
2559 return IOPMWillAckLater
;
2563 //*********************************************************************************
2564 // ParentDownTellPriorityClientsPowerDown_Immediate4
2566 // All applications and kernel clients have been notified of a power lowering
2567 // initiated by the parent and we had to wait for responses. Here
2568 // we notify any priority clients. If they all ack, we continue with the power change.
2569 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2570 //*********************************************************************************
2572 void IOService::ParentDownTellPriorityClientsPowerDown_Delayed ( void )
2574 // in case they don't all ack
2575 priv
->machine_state
= kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
;
2577 // are we waiting for responses?
2578 if ( tellChangeDown2(priv
->head_note_state
) )
2580 // no, notify interested drivers
2581 ParentDownNotifyInterestedDriversWillChange_Delayed();
2583 // If we are waiting for responses, execution will resume via
2584 // allowCancelCommon() or ack timeout
2588 //*********************************************************************************
2589 // ParentDownTellPriorityClientsPowerDown_Immediate5
2591 // All applications and kernel clients have been notified of a power lowering
2592 // initiated by the parent and we had to wait for their responses. Here we notify
2593 // any interested drivers and power domain children. If they all ack, we continue
2594 // with the power change.
2595 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2596 //*********************************************************************************
2598 void IOService::ParentDownNotifyInterestedDriversWillChange_Delayed ( void )
2600 // in case they don't all ack
2601 priv
->machine_state
= kIOPM_ParentDownSetPowerState_Delayed
;
2602 if ( notifyAll(true) == IOPMAckImplied
)
2605 ParentDownSetPowerState_Delayed();
2607 // If we are waiting for responses, execution will resume via
2608 // all_acked() or ack timeout
2612 //*********************************************************************************
2613 // ParentDownSetPowerState_Immediate
2615 // All parties have acknowledged our pre-change notification of a power
2616 // lowering initiated by the parent. Here we instruct our controlling driver
2617 // to put the hardware in the state it needs to be in when the domain is
2618 // lowered. If it does so, we continue processing
2619 // (waiting for settle and acknowledging the parent.)
2620 // If it doesn't, we have to wait for it to acknowledge and then continue.
2621 //*********************************************************************************
2623 IOReturn
IOService::ParentDownSetPowerState_Immediate ( void )
2625 priv
->machine_state
= kIOPM_ParentDownWaitForPowerSettle_Delayed
;
2627 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2629 // it's done, carry on
2630 return ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate();
2632 // it's not, wait for it
2633 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2635 return IOPMWillAckLater
;
2639 //*********************************************************************************
2640 // ParentDownSetPowerState_Delayed
2642 // We had to wait for it, but all parties have acknowledged our pre-change
2643 // notification of a power lowering initiated by the parent.
2644 // Here we instruct our controlling driver
2645 // to put the hardware in the state it needs to be in when the domain is
2646 // lowered. If it does so, we continue processing
2647 // (waiting for settle and acknowledging the parent.)
2648 // If it doesn't, we have to wait for it to acknowledge and then continue.
2649 //*********************************************************************************
2651 void IOService::ParentDownSetPowerState_Delayed ( void )
2653 priv
-> machine_state
= kIOPM_ParentDownWaitForPowerSettle_Delayed
;
2655 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2657 // it's done, carry on
2658 ParentDownWaitForPowerSettle_Delayed();
2660 // it's not, wait for it
2661 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2667 //*********************************************************************************
2668 // ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate
2670 // Our controlling driver has changed power state on the hardware
2671 // during a power change initiated by our parent. Here we see if we need
2672 // to wait for power to settle before continuing. If not, we continue
2673 // processing (acknowledging our preparedness to the parent).
2674 // If so, we wait and continue later.
2675 //*********************************************************************************
2677 IOReturn
IOService::ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate ( void )
2681 priv
->settle_time
= compute_settle_time();
2682 if ( priv
->settle_time
== 0 )
2684 // store current state in case they don't all ack
2685 priv
->machine_state
= kIOPM_ParentDownAcknowledgeChange_Delayed
;
2686 if ( notifyAll(false) == IOPMAckImplied
)
2688 // not waiting for responses
2689 nub
= priv
->head_note_parent
;
2693 return IOPMAckImplied
;
2695 // If we are waiting for responses, execution will resume via
2696 // all_acked() or ack timeout
2697 return IOPMWillAckLater
;
2699 // let settle time elapse, then notify interest drivers of our power state change in ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
2700 priv
->machine_state
= kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
;
2701 startSettleTimer(priv
->settle_time
);
2702 return IOPMWillAckLater
;
2707 //*********************************************************************************
2708 // ParentDownWaitForPowerSettle_Delayed
2710 // Our controlling driver has changed power state on the hardware
2711 // during a power change initiated by our parent. We have had to wait
2712 // for acknowledgement from interested parties, or we have had to wait
2713 // for the controlling driver to change the state. Here we see if we need
2714 // to wait for power to settle before continuing. If not, we continue
2715 // processing (acknowledging our preparedness to the parent).
2716 // If so, we wait and continue later.
2717 //*********************************************************************************
2719 void IOService::ParentDownWaitForPowerSettle_Delayed ( void )
2721 priv
->settle_time
= compute_settle_time();
2722 if ( priv
->settle_time
== 0 )
2724 ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed();
2726 priv
->machine_state
= kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
;
2727 startSettleTimer(priv
->settle_time
);
2732 //*********************************************************************************
2733 // ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
2735 // Power has settled on a power change initiated by our parent. Here we
2736 // notify interested parties.
2737 //*********************************************************************************
2739 void IOService::ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed ( void )
2741 IORegistryEntry
*nub
;
2744 // in case they don't all ack
2745 priv
->machine_state
= kIOPM_ParentDownAcknowledgeChange_Delayed
;
2746 if ( notifyAll(false) == IOPMAckImplied
) {
2747 nub
= priv
->head_note_parent
;
2750 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
2752 parent
->acknowledgePowerChange((IOService
*)nub
);
2757 // If we are waiting for responses, execution will resume via
2758 // all_acked() or ack timeout in ParentDownAcknowledgeChange_Delayed.
2759 // Notice the duplication of code just above and in ParentDownAcknowledgeChange_Delayed.
2763 //*********************************************************************************
2764 // ParentDownAcknowledgeChange_Delayed
2766 // We had to wait for it, but all parties have acknowledged our post-change
2767 // notification of a power lowering initiated by the parent.
2768 // Here we acknowledge the parent.
2769 // We are done with this change note, and we can start on the next one.
2770 //*********************************************************************************
2772 void IOService::ParentDownAcknowledgeChange_Delayed ( void )
2774 IORegistryEntry
*nub
;
2777 nub
= priv
->head_note_parent
;
2780 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
2783 parent
->acknowledgePowerChange((IOService
*)nub
);
2790 //*********************************************************************************
2791 // ParentUpSetPowerState_Delayed
2793 // Our parent has informed us via powerStateDidChange that it has
2794 // raised the power in our power domain, and we have had to wait
2795 // for some interested party to acknowledge our notification.
2796 // Here we instruct our controlling
2797 // driver to program the hardware to take advantage of the higher domain
2798 // power. If it does so, we continue processing
2799 // (waiting for settle and notifying interested parties post-change.)
2800 // If it doesn't, we have to wait for it to acknowledge and then continue.
2801 //*********************************************************************************
2803 void IOService::ParentUpSetPowerState_Delayed ( void )
2805 priv
->machine_state
= kIOPM_ParentUpWaitForSettleTime_Delayed
;
2807 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2809 // it did it, carry on
2810 ParentUpWaitForSettleTime_Delayed();
2812 // it didn't, wait for it
2813 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2819 //*********************************************************************************
2820 // ParentUpSetPowerState_Immediate
2822 // Our parent has informed us via powerStateDidChange that it has
2823 // raised the power in our power domain. Here we instruct our controlling
2824 // driver to program the hardware to take advantage of the higher domain
2825 // power. If it does so, we continue processing
2826 // (waiting for settle and notifying interested parties post-change.)
2827 // If it doesn't, we have to wait for it to acknowledge and then continue.
2828 //*********************************************************************************
2830 IOReturn
IOService::ParentUpSetPowerState_Immediate ( void )
2832 priv
->machine_state
= kIOPM_ParentUpWaitForSettleTime_Delayed
;
2834 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2836 // it did it, carry on
2837 return ParentUpWaitForSettleTime_Immediate();
2840 // it didn't, wait for it
2841 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2843 return IOPMWillAckLater
;
2848 //*********************************************************************************
2849 // ParentUpWaitForSettleTime_Immediate
2851 // Our controlling driver has changed power state on the hardware
2852 // during a power raise initiated by the parent. Here we see if we need to wait
2853 // for power to settle before continuing. If not, we continue processing
2854 // (notifying interested parties post-change). If so, we wait and
2856 //*********************************************************************************
2858 IOReturn
IOService::ParentUpWaitForSettleTime_Immediate ( void )
2860 priv
->settle_time
= compute_settle_time();
2861 if ( priv
->settle_time
== 0 )
2863 return ParentUpNotifyInterestedDriversDidChange_Immediate();
2865 priv
->machine_state
= kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed
;
2866 startSettleTimer(priv
->settle_time
);
2867 return IOPMWillAckLater
;
2872 //*********************************************************************************
2873 // ParentUpWaitForSettleTime_Delayed
2875 // Our controlling driver has changed power state on the hardware
2876 // during a power raise initiated by the parent, but we had to wait for it.
2877 // Here we see if we need to wait for power to settle before continuing.
2878 // If not, we continue processing (notifying interested parties post-change).
2879 // If so, we wait and continue later.
2880 //*********************************************************************************
2882 void IOService::ParentUpWaitForSettleTime_Delayed ( void )
2884 priv
->settle_time
= compute_settle_time();
2885 if ( priv
->settle_time
== 0 )
2887 ParentUpNotifyInterestedDriversDidChange_Delayed();
2889 priv
->machine_state
= kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed
;
2890 startSettleTimer(priv
->settle_time
);
2895 //*********************************************************************************
2896 // ParentUpNotifyInterestedDriversDidChange_Immediate
2898 // No power settling was required on a power raise initiated by the parent.
2899 // Here we notify all our interested parties post-change. If they all acknowledge,
2900 // we're done with this change note, and we can start on the next one.
2901 // Otherwise we have to wait for acknowledgements and finish up later.
2902 //*********************************************************************************
2904 IOReturn
IOService::ParentUpNotifyInterestedDriversDidChange_Immediate ( void )
2908 // in case they don't all ack
2909 priv
->machine_state
= kIOPM_ParentUpAcknowledgePowerChange_Delayed
;
2910 if ( notifyAll(false) == IOPMAckImplied
)
2912 nub
= priv
->head_note_parent
;
2916 return IOPMAckImplied
;
2918 // If we are waiting for responses, execution will resume via
2919 // all_acked() or ack timeout in ParentUpAcknowledgePowerChange_Delayed.
2920 return IOPMWillAckLater
;
2924 //*********************************************************************************
2925 // ParentUpNotifyInterestedDriversDidChange_Delayed
2927 // Power has settled on a power raise initiated by the parent.
2928 // Here we notify all our interested parties post-change. If they all acknowledge,
2929 // we're done with this change note, and we can start on the next one.
2930 // Otherwise we have to wait for acknowledgements and finish up later.
2931 //*********************************************************************************
2933 void IOService::ParentUpNotifyInterestedDriversDidChange_Delayed ( void )
2935 // in case they don't all ack
2936 priv
->machine_state
= kIOPM_ParentUpAcknowledgePowerChange_Delayed
;
2937 if ( notifyAll(false) == IOPMAckImplied
)
2939 ParentUpAcknowledgePowerChange_Delayed();
2941 // If we are waiting for responses, execution will resume via
2942 // all_acked() or ack timeout in ParentUpAcknowledgePowerChange_Delayed.
2946 //*********************************************************************************
2947 // ParentUpAcknowledgePowerChange_Delayed
2949 // All parties have acknowledged our post-change notification of a power
2950 // raising initiated by the parent. Here we acknowledge the parent.
2951 // We are done with this change note, and we can start on the next one.
2952 //*********************************************************************************
2954 void IOService::ParentUpAcknowledgePowerChange_Delayed ( void )
2956 IORegistryEntry
*nub
;
2959 nub
= priv
->head_note_parent
;
2962 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
2965 parent
->acknowledgePowerChange((IOService
*)nub
);
2972 //*********************************************************************************
2975 // A power change is complete, and the used post-change note is at
2976 // the head of the queue. Remove it and set myCurrentState to the result
2977 // of the change. Start up the next change in queue.
2978 //*********************************************************************************
2980 void IOService::all_done ( void )
2982 unsigned long previous_state
;
2983 IORegistryEntry
*nub
;
2986 priv
->machine_state
= kIOPM_Finished
;
2989 if ( priv
->head_note_flags
& IOPMWeInitiated
)
2991 // could our driver switch to the new state?
2992 if ( !( priv
->head_note_flags
& IOPMNotDone
) )
2994 // yes, did power raise?
2995 if ( pm_vars
->myCurrentState
< priv
->head_note_state
)
2997 // yes, inform clients and apps
2998 tellChangeUp (priv
->head_note_state
);
3000 // no, if this lowers our
3001 if ( ! priv
->we_are_root
)
3003 // power requirements, tell the parent
3004 ask_parent(priv
->head_note_state
);
3007 previous_state
= pm_vars
->myCurrentState
;
3009 pm_vars
->myCurrentState
= priv
->head_note_state
;
3010 priv
->imminentState
= pm_vars
->myCurrentState
;
3011 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeDone
,(unsigned long)pm_vars
->myCurrentState
,0);
3012 // inform subclass policy-maker
3013 powerChangeDone(previous_state
);
3017 // parent's power change
3018 if ( priv
->head_note_flags
& IOPMParentInitiated
)
3020 if ( ((priv
->head_note_flags
& IOPMDomainWillChange
) && (pm_vars
->myCurrentState
>= priv
->head_note_state
)) ||
3021 ((priv
->head_note_flags
& IOPMDomainDidChange
) && (pm_vars
->myCurrentState
< priv
->head_note_state
)) )
3024 if ( pm_vars
->myCurrentState
< priv
->head_note_state
)
3026 // yes, inform clients and apps
3027 tellChangeUp (priv
->head_note_state
);
3030 previous_state
= pm_vars
->myCurrentState
;
3031 pm_vars
->myCurrentState
= priv
->head_note_state
;
3032 priv
->imminentState
= pm_vars
->myCurrentState
;
3033 pm_vars
->maxCapability
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(priv
->head_note_domainState
);
3035 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeDone
,(unsigned long)pm_vars
->myCurrentState
,0);
3036 // inform subclass policy-maker
3037 powerChangeDone(previous_state
);
3041 IOLockLock(priv
->queue_lock
);
3042 // we're done with this
3043 priv
->changeList
->releaseHeadChangeNote();
3045 // start next one in queue
3046 priv
->head_note
= priv
->changeList
->currentChange();
3047 if ( priv
->head_note
!= -1 )
3050 IOLockUnlock(priv
->queue_lock
);
3051 if (priv
->changeList
->changeNote
[priv
->head_note
].flags
& IOPMWeInitiated
)
3053 start_our_change(priv
->head_note
);
3055 nub
= priv
->changeList
->changeNote
[priv
->head_note
].parent
;
3056 if ( start_parent_change(priv
->head_note
) == IOPMAckImplied
)
3058 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
3061 parent
->acknowledgePowerChange((IOService
*)nub
);
3067 IOLockUnlock(priv
->queue_lock
);
3073 //*********************************************************************************
3076 // A driver or child has acknowledged our notification of an upcoming power
3077 // change, and this acknowledgement is the last one pending
3078 // before we change power or after changing power.
3080 //*********************************************************************************
3082 void IOService::all_acked ( void )
3084 switch (priv
->machine_state
) {
3085 case kIOPM_OurChangeSetPowerState
:
3086 OurChangeSetPowerState();
3088 case kIOPM_OurChangeFinish
:
3091 case kIOPM_ParentDownSetPowerState_Delayed
:
3092 ParentDownSetPowerState_Delayed();
3094 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3095 ParentDownAcknowledgeChange_Delayed();
3097 case kIOPM_ParentUpSetPowerState_Delayed
:
3098 ParentUpSetPowerState_Delayed();
3100 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3101 ParentUpAcknowledgePowerChange_Delayed();
3106 //*********************************************************************************
3107 // settleTimerExpired
3109 // Power has settled after our last change. Notify interested parties that
3110 // there is a new power state.
3111 //*********************************************************************************
3113 void IOService::settleTimerExpired ( void )
3115 if ( ! initialized
)
3121 switch (priv
->machine_state
) {
3122 case kIOPM_OurChangeNotifyInterestedDriversDidChange
:
3123 OurChangeNotifyInterestedDriversDidChange();
3125 case kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
:
3126 ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed();
3128 case kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed
:
3129 ParentUpNotifyInterestedDriversDidChange_Delayed();
3135 //*********************************************************************************
3136 // compute_settle_time
3138 // Compute the power-settling delay in microseconds for the
3139 // change from myCurrentState to head_note_state.
3140 //*********************************************************************************
3142 unsigned long IOService::compute_settle_time ( void )
3144 unsigned long totalTime
;
3147 // compute total time to attain the new state
3149 i
= pm_vars
->myCurrentState
;
3151 // we're lowering power
3152 if ( priv
->head_note_state
< pm_vars
->myCurrentState
)
3154 while ( i
> priv
->head_note_state
)
3156 totalTime
+= pm_vars
->thePowerStates
[i
].settleDownTime
;
3161 // we're raising power
3162 if ( priv
->head_note_state
> pm_vars
->myCurrentState
)
3164 while ( i
< priv
->head_note_state
)
3166 totalTime
+= pm_vars
->thePowerStates
[i
+1].settleUpTime
;
3175 //*********************************************************************************
3178 // Enter with a power-settling delay in microseconds and start a nano-second
3179 // timer for that delay.
3180 //*********************************************************************************
3182 IOReturn
IOService::startSettleTimer ( unsigned long delay
)
3184 AbsoluteTime deadline
;
3186 clock_interval_to_deadline(delay
, kMicrosecondScale
, &deadline
);
3188 thread_call_enter_delayed(priv
->settleTimer
, deadline
);
3193 //*********************************************************************************
3196 // The acknowledgement timeout periodic timer has ticked.
3197 // If we are awaiting acks for a power change notification,
3198 // we decrement the timer word of each interested driver which hasn't acked.
3199 // If a timer word becomes zero, we pretend the driver aknowledged.
3200 // If we are waiting for the controlling driver to change the power
3201 // state of the hardware, we decrement its timer word, and if it becomes
3202 // zero, we pretend the driver acknowledged.
3203 //*********************************************************************************
3205 void IOService::ack_timer_ticked ( void )
3207 IOPMinformee
* nextObject
;
3209 if ( ! initialized
)
3215 if (! acquire_lock() )
3220 switch (priv
->machine_state
) {
3221 case kIOPM_OurChangeWaitForPowerSettle
:
3222 case kIOPM_ParentDownWaitForPowerSettle_Delayed
:
3223 case kIOPM_ParentUpWaitForSettleTime_Delayed
:
3224 // are we waiting for our driver to make its change?
3225 if ( priv
->driver_timer
!= 0 ) {
3227 priv
->driver_timer
-= 1;
3228 // it's tardy, we'll go on without it
3229 if ( priv
->driver_timer
== 0 )
3231 IOUnlock(priv
->our_lock
);
3232 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogCtrlDriverTardy
,0,0);
3235 // still waiting, set timer again
3237 IOUnlock(priv
->our_lock
);
3241 IOUnlock(priv
->our_lock
);
3245 case kIOPM_OurChangeSetPowerState
:
3246 case kIOPM_OurChangeFinish
:
3247 case kIOPM_ParentDownSetPowerState_Delayed
:
3248 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3249 case kIOPM_ParentUpSetPowerState_Delayed
:
3250 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3251 // are we waiting for interested parties to acknowledge?
3252 if (priv
->head_note_pendingAcks
!= 0 )
3254 // yes, go through the list of interested drivers
3255 nextObject
= priv
->interestedDrivers
->firstInList();
3256 // and check each one
3257 while ( nextObject
!= NULL
)
3259 if ( nextObject
->timer
> 0 )
3261 nextObject
->timer
-= 1;
3262 // this one should have acked by now
3263 if ( nextObject
->timer
== 0 )
3265 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogIntDriverTardy
,0,0);
3266 //kprintf("interested driver tardy: %s\n",nextObject->whatObject->getName());
3267 priv
->head_note_pendingAcks
-= 1;
3270 nextObject
= priv
->interestedDrivers
->nextInList(nextObject
);
3273 // is that the last?
3274 if ( priv
->head_note_pendingAcks
== 0 )
3276 IOUnlock(priv
->our_lock
);
3277 // yes, we can continue
3280 // no, set timer again
3282 IOUnlock(priv
->our_lock
);
3285 IOUnlock(priv
->our_lock
);
3289 // apps didn't respond to parent-down notification
3290 case kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate
:
3291 IOUnlock(priv
->our_lock
);
3292 IOLockLock(priv
->flags_lock
);
3293 if (pm_vars
->responseFlags
)
3295 // get rid of this stuff
3296 pm_vars
->responseFlags
->release();
3297 pm_vars
->responseFlags
= NULL
;
3299 IOLockUnlock(priv
->flags_lock
);
3300 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,5);
3301 // carry on with the change
3302 ParentDownTellPriorityClientsPowerDown_Delayed();
3305 case kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
:
3306 IOUnlock(priv
->our_lock
);
3307 IOLockLock(priv
->flags_lock
);
3308 if (pm_vars
->responseFlags
)
3310 // get rid of this stuff
3311 pm_vars
->responseFlags
->release();
3312 pm_vars
->responseFlags
= NULL
;
3314 IOLockUnlock(priv
->flags_lock
);
3315 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,1);
3316 // carry on with the change
3317 ParentDownNotifyInterestedDriversWillChange_Delayed();
3320 case kIOPM_OurChangeTellClientsPowerDown
:
3321 // apps didn't respond to our power-down request
3322 IOUnlock(priv
->our_lock
);
3323 IOLockLock(priv
->flags_lock
);
3324 if (pm_vars
->responseFlags
)
3326 // get rid of this stuff
3327 pm_vars
->responseFlags
->release();
3328 pm_vars
->responseFlags
= NULL
;
3330 IOLockUnlock(priv
->flags_lock
);
3331 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,2);
3332 // rescind the request
3333 tellNoChangeDown(priv
->head_note_state
);
3334 // mark the change note un-actioned
3335 priv
->head_note_flags
|= IOPMNotDone
;
3340 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
3341 // clients didn't respond to our power-down note
3342 IOUnlock(priv
->our_lock
);
3343 IOLockLock(priv
->flags_lock
);
3344 if (pm_vars
->responseFlags
)
3346 // get rid of this stuff
3347 pm_vars
->responseFlags
->release();
3348 pm_vars
->responseFlags
= NULL
;
3350 IOLockUnlock(priv
->flags_lock
);
3351 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,4);
3352 // carry on with the change
3353 OurChangeTellPriorityClientsPowerDown();
3356 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
3357 // apps didn't respond to our power-down notification
3358 IOUnlock(priv
->our_lock
);
3359 IOLockLock(priv
->flags_lock
);
3360 if (pm_vars
->responseFlags
)
3362 // get rid of this stuff
3363 pm_vars
->responseFlags
->release();
3364 pm_vars
->responseFlags
= NULL
;
3366 IOLockUnlock(priv
->flags_lock
);
3367 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,3);
3368 // carry on with the change
3369 OurChangeNotifyInterestedDriversWillChange();
3373 // not waiting for acks
3374 IOUnlock(priv
->our_lock
);
3380 //*********************************************************************************
3383 //*********************************************************************************
3385 void IOService::start_ack_timer ( void )
3387 AbsoluteTime deadline
;
3389 clock_interval_to_deadline(ACK_TIMER_PERIOD
, kNanosecondScale
, &deadline
);
3391 thread_call_enter_delayed(priv
->ackTimer
, deadline
);
3395 //*********************************************************************************
3398 //*********************************************************************************
3400 void IOService::stop_ack_timer ( void )
3402 thread_call_cancel(priv
->ackTimer
);
3406 //*********************************************************************************
3407 // c-language timer expiration functions
3409 //*********************************************************************************
3411 static void ack_timer_expired ( thread_call_param_t us
)
3413 ((IOService
*)us
)->ack_timer_ticked();
3417 static void settle_timer_expired ( thread_call_param_t us
)
3419 ((IOService
*)us
)->settleTimerExpired();
3423 //*********************************************************************************
3424 // add_child_to_active_change
3426 // A child has just registered with us. If there is
3427 // currently a change in progress, get the new party involved: if we
3428 // have notified all parties and are waiting for acks, notify the new
3430 //*********************************************************************************
3432 IOReturn
IOService::add_child_to_active_change ( IOPowerConnection
* newObject
)
3434 if (! acquire_lock() )
3439 switch (priv
->machine_state
)
3441 case kIOPM_OurChangeSetPowerState
:
3442 case kIOPM_ParentDownSetPowerState_Delayed
:
3443 case kIOPM_ParentUpSetPowerState_Delayed
:
3444 // one for this child and one to prevent
3445 priv
->head_note_pendingAcks
+= 2;
3446 // incoming acks from changing our state
3447 IOUnlock(priv
->our_lock
);
3448 notifyChild(newObject
, true);
3449 if (! acquire_lock() )
3452 --priv
->head_note_pendingAcks
;
3455 // are we still waiting for acks?
3456 if ( --priv
->head_note_pendingAcks
== 0 )
3458 // no, stop the timer
3460 IOUnlock(priv
->our_lock
);
3462 // and now we can continue
3467 case kIOPM_OurChangeFinish
:
3468 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3469 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3470 // one for this child and one to prevent
3471 priv
->head_note_pendingAcks
+= 2;
3472 // incoming acks from changing our state
3473 IOUnlock(priv
->our_lock
);
3474 notifyChild(newObject
, false);
3475 if (! acquire_lock() )
3478 --priv
->head_note_pendingAcks
;
3481 // are we still waiting for acks?
3482 if ( --priv
->head_note_pendingAcks
== 0 )
3484 // no, stop the timer
3486 IOUnlock(priv
->our_lock
);
3488 // and now we can continue
3494 IOUnlock(priv
->our_lock
);
3499 //*********************************************************************************
3500 // add_driver_to_active_change
3502 // An interested driver has just registered with us. If there is
3503 // currently a change in progress, get the new party involved: if we
3504 // have notified all parties and are waiting for acks, notify the new
3506 //*********************************************************************************
3508 IOReturn
IOService::add_driver_to_active_change ( IOPMinformee
* newObject
)
3510 if (! acquire_lock() )
3515 switch (priv
->machine_state
) {
3516 case kIOPM_OurChangeSetPowerState
:
3517 case kIOPM_ParentDownSetPowerState_Delayed
:
3518 case kIOPM_ParentUpSetPowerState_Delayed
:
3519 // one for this driver and one to prevent
3520 priv
->head_note_pendingAcks
+= 2;
3521 // incoming acks from changing our state
3522 IOUnlock(priv
->our_lock
);
3523 // inform the driver
3524 inform(newObject
, true);
3525 if (! acquire_lock() )
3528 --priv
->head_note_pendingAcks
;
3531 // are we still waiting for acks?
3532 if ( --priv
->head_note_pendingAcks
== 0 )
3534 // no, stop the timer
3536 IOUnlock(priv
->our_lock
);
3538 // and now we can continue
3543 case kIOPM_OurChangeFinish
:
3544 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3545 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3546 // one for this driver and one to prevent
3547 priv
->head_note_pendingAcks
+= 2;
3548 // incoming acks from changing our state
3549 IOUnlock(priv
->our_lock
);
3550 // inform the driver
3551 inform(newObject
, false);
3552 if (! acquire_lock() ) {
3554 --priv
->head_note_pendingAcks
;
3557 // are we still waiting for acks?
3558 if ( --priv
->head_note_pendingAcks
== 0 ) {
3559 // no, stop the timer
3561 IOUnlock(priv
->our_lock
);
3563 // and now we can continue
3569 IOUnlock(priv
->our_lock
);
3574 //*********************************************************************************
3575 // start_parent_change
3577 // Here we begin the processing of a change note initiated by our parent
3578 // which is at the head of the queue.
3580 // It is possible for the change to be processed to completion and removed from the queue.
3581 // There are several possible interruptions to the processing, though, and they are:
3582 // we may have to wait for interested parties to acknowledge our pre-change notification,
3583 // we may have to wait for our controlling driver to change the hardware power state,
3584 // there may be a settling time after changing the hardware power state,
3585 // we may have to wait for interested parties to acknowledge our post-change notification,
3586 // we may have to wait for the acknowledgement timer expiration to substitute for the
3587 // acknowledgement from a failing driver.
3588 //*********************************************************************************
3590 IOReturn
IOService::start_parent_change ( unsigned long queue_head
)
3592 priv
->head_note
= queue_head
;
3593 priv
->head_note_flags
= priv
-> changeList
->changeNote
[priv
->head_note
].flags
;
3594 priv
->head_note_state
= priv
->changeList
->changeNote
[priv
->head_note
].newStateNumber
;
3595 priv
->imminentState
= priv
->head_note_state
;
3596 priv
->head_note_outputFlags
= priv
->changeList
->changeNote
[priv
->head_note
].outputPowerCharacter
;
3597 priv
->head_note_domainState
= priv
->changeList
->changeNote
[priv
->head_note
].domainState
;
3598 priv
->head_note_parent
= priv
->changeList
->changeNote
[priv
->head_note
].parent
;
3599 priv
->head_note_capabilityFlags
= priv
->changeList
->changeNote
[priv
->head_note
].capabilityFlags
;
3601 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartParentChange
,
3602 (unsigned long)priv
->head_note_state
,(unsigned long)pm_vars
->myCurrentState
);
3604 // if we need something and haven't told the parent, do so
3605 ask_parent( priv
->ourDesiredPowerState
);
3607 // power domain is lowering
3608 if ( priv
->head_note_state
< pm_vars
->myCurrentState
)
3610 setParentInfo(priv
->changeList
->changeNote
[priv
->head_note
].singleParentState
,priv
->head_note_parent
);
3611 priv
->initial_change
= false;
3612 // tell apps and kernel clients
3613 priv
->machine_state
= kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate
;
3615 // are we waiting for responses?
3616 if ( tellChangeDown1(priv
->head_note_state
) )
3618 // no, notify priority clients
3619 return ParentDownTellPriorityClientsPowerDown_Immediate();
3622 return IOPMWillAckLater
;
3625 // parent is raising power, we may or may not
3626 if ( priv
->head_note_state
> pm_vars
->myCurrentState
)
3628 if ( priv
->ourDesiredPowerState
> pm_vars
->myCurrentState
)
3630 if ( priv
->ourDesiredPowerState
< priv
->head_note_state
)
3632 // we do, but not all the way
3633 priv
->head_note_state
= priv
->ourDesiredPowerState
;
3634 priv
->imminentState
= priv
->head_note_state
;
3635 priv
->head_note_outputFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].outputPowerCharacter
;
3636 priv
->head_note_capabilityFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].capabilityFlags
;
3637 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAmendParentChange
,(unsigned long)priv
->head_note_state
,0);
3641 priv
->head_note_state
= pm_vars
->myCurrentState
;
3642 priv
->imminentState
= priv
->head_note_state
;
3643 priv
->head_note_outputFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].outputPowerCharacter
;
3644 priv
->head_note_capabilityFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].capabilityFlags
;
3645 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAmendParentChange
,(unsigned long)priv
->head_note_state
,0);
3649 if ( (priv
->head_note_state
> pm_vars
->myCurrentState
) &&
3650 (priv
->head_note_flags
& IOPMDomainDidChange
) )
3653 priv
->initial_change
= false;
3654 priv
->machine_state
= kIOPM_ParentUpSetPowerState_Delayed
;
3655 if ( notifyAll(true) == IOPMAckImplied
) {
3656 return ParentUpSetPowerState_Immediate();
3658 // they didn't all ack
3659 return IOPMWillAckLater
;
3663 // a null change or power will go up
3664 return IOPMAckImplied
;
3668 //*********************************************************************************
3671 // Here we begin the processing of a change note initiated by us
3672 // which is at the head of the queue.
3674 // It is possible for the change to be processed to completion and removed from the queue.
3675 // There are several possible interruptions to the processing, though, and they are:
3676 // we may have to wait for interested parties to acknowledge our pre-change notification,
3677 // changes initiated by the parent will wait in the middle for powerStateDidChange,
3678 // we may have to wait for our controlling driver to change the hardware power state,
3679 // there may be a settling time after changing the hardware power state,
3680 // we may have to wait for interested parties to acknowledge our post-change notification,
3681 // we may have to wait for the acknowledgement timer expiration to substitute for the
3682 // acknowledgement from a failing driver.
3683 //*********************************************************************************
3685 void IOService::start_our_change ( unsigned long queue_head
)
3687 priv
->head_note
= queue_head
;
3688 priv
->head_note_flags
= priv
->changeList
->changeNote
[priv
->head_note
].flags
;
3689 priv
->head_note_state
= priv
->changeList
->changeNote
[priv
->head_note
].newStateNumber
;
3690 priv
->imminentState
= priv
->head_note_state
;
3691 priv
->head_note_outputFlags
= priv
->changeList
->changeNote
[priv
->head_note
].outputPowerCharacter
;
3692 priv
->head_note_capabilityFlags
= priv
->changeList
->changeNote
[priv
->head_note
].capabilityFlags
;
3694 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartDeviceChange
,
3695 (unsigned long)priv
->head_note_state
,(unsigned long)pm_vars
->myCurrentState
);
3697 // can our driver switch to the new state?
3698 if ( priv
->head_note_capabilityFlags
& IOPMNotAttainable
)
3700 // no, ask the parent to do it then
3701 if ( ! priv
->we_are_root
)
3703 ask_parent(priv
->head_note_state
);
3705 // mark the change note un-actioned
3706 priv
-> head_note_flags
|= IOPMNotDone
;
3712 // is there enough power in the domain?
3713 if ( (pm_vars
->maxCapability
< priv
->head_note_state
) && (! priv
->we_are_root
) )
3715 // no, ask the parent to raise it
3716 if ( ! priv
->we_are_root
)
3718 ask_parent(priv
->head_note_state
);
3720 // no, mark the change note un-actioned
3721 priv
->head_note_flags
|= IOPMNotDone
;
3723 // till the parent raises power
3728 if ( ! priv
->initial_change
)
3730 if ( priv
->head_note_state
== pm_vars
->myCurrentState
)
3732 // we initiated a null change; forget it
3737 priv
->initial_change
= false;
3740 if ( priv
->head_note_state
< pm_vars
->myCurrentState
)
3742 // yes, in case we have to wait for acks
3743 priv
->machine_state
= kIOPM_OurChangeTellClientsPowerDown
;
3744 pm_vars
->doNotPowerDown
= false;
3746 // ask apps and kernel clients if we can drop power
3747 pm_vars
->outofbandparameter
= kNotifyApps
;
3748 if ( askChangeDown(priv
->head_note_state
) )
3750 // don't have to wait, did any clients veto?
3751 if ( pm_vars
->doNotPowerDown
)
3753 // yes, rescind the warning
3754 tellNoChangeDown(priv
->head_note_state
);
3755 // mark the change note un-actioned
3756 priv
-> head_note_flags
|= IOPMNotDone
;
3760 // no, tell'em we're dropping power
3761 OurChangeTellClientsPowerDown();
3765 // we are raising power
3766 if ( ! priv
->we_are_root
)
3768 // if this changes our power requirement, tell the parent
3769 ask_parent(priv
->head_note_state
);
3771 // in case they don't all ack
3772 priv
->machine_state
= kIOPM_OurChangeSetPowerState
;
3774 // notify interested drivers and children
3775 if ( notifyAll(true) == IOPMAckImplied
)
3777 OurChangeSetPowerState();
3783 //*********************************************************************************
3786 // Call the power domain parent to ask for a higher power state in the domain
3787 // or to suggest a lower power state.
3788 //*********************************************************************************
3790 IOReturn
IOService::ask_parent ( unsigned long requestedState
)
3794 IOPowerConnection
*connection
;
3796 unsigned long ourRequest
= pm_vars
->thePowerStates
[requestedState
].inputPowerRequirement
;
3798 if ( pm_vars
->thePowerStates
[requestedState
].capabilityFlags
& (kIOPMChildClamp
| kIOPMPreventIdleSleep
) )
3800 ourRequest
|= kIOPMPreventIdleSleep
;
3802 if ( pm_vars
->thePowerStates
[requestedState
].capabilityFlags
& (kIOPMChildClamp2
| kIOPMPreventSystemSleep
) )
3804 ourRequest
|= kIOPMPreventSystemSleep
;
3807 // is this a new desire?
3808 if ( priv
->previousRequest
== ourRequest
)
3810 // no, the parent knows already, just return
3814 if ( priv
->we_are_root
)
3818 priv
->previousRequest
= ourRequest
;
3820 iter
= getParentIterator(gIOPowerPlane
);
3824 while ( (next
= iter
->getNextObject()) )
3826 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
3828 parent
= (IOService
*)connection
->copyParentEntry(gIOPowerPlane
);
3830 if ( parent
->requestPowerDomainState(ourRequest
,connection
,IOPMLowestState
)!= IOPMNoErr
)
3832 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRequestDenied
,
3833 (unsigned long)priv
->previousRequest
,0);
3846 //*********************************************************************************
3849 // Call the controlling driver and have it change the power state of the
3850 // hardware. If it returns IOPMAckImplied, the change is complete, and
3851 // we return IOPMAckImplied. Otherwise, it will ack when the change
3852 // is done; we return IOPMWillAckLater.
3853 //*********************************************************************************
3854 IOReturn
IOService::instruct_driver ( unsigned long newState
)
3856 IOReturn return_code
;
3858 // can our driver switch to the desired state?
3859 if ( pm_vars
->thePowerStates
[newState
].capabilityFlags
& IOPMNotAttainable
)
3862 return IOPMAckImplied
;
3865 priv
->driver_timer
= -1;
3866 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogProgramHardware
,newState
,0);
3869 ioSPMTraceStart(IOPOWER_STATE
, * (int *) this, (int) newState
);
3870 return_code
= pm_vars
->theControllingDriver
->setPowerState( newState
,this );
3871 ioSPMTraceEnd(IOPOWER_STATE
, * (int *) this, (int) newState
, (int) return_code
);
3874 if ( return_code
== IOPMAckImplied
)
3876 priv
->driver_timer
= 0;
3877 return IOPMAckImplied
;
3880 // it acked behind our back
3881 if ( priv
->driver_timer
== 0 )
3883 return IOPMAckImplied
;
3887 if ( return_code
< 0 )
3889 return IOPMAckImplied
;
3893 priv
->driver_timer
= (return_code
/ ( ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
3894 return IOPMWillAckLater
;
3898 //*********************************************************************************
3901 // We are acquiring the lock we use to protect our queue head from
3902 // simutaneous access by a thread which calls acknowledgePowerStateChange
3903 // or acknowledgeSetPowerState and the ack timer expiration thread.
3904 // Return TRUE if we acquire the lock, and the queue head didn't change
3905 // while we were acquiring the lock (and maybe blocked).
3906 // If there is no queue head, or it changes while we are blocked,
3907 // return FALSE with the lock unlocked.
3908 //*********************************************************************************
3910 bool IOService::acquire_lock ( void )
3912 long current_change_note
;
3914 current_change_note
= priv
->head_note
;
3915 if ( current_change_note
== -1 ) {
3919 IOTakeLock(priv
->our_lock
);
3920 if ( current_change_note
== priv
->head_note
)
3924 // we blocked and something changed radically
3925 // so there's nothing to do any more
3926 IOUnlock(priv
->our_lock
);
3932 //*********************************************************************************
3935 // Ask registered applications and kernel clients if we can change to a lower
3938 // Subclass can override this to send a different message type. Parameter is
3939 // the destination state number.
3941 // Return true if we don't have to wait for acknowledgements
3942 //*********************************************************************************
3944 bool IOService::askChangeDown ( unsigned long stateNum
)
3946 return tellClientsWithResponse(kIOMessageCanDevicePowerOff
);
3950 //*********************************************************************************
3953 // Notify registered applications and kernel clients that we are definitely
3956 // Return true if we don't have to wait for acknowledgements
3957 //*********************************************************************************
3959 bool IOService::tellChangeDown1 ( unsigned long stateNum
)
3961 pm_vars
->outofbandparameter
= kNotifyApps
;
3962 return tellChangeDown(stateNum
);
3966 //*********************************************************************************
3969 // Notify priority clients that we are definitely dropping power.
3971 // Return true if we don't have to wait for acknowledgements
3972 //*********************************************************************************
3974 bool IOService::tellChangeDown2 ( unsigned long stateNum
)
3976 pm_vars
->outofbandparameter
= kNotifyPriority
;
3977 return tellChangeDown(stateNum
);
3981 //*********************************************************************************
3984 // Notify registered applications and kernel clients that we are definitely
3987 // Subclass can override this to send a different message type. Parameter is
3988 // the destination state number.
3990 // Return true if we don't have to wait for acknowledgements
3991 //*********************************************************************************
3993 bool IOService::tellChangeDown ( unsigned long stateNum
)
3995 return tellClientsWithResponse(kIOMessageDeviceWillPowerOff
);
3999 //*********************************************************************************
4000 // tellClientsWithResponse
4002 // Notify registered applications and kernel clients that we are definitely
4005 // Return true if we don't have to wait for acknowledgements
4006 //*********************************************************************************
4008 bool IOService::tellClientsWithResponse ( int messageType
)
4010 struct context theContext
;
4011 AbsoluteTime deadline
;
4014 pm_vars
->responseFlags
= OSArray::withCapacity( 1 );
4015 pm_vars
->serialNumber
+= 1;
4017 theContext
.responseFlags
= pm_vars
->responseFlags
;
4018 theContext
.serialNumber
= pm_vars
->serialNumber
;
4019 theContext
.flags_lock
= priv
->flags_lock
;
4020 theContext
.counter
= 1;
4021 theContext
.msgType
= messageType
;
4022 theContext
.us
= this;
4023 theContext
.maxTimeRequested
= 0;
4024 theContext
.stateNumber
= priv
->head_note_state
;
4025 theContext
.stateFlags
= priv
->head_note_capabilityFlags
;
4027 IOLockLock(priv
->flags_lock
);
4029 // position zero is false to
4030 // prevent allowCancelCommon from succeeding
4031 aBool
= OSBoolean::withBoolean(false);
4032 theContext
.responseFlags
->setObject(0,aBool
);
4034 IOLockUnlock(priv
->flags_lock
);
4036 switch ( pm_vars
->outofbandparameter
) {
4038 applyToInterested(gIOAppPowerStateInterest
,tellAppWithResponse
,(void *)&theContext
);
4039 applyToInterested(gIOGeneralInterest
,tellClientWithResponse
,(void *)&theContext
);
4041 case kNotifyPriority
:
4042 applyToInterested(gIOPriorityPowerStateInterest
,tellClientWithResponse
,(void *)&theContext
);
4046 if (! acquire_lock() )
4050 IOLockLock(priv
->flags_lock
);
4051 // now fix position zero
4052 aBool
= OSBoolean::withBoolean(true);
4053 theContext
.responseFlags
->replaceObject(0,aBool
);
4055 IOLockUnlock(priv
->flags_lock
);
4057 // do we have to wait for somebody?
4058 if ( ! checkForDone() )
4060 // yes, start the ackTimer
4061 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,theContext
.maxTimeRequested
,0);
4062 clock_interval_to_deadline(theContext
.maxTimeRequested
/ 1000, kMillisecondScale
, &deadline
);
4064 thread_call_enter_delayed(priv
->ackTimer
, deadline
);
4066 IOUnlock(priv
->our_lock
);
4070 IOUnlock(priv
->our_lock
);
4071 IOLockLock(priv
->flags_lock
);
4073 // everybody responded
4074 pm_vars
->responseFlags
->release();
4075 pm_vars
->responseFlags
= NULL
;
4076 IOLockUnlock(priv
->flags_lock
);
4082 //*********************************************************************************
4083 // tellAppWithResponse
4085 // We send a message to an application, and we expect a response, so we compute a
4086 // cookie we can identify the response with.
4087 //*********************************************************************************
4088 void tellAppWithResponse ( OSObject
* object
, void * context
)
4090 struct context
*theContext
= (struct context
*)context
;
4094 if( OSDynamicCast( IOService
, object
) )
4096 IOLockLock(theContext
->flags_lock
);
4097 aBool
= OSBoolean::withBoolean(true);
4098 theContext
->responseFlags
->setObject(theContext
->counter
,aBool
);
4100 IOLockUnlock(theContext
->flags_lock
);
4102 refcon
= ((theContext
->serialNumber
& 0xFFFF)<<16) + (theContext
->counter
& 0xFFFF);
4103 IOLockLock(theContext
->flags_lock
);
4104 aBool
= OSBoolean::withBoolean(false);
4105 theContext
->responseFlags
->setObject(theContext
->counter
,aBool
);
4107 IOLockUnlock(theContext
->flags_lock
);
4108 theContext
->us
->messageClient(theContext
->msgType
,object
,(void *)refcon
);
4109 if ( theContext
->maxTimeRequested
< k30seconds
)
4111 theContext
->maxTimeRequested
= k30seconds
;
4114 theContext
->counter
+= 1;
4118 //*********************************************************************************
4119 // tellClientWithResponse
4121 // We send a message to an in-kernel client, and we expect a response, so we compute a
4122 // cookie we can identify the response with.
4123 // If it doesn't understand the notification (it is not power-management savvy)
4124 // we won't wait for it to prepare for sleep. If it tells us via a return code
4125 // in the passed struct that it is currently ready, we won't wait for it to prepare.
4126 // If it tells us via the return code in the struct that it does need time, we will chill.
4127 //*********************************************************************************
4128 void tellClientWithResponse ( OSObject
* object
, void * context
)
4130 struct context
*theContext
= (struct context
*)context
;
4131 IOPowerStateChangeNotification notify
;
4137 refcon
= ((theContext
->serialNumber
& 0xFFFF)<<16) + (theContext
->counter
& 0xFFFF);
4138 IOLockLock(theContext
->flags_lock
);
4139 aBool
= OSBoolean::withBoolean(false);
4140 theContext
->responseFlags
->setObject(theContext
->counter
,aBool
);
4142 IOLockUnlock(theContext
->flags_lock
);
4144 notify
.powerRef
= (void *)refcon
;
4145 notify
.returnValue
= 0;
4146 notify
.stateNumber
= theContext
->stateNumber
;
4147 notify
.stateFlags
= theContext
->stateFlags
;
4148 retCode
= theContext
->us
->messageClient(theContext
->msgType
,object
,(void *)¬ify
);
4149 if ( retCode
== kIOReturnSuccess
)
4151 if ( notify
.returnValue
== 0 )
4153 // client doesn't want time to respond
4154 IOLockLock(theContext
->flags_lock
);
4155 aBool
= OSBoolean::withBoolean(true);
4156 // so set its flag true
4157 theContext
->responseFlags
->replaceObject(theContext
->counter
,aBool
);
4159 IOLockUnlock(theContext
->flags_lock
);
4161 IOLockLock(theContext
->flags_lock
);
4163 // it does want time, and it hasn't responded yet
4164 theFlag
= theContext
->responseFlags
->getObject(theContext
->counter
);
4167 if ( ((OSBoolean
*)theFlag
)->isFalse() )
4169 // so note its time requirement
4170 if ( theContext
->maxTimeRequested
< notify
.returnValue
)
4172 theContext
->maxTimeRequested
= notify
.returnValue
;
4176 IOLockUnlock(theContext
->flags_lock
);
4179 // not a client of ours
4180 IOLockLock(theContext
->flags_lock
);
4181 // so we won't be waiting for response
4182 aBool
= OSBoolean::withBoolean(true);
4183 theContext
->responseFlags
->replaceObject(theContext
->counter
,aBool
);
4185 IOLockUnlock(theContext
->flags_lock
);
4187 theContext
->counter
+= 1;
4191 //*********************************************************************************
4194 // Notify registered applications and kernel clients that we are not
4197 // Subclass can override this to send a different message type. Parameter is
4198 // the aborted destination state number.
4199 //*********************************************************************************
4201 void IOService::tellNoChangeDown ( unsigned long )
4203 return tellClients(kIOMessageDeviceWillNotPowerOff
);
4207 //*********************************************************************************
4210 // Notify registered applications and kernel clients that we are raising power.
4212 // Subclass can override this to send a different message type. Parameter is
4213 // the aborted destination state number.
4214 //*********************************************************************************
4216 void IOService::tellChangeUp ( unsigned long )
4218 return tellClients(kIOMessageDeviceHasPoweredOn
);
4222 //*********************************************************************************
4225 // Notify registered applications and kernel clients of something.
4226 //*********************************************************************************
4228 void IOService::tellClients ( int messageType
)
4230 struct context theContext
;
4232 theContext
.msgType
= messageType
;
4233 theContext
.us
= this;
4234 theContext
.stateNumber
= priv
->head_note_state
;
4235 theContext
.stateFlags
= priv
->head_note_capabilityFlags
;
4237 applyToInterested(gIOAppPowerStateInterest
,tellClient
,(void *)&theContext
);
4238 applyToInterested(gIOGeneralInterest
,tellClient
,(void *)&theContext
);
4242 //*********************************************************************************
4245 // Notify a registered application or kernel client of something.
4246 //*********************************************************************************
4247 void tellClient ( OSObject
* object
, void * context
)
4249 struct context
*theContext
= (struct context
*)context
;
4250 IOPowerStateChangeNotification notify
;
4252 notify
.powerRef
= (void *) 0;
4253 notify
.returnValue
= 0;
4254 notify
.stateNumber
= theContext
->stateNumber
;
4255 notify
.stateFlags
= theContext
->stateFlags
;
4257 theContext
->us
->messageClient(theContext
->msgType
,object
, ¬ify
);
4261 // **********************************************************************************
4264 // **********************************************************************************
4265 bool IOService::checkForDone ( void )
4270 IOLockLock(priv
->flags_lock
);
4271 if ( pm_vars
->responseFlags
== NULL
)
4273 IOLockUnlock(priv
->flags_lock
);
4277 for ( i
= 0; ; i
++ )
4279 theFlag
= pm_vars
->responseFlags
->getObject(i
);
4280 if ( theFlag
== NULL
)
4284 if ( ((OSBoolean
*)theFlag
)->isFalse() )
4286 IOLockUnlock(priv
->flags_lock
);
4290 IOLockUnlock(priv
->flags_lock
);
4295 // **********************************************************************************
4298 // **********************************************************************************
4299 bool IOService::responseValid ( unsigned long x
)
4301 UInt16 serialComponent
;
4302 UInt16 ordinalComponent
;
4304 unsigned long refcon
= (unsigned long)x
;
4307 serialComponent
= (refcon
>>16) & 0xFFFF;
4308 ordinalComponent
= refcon
& 0xFFFF;
4310 if ( serialComponent
!= pm_vars
->serialNumber
)
4315 IOLockLock(priv
->flags_lock
);
4316 if ( pm_vars
->responseFlags
== NULL
)
4318 IOLockUnlock(priv
->flags_lock
);
4322 theFlag
= pm_vars
->responseFlags
->getObject(ordinalComponent
);
4326 IOLockUnlock(priv
->flags_lock
);
4330 if ( ((OSBoolean
*)theFlag
)->isFalse() )
4332 aBool
= OSBoolean::withBoolean(true);
4333 pm_vars
->responseFlags
->replaceObject(ordinalComponent
,aBool
);
4337 IOLockUnlock(priv
->flags_lock
);
4342 // **********************************************************************************
4345 // Our power state is about to lower, and we have notified applications
4346 // and kernel clients, and one of them has acknowledged. If this is the last to do
4347 // so, and all acknowledgements are positive, we continue with the power change.
4349 // We serialize this processing with timer expiration with a command gate on the
4350 // power management workloop, which the timer expiration is command gated to as well.
4351 // **********************************************************************************
4352 IOReturn
IOService::allowPowerChange ( unsigned long refcon
)
4354 if ( ! initialized
)
4357 return kIOReturnSuccess
;
4360 return pm_vars
->PMcommandGate
->runAction(serializedAllowPowerChange
,(void *)refcon
);
4364 IOReturn
serializedAllowPowerChange ( OSObject
*owner
, void * refcon
, void *, void *, void *)
4366 return ((IOService
*)owner
)->serializedAllowPowerChange2((unsigned long)refcon
);
4369 IOReturn
IOService::serializedAllowPowerChange2 ( unsigned long refcon
)
4372 if ( ! responseValid(refcon
) )
4374 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr5
,refcon
,0);
4376 return kIOReturnSuccess
;
4378 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientAcknowledge
,refcon
,0);
4380 return allowCancelCommon();
4384 // **********************************************************************************
4385 // cancelPowerChange
4387 // Our power state is about to lower, and we have notified applications
4388 // and kernel clients, and one of them has vetoed the change. If this is the last
4389 // client to respond, we abandon the power change.
4391 // We serialize this processing with timer expiration with a command gate on the
4392 // power management workloop, which the timer expiration is command gated to as well.
4393 // **********************************************************************************
4394 IOReturn
IOService::cancelPowerChange ( unsigned long refcon
)
4396 if ( ! initialized
)
4399 return kIOReturnSuccess
;
4402 return pm_vars
->PMcommandGate
->runAction(serializedCancelPowerChange
,(void *)refcon
);
4406 IOReturn
serializedCancelPowerChange ( OSObject
*owner
, void * refcon
, void *, void *, void *)
4408 return ((IOService
*)owner
)->serializedCancelPowerChange2((unsigned long)refcon
);
4411 IOReturn
IOService::serializedCancelPowerChange2 ( unsigned long refcon
)
4414 if ( ! responseValid(refcon
) )
4416 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr5
,refcon
,0);
4418 return kIOReturnSuccess
;
4420 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientCancel
,refcon
,0);
4422 pm_vars
->doNotPowerDown
= true;
4424 return allowCancelCommon();
4428 // **********************************************************************************
4429 // allowCancelCommon
4431 // **********************************************************************************
4432 IOReturn
IOService::allowCancelCommon ( void )
4434 if (! acquire_lock() )
4436 return kIOReturnSuccess
;
4439 // is this the last response?
4440 if ( checkForDone() )
4442 // yes, stop the timer
4444 IOUnlock(priv
->our_lock
);
4445 IOLockLock(priv
->flags_lock
);
4446 if ( pm_vars
->responseFlags
)
4448 pm_vars
->responseFlags
->release();
4449 pm_vars
->responseFlags
= NULL
;
4451 IOLockUnlock(priv
->flags_lock
);
4452 switch (priv
->machine_state
) {
4453 case kIOPM_OurChangeTellClientsPowerDown
:
4454 // our change, was it vetoed?
4455 if ( ! pm_vars
->doNotPowerDown
)
4457 // no, we can continue
4458 OurChangeTellClientsPowerDown();
4460 // yes, rescind the warning
4461 tellNoChangeDown(priv
->head_note_state
);
4462 // mark the change note un-actioned
4463 priv
->head_note_flags
|= IOPMNotDone
;
4469 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
4470 OurChangeTellPriorityClientsPowerDown();
4472 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
4473 // our change, continue
4474 OurChangeNotifyInterestedDriversWillChange();
4476 case kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate
:
4477 // parent change, continue
4478 ParentDownTellPriorityClientsPowerDown_Delayed();
4480 case kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
:
4481 // parent change, continue
4482 ParentDownNotifyInterestedDriversWillChange_Delayed();
4487 IOUnlock(priv
->our_lock
);
4490 return kIOReturnSuccess
;
4494 //*********************************************************************************
4497 // Set to highest available power state for a minimum of duration milliseconds
4498 //*********************************************************************************
4500 #define kFiveMinutesInNanoSeconds (300 * NSEC_PER_SEC)
4502 void IOService::clampPowerOn (unsigned long duration
)
4505 changePowerStateToPriv (pm_vars->theNumberOfPowerStates-1);
4507 if ( priv->clampTimerEventSrc == NULL ) {
4508 priv->clampTimerEventSrc = IOTimerEventSource::timerEventSource(this,
4509 c_PM_Clamp_Timer_Expired);
4511 IOWorkLoop * workLoop = getPMworkloop ();
4513 if ( !priv->clampTimerEventSrc || !workLoop ||
4514 ( workLoop->addEventSource( priv->clampTimerEventSrc) != kIOReturnSuccess) ) {
4519 priv->clampTimerEventSrc->setTimeout(300*USEC_PER_SEC, USEC_PER_SEC);
4523 //*********************************************************************************
4524 // PM_Clamp_Timer_Expired
4526 // called when clamp timer expires...set power state to 0.
4527 //*********************************************************************************
4529 void IOService::PM_Clamp_Timer_Expired (void)
4531 if ( ! initialized
)
4537 changePowerStateToPriv (0);
4540 //*********************************************************************************
4541 // c_PM_clamp_Timer_Expired (C Func)
4543 // Called when our clamp timer expires...we will call the object method.
4544 //*********************************************************************************
4546 void c_PM_Clamp_Timer_Expired (OSObject
* client
, IOTimerEventSource
*)
4549 ((IOService
*)client
)->PM_Clamp_Timer_Expired ();
4553 //*********************************************************************************
4556 // Does nothing here. This should be implemented in a subclass driver.
4557 //*********************************************************************************
4559 IOReturn
IOService::setPowerState ( unsigned long powerStateOrdinal
, IOService
* whatDevice
)
4565 //*********************************************************************************
4566 // maxCapabilityForDomainState
4568 // Finds the highest power state in the array whose input power
4569 // requirement is equal to the input parameter. Where a more intelligent
4570 // decision is possible, override this in the subclassed driver.
4571 //*********************************************************************************
4573 unsigned long IOService::maxCapabilityForDomainState ( IOPMPowerFlags domainState
)
4577 if (pm_vars
->theNumberOfPowerStates
== 0 )
4581 for ( i
= (pm_vars
->theNumberOfPowerStates
)-1; i
>= 0; i
-- )
4583 if ( (domainState
& pm_vars
->thePowerStates
[i
].inputPowerRequirement
) == pm_vars
->thePowerStates
[i
].inputPowerRequirement
)
4592 //*********************************************************************************
4593 // initialPowerStateForDomainState
4595 // Finds the highest power state in the array whose input power
4596 // requirement is equal to the input parameter. Where a more intelligent
4597 // decision is possible, override this in the subclassed driver.
4598 //*********************************************************************************
4600 unsigned long IOService::initialPowerStateForDomainState ( IOPMPowerFlags domainState
)
4604 if (pm_vars
->theNumberOfPowerStates
== 0 )
4608 for ( i
= (pm_vars
->theNumberOfPowerStates
)-1; i
>= 0; i
-- )
4610 if ( (domainState
& pm_vars
->thePowerStates
[i
].inputPowerRequirement
) == pm_vars
->thePowerStates
[i
].inputPowerRequirement
)
4619 //*********************************************************************************
4620 // powerStateForDomainState
4622 // Finds the highest power state in the array whose input power
4623 // requirement is equal to the input parameter. Where a more intelligent
4624 // decision is possible, override this in the subclassed driver.
4625 //*********************************************************************************
4627 unsigned long IOService::powerStateForDomainState ( IOPMPowerFlags domainState
)
4631 if (pm_vars
->theNumberOfPowerStates
== 0 )
4635 for ( i
= (pm_vars
->theNumberOfPowerStates
)-1; i
>= 0; i
-- )
4637 if ( (domainState
& pm_vars
->thePowerStates
[i
].inputPowerRequirement
) == pm_vars
->thePowerStates
[i
].inputPowerRequirement
)
4646 //*********************************************************************************
4649 // Does nothing here. This should be implemented in a subclass driver.
4650 //*********************************************************************************
4652 bool IOService::didYouWakeSystem ( void )
4658 //*********************************************************************************
4659 // powerStateWillChangeTo
4661 // Does nothing here. This should be implemented in a subclass driver.
4662 //*********************************************************************************
4664 IOReturn
IOService::powerStateWillChangeTo ( IOPMPowerFlags
, unsigned long, IOService
*)
4670 //*********************************************************************************
4671 // powerStateDidChangeTo
4673 // Does nothing here. This should be implemented in a subclass driver.
4674 //*********************************************************************************
4676 IOReturn
IOService::powerStateDidChangeTo ( IOPMPowerFlags
, unsigned long, IOService
*)
4682 //*********************************************************************************
4685 // Does nothing here. This should be implemented in a subclass policy-maker.
4686 //*********************************************************************************
4688 void IOService::powerChangeDone ( unsigned long )
4693 //*********************************************************************************
4696 // Does nothing here. This should be implemented in a subclass driver.
4697 //*********************************************************************************
4699 IOReturn
IOService::newTemperature ( long currentTemp
, IOService
* whichZone
)
4707 #define super OSObject
4709 OSDefineMetaClassAndStructors(IOPMprot
, OSObject
)
4710 //*********************************************************************************
4713 // Serialize protected instance variables for debug output.
4714 //*********************************************************************************
4715 bool IOPMprot::serialize(OSSerialize
*s
) const
4717 OSString
* theOSString
;
4723 buffer
= ptr
= IONew(char, 2000);
4727 ptr
+= sprintf(ptr
,"{ theNumberOfPowerStates = %d, ",(unsigned int)theNumberOfPowerStates
);
4729 if ( theNumberOfPowerStates
!= 0 ) {
4730 ptr
+= sprintf(ptr
,"version %d, ",(unsigned int)thePowerStates
[0].version
);
4733 if ( theNumberOfPowerStates
!= 0 ) {
4734 for ( i
= 0; i
< (int)theNumberOfPowerStates
; i
++ ) {
4735 ptr
+= sprintf(ptr
,"power state %d = { ",i
);
4736 ptr
+= sprintf(ptr
,"capabilityFlags %08x, ",(unsigned int)thePowerStates
[i
].capabilityFlags
);
4737 ptr
+= sprintf(ptr
,"outputPowerCharacter %08x, ",(unsigned int)thePowerStates
[i
].outputPowerCharacter
);
4738 ptr
+= sprintf(ptr
,"inputPowerRequirement %08x, ",(unsigned int)thePowerStates
[i
].inputPowerRequirement
);
4739 ptr
+= sprintf(ptr
,"staticPower %d, ",(unsigned int)thePowerStates
[i
].staticPower
);
4740 ptr
+= sprintf(ptr
,"unbudgetedPower %d, ",(unsigned int)thePowerStates
[i
].unbudgetedPower
);
4741 ptr
+= sprintf(ptr
,"powerToAttain %d, ",(unsigned int)thePowerStates
[i
].powerToAttain
);
4742 ptr
+= sprintf(ptr
,"timeToAttain %d, ",(unsigned int)thePowerStates
[i
].timeToAttain
);
4743 ptr
+= sprintf(ptr
,"settleUpTime %d, ",(unsigned int)thePowerStates
[i
].settleUpTime
);
4744 ptr
+= sprintf(ptr
,"timeToLower %d, ",(unsigned int)thePowerStates
[i
].timeToLower
);
4745 ptr
+= sprintf(ptr
,"settleDownTime %d, ",(unsigned int)thePowerStates
[i
].settleDownTime
);
4746 ptr
+= sprintf(ptr
,"powerDomainBudget %d }, ",(unsigned int)thePowerStates
[i
].powerDomainBudget
);
4750 ptr
+= sprintf(ptr
,"aggressiveness = %d, ",(unsigned int)aggressiveness
);
4751 ptr
+= sprintf(ptr
,"myCurrentState = %d, ",(unsigned int)myCurrentState
);
4752 ptr
+= sprintf(ptr
,"parentsCurrentPowerFlags = %08x, ",(unsigned int)parentsCurrentPowerFlags
);
4753 ptr
+= sprintf(ptr
,"maxCapability = %d }",(unsigned int)maxCapability
);
4755 theOSString
= OSString::withCString(buffer
);
4756 rtn_code
= theOSString
->serialize(s
);
4757 theOSString
->release();
4758 IODelete(buffer
, char, 2000);
4765 #define super OSObject
4767 OSDefineMetaClassAndStructors(IOPMpriv
, OSObject
)
4768 //*********************************************************************************
4771 // Serialize private instance variables for debug output.
4772 //*********************************************************************************
4773 bool IOPMpriv::serialize(OSSerialize
*s
) const
4775 OSString
* theOSString
;
4779 IOPMinformee
* nextObject
;
4781 buffer
= ptr
= IONew(char, 2000);
4785 ptr
+= sprintf(ptr
,"{ this object = %08x",(unsigned int)owner
);
4786 if ( we_are_root
) {
4787 ptr
+= sprintf(ptr
," (root)");
4789 ptr
+= sprintf(ptr
,", ");
4791 nextObject
= interestedDrivers
->firstInList(); // display interested drivers
4792 while ( nextObject
!= NULL
) {
4793 ptr
+= sprintf(ptr
,"interested driver = %08x, ",(unsigned int)nextObject
->whatObject
);
4794 nextObject
= interestedDrivers
->nextInList(nextObject
);
4797 if ( machine_state
!= kIOPM_Finished
) {
4798 ptr
+= sprintf(ptr
,"machine_state = %d, ",(unsigned int)machine_state
);
4799 ptr
+= sprintf(ptr
,"driver_timer = %d, ",(unsigned int)driver_timer
);
4800 ptr
+= sprintf(ptr
,"settle_time = %d, ",(unsigned int)settle_time
);
4801 ptr
+= sprintf(ptr
,"head_note_flags = %08x, ",(unsigned int)head_note_flags
);
4802 ptr
+= sprintf(ptr
,"head_note_state = %d, ",(unsigned int)head_note_state
);
4803 ptr
+= sprintf(ptr
,"head_note_outputFlags = %08x, ",(unsigned int)head_note_outputFlags
);
4804 ptr
+= sprintf(ptr
,"head_note_domainState = %08x, ",(unsigned int)head_note_domainState
);
4805 ptr
+= sprintf(ptr
,"head_note_capabilityFlags = %08x, ",(unsigned int)head_note_capabilityFlags
);
4806 ptr
+= sprintf(ptr
,"head_note_pendingAcks = %d, ",(unsigned int)head_note_pendingAcks
);
4809 if ( device_overrides
) {
4810 ptr
+= sprintf(ptr
,"device overrides, ");
4812 ptr
+= sprintf(ptr
,"driverDesire = %d, ",(unsigned int)driverDesire
);
4813 ptr
+= sprintf(ptr
,"deviceDesire = %d, ",(unsigned int)deviceDesire
);
4814 ptr
+= sprintf(ptr
,"ourDesiredPowerState = %d, ",(unsigned int)ourDesiredPowerState
);
4815 ptr
+= sprintf(ptr
,"previousRequest = %d }",(unsigned int)previousRequest
);
4817 theOSString
= OSString::withCString(buffer
);
4818 rtn_code
= theOSString
->serialize(s
);
4819 theOSString
->release();
4820 IODelete(buffer
, char, 2000);