2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 #include <IOKit/assert.h>
25 #include <IOKit/IOCommandGate.h>
26 #include <IOKit/IOKitDebug.h>
27 #include <IOKit/IOLib.h>
28 #include <IOKit/IOMessage.h>
29 #include <IOKit/IOPlatformExpert.h>
30 #include <IOKit/IOService.h>
31 #include <IOKit/IOTimerEventSource.h>
32 #include <IOKit/IOWorkLoop.h>
34 #include <IOKit/pwr_mgt/IOPMchangeNoteList.h>
35 #include <IOKit/pwr_mgt/IOPMinformee.h>
36 #include <IOKit/pwr_mgt/IOPMinformeeList.h>
37 #include <IOKit/pwr_mgt/IOPMlog.h>
38 #include <IOKit/pwr_mgt/IOPowerConnection.h>
39 #include <IOKit/pwr_mgt/RootDomain.h>
41 // Required for notification instrumentation
42 #include "IOServicePrivate.h"
44 #define super IORegistryEntry
46 #define OUR_PMLog(t, a, b) \
47 do { pm_vars->thePlatform->PMLog(pm_vars->ourName, t, a, b); } while(0)
49 static void ack_timer_expired(thread_call_param_t
);
50 static void settle_timer_expired(thread_call_param_t
);
51 static void PM_idle_timer_expired(OSObject
*, IOTimerEventSource
*);
52 void tellAppWithResponse ( OSObject
* object
, void * context
);
53 void tellClientWithResponse ( OSObject
* object
, void * context
);
54 void tellClient ( OSObject
* object
, void * context
);
55 IOReturn
serializedAllowPowerChange ( OSObject
*, void *, void *, void *, void *);
56 IOReturn
serializedCancelPowerChange ( OSObject
*, void *, void *, void *, void *);
58 extern const IORegistryPlane
* gIOPowerPlane
;
61 // and there's 1000 nanoseconds in a microsecond:
62 #define ns_per_us 1000
65 // The current change note is processed by a state machine.
66 // Inputs are acks from interested parties, ack from the controlling driver,
67 // ack timeouts, settle timeout, and powerStateDidChange from the parent.
68 // These are the states:
70 kIOPM_OurChangeTellClientsPowerDown
= 1,
71 kIOPM_OurChangeTellPriorityClientsPowerDown
,
72 kIOPM_OurChangeNotifyInterestedDriversWillChange
,
73 kIOPM_OurChangeSetPowerState
,
74 kIOPM_OurChangeWaitForPowerSettle
,
75 kIOPM_OurChangeNotifyInterestedDriversDidChange
,
76 kIOPM_OurChangeFinish
,
77 kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate
,
78 kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
,
79 kIOPM_ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate
,
80 kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
,
81 kIOPM_ParentDownSetPowerState_Delayed
,
82 kIOPM_ParentDownWaitForPowerSettle_Delayed
,
83 kIOPM_ParentDownAcknowledgeChange_Delayed
,
84 kIOPM_ParentUpSetPowerState_Delayed
,
85 kIOPM_ParentUpSetPowerState_Immediate
,
86 kIOPM_ParentUpWaitForSettleTime_Delayed
,
87 kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed
,
88 kIOPM_ParentUpAcknowledgePowerChange_Delayed
,
92 // values of outofbandparameter
99 // used for applyToInterested
101 OSArray
* responseFlags
;
104 UInt32 maxTimeRequested
;
108 unsigned long stateNumber
;
109 IOPMPowerFlags stateFlags
;
112 // five minutes in microseconds
113 #define FIVE_MINUTES 5*60*1000000
114 #define k30seconds 30*1000000
117 There are two different kinds of power state changes. One is initiated by a subclassed device object which has either
118 decided to change power state, or its controlling driver has suggested it, or some other driver wants to use the
119 idle device and has asked it to become usable. The second kind of power state change is initiated by the power
120 domain parent. The two are handled slightly differently.
122 There is a queue of so-called change notifications, or change notes for short. Usually the queue is empty, and when
123 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
124 at one time, a queue is implemented. Example: the subclass device decides it's idle and initiates a change to a lower
125 power state. This causes interested parties to be notified, but they don't all acknowledge right away. This causes the
126 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
127 wants to raise power back up again. This change can't be started, however, because the previous one isn't complete yet,
128 so the second one waits in the queue. During this time, the parent decides to lower or raise the power state of the entire
129 power domain and notifies the device, and that notification goes into the queue, too, and can't be actioned until the
132 This is how a power change initiated by the subclass device is handled:
133 First, all interested parties are notified of the change via their powerStateWillChangeTo method. If they all don't
134 acknowledge via return code, then we have to wait. If they do, or when they finally all acknowledge via our
135 acknowledgePowerChange method, then we can continue. We call the controlling driver, instructing it to change to
136 the new state. Then we wait for power to settle. If there is no settling-time, or after it has passed, we notify
137 interested parties again, this time via their powerStateDidChangeTo methods. When they have all acked, we're done.
138 If we lowered power and don't need the power domain to be in its current power state, we suggest to the parent that
139 it lower the power domain state.
141 This is how a change to a lower power domain state initiated by the parent is handled:
142 First, we figure out what power state we will be in when the new domain state is reached. Then all interested parties are
143 notified that we are moving to that new state. When they have acknowledged, we call the controlling driver to assume
144 that state and we wait for power to settle. Then we acknowledge our preparedness to our parent. When all its interested
145 parties have acknowledged, it lowers power and then notifies its interested parties again. When we get this call, we notify
146 our interested parties that the power state has changed, and when they have all acknowledged, we're done.
148 This is how a change to a higher power domain state initiated by the parent is handled:
149 We figure out what power state we will be in when the new domain state is reached. If it is different from our current
150 state we acknowledge the parent. When all the parent's interested parties have acknowledged, it raises power in the
151 domain and waits for power to settle. Then it notifies everyone that the new state has been reached. When we get this call,
152 we call the controlling driver, instructing it to assume the new state, and wait for power to settle. Then we notify our interested
153 parties. When they all acknowledge we are done.
155 In either of the two cases above, it is possible that we will not be changing state even though the domain is. Examples:
156 A change to a lower domain state may not affect us because we are already in a low enough state, and
157 We will not take advantage of a change to a higher domain state, because we have no need of the higher power.
158 In such a case, there is nothing to do but acknowledge the parent. So when the parent calls our powerDomainWillChange
159 method, and we decide that we will not be changing state, we merely acknowledge the parent, via return code, and wait.
160 When the parent subsequently calls powerStateDidChange, we acknowledge again via return code, and the change is complete.
162 Power state changes are processed in a state machine, and since there are four varieties of power state changes, there are
163 four major paths through the state machine:
165 The fourth is nearly trivial. In this path, the parent is changing the domain state, but we are not changing the device state.
166 The change starts when the parent calls powerDomainWillChange. All we do is acknowledge the parent.
167 When the parent calls powerStateDidChange, we acknowledge the parent again, and we're done.
169 The first is fairly simple. It starts when a power domain child calls requestPowerDomainState and we decide to change power states
170 to accomodate the child, or if our power-controlling driver calls changePowerStateTo, or if some other driver which is using our
171 device calls makeUsable, or if a subclassed object calls changePowerStateToPriv. These are all power changes initiated by us, not
172 forced upon us by the parent. We start by notifying interested parties. If they all acknowledge via return code, we can go
173 on to state "OurChangeSetPowerState". Otherwise, we start the ack timer and wait for the stragglers to acknowlege by calling
174 acknowledgePowerChange. We move on to state "OurChangeSetPowerState" when all the stragglers have acknowledged,
175 or when the ack timer expires on all those which didn't acknowledge. In "OurChangeSetPowerState" we call the power-controlling
176 driver to change the power state of the hardware. If it returns saying it has done so, we go on to state "OurChangeWaitForPowerSettle".
177 Otherwise, we have to wait for it, so we set the ack timer and wait. When it calls acknowledgeSetPowerState, or when the
178 ack timer expires, we go on. In "OurChangeWaitForPowerSettle", we look in the power state array to see if there is any settle time required
179 when changing from our current state to the new state. If not, we go right away to "OurChangeNotifyInterestedDriversDidChange". Otherwise, we
180 set the settle timer and wait. When it expires, we move on. In "OurChangeNotifyInterestedDriversDidChange" state, we notify all our interested parties
181 via their powerStateDidChange methods that we have finished changing power state. If they all acknowledge via return
182 code, we move on to "OurChangeFinish". Otherwise we set the ack timer and wait. When they have all acknowledged, or
183 when the ack timer has expired for those that didn't, we move on to "OurChangeFinish", where we remove the used
184 change note from the head of the queue and start the next one if one exists.
186 Parent-initiated changes are more complex in the state machine. First, power going up and power going down are handled
187 differently, so they have different paths throught the state machine. Second, we can acknowledge the parent's notification
188 in two different ways, so each of the parent paths is really two.
190 When the parent calls our powerDomainWillChange method, notifying us that it will lower power in the domain, we decide
191 what state that will put our device in. Then we embark on the state machine path "IOPMParentDownSetPowerState_Immediate"
192 and "kIOPM_ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate", in which we notify interested parties of the upcoming change, instruct our driver to make
193 the change, check for settle time, and notify interested parties of the completed change. If we get to the end of this path without
194 stalling due to an interested party which didn't acknowledge via return code, due to the controlling driver not able to change
195 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.
196 If we do stall in any of those states, we return IOPMWillAckLater to the parent and enter the parallel path "kIOPM_ParentDownSetPowerState_Delayed"
197 "kIOPM_ParentDownWaitForPowerSettle_Delayed", and "kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed", where we continue with the same processing, except that at the end we
198 acknowledge the parent explicitly via acknowledgePowerChange, and we're done with the change.
199 Then when the parent calls us at powerStateDidChange we acknowledging via return code, because we have already made
200 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.
202 The case of the parent raising power in the domain is handled similarly in that there are parallel paths, one for no-stall
203 that ends in implicit acknowleging the parent, and one that has stalled at least once that ends in explicit acknowledging
204 the parent. This case is different, though in that our device changes state in the second half, after the parent calls
205 powerStateDidChange rather than before, as in the power-lowering case.
207 When the parent calls our powerDomainWillChange method, notifying us that it will raise power in the domain, we acknowledge
208 via return code, because there's really nothing we can do until the power is actually raised in the domain.
209 When the parent calls us at powerStateDidChange, we start by notifying our interested parties. If they all acknowledge via return code,
210 we go on to" kIOPM_ParentUpSetPowerState_Immediate" to instruct the driver to raise its power level. After that, we check for any
211 necessary settling time in "IOPMParentUpWaitForSettleTime_Immediate", and we notify all interested parties that power has changed
212 in "IOPMParentUpNotifyInterestedDriversDidChange_Immediate". If none of these operations stall, we acknowledge the parent via return code, release
213 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",
214 "kIOPM_ParentUpWaitForSettleTime_Delayed", "kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed", and "kIOPM_ParentUpAcknowledgePowerChange_Delayed", which ends with
215 our explicit acknowledgement to the parent.
220 const char priv_key
[ ] = "Power Management private data";
221 const char prot_key
[ ] = "Power Management protected data";
224 void IOService::PMinit ( void )
226 if ( ! initialized
) {
228 // make space for our variables
229 pm_vars
= new IOPMprot
;
235 // add pm_vars & priv to the properties
236 setProperty(prot_key
, (OSObject
*) pm_vars
);
237 setProperty(priv_key
, (OSObject
*) priv
);
239 // then initialize them
241 pm_vars
->theNumberOfPowerStates
= 0;
242 priv
->we_are_root
= false;
243 pm_vars
->theControllingDriver
= NULL
;
244 priv
->our_lock
= IOLockAlloc();
245 priv
->flags_lock
= IOLockAlloc();
246 priv
->queue_lock
= IOLockAlloc();
247 pm_vars
->childLock
= IOLockAlloc();
248 pm_vars
->parentLock
= IOLockAlloc();
249 priv
->interestedDrivers
= new IOPMinformeeList
;
250 priv
->interestedDrivers
->initialize();
251 priv
->changeList
= new IOPMchangeNoteList
;
252 priv
->changeList
->initialize();
253 pm_vars
->aggressiveness
= 0;
254 for (unsigned int i
= 0; i
<= kMaxType
; i
++)
256 pm_vars
->current_aggressiveness_values
[i
] = 0;
257 pm_vars
->current_aggressiveness_valid
[i
] = false;
259 pm_vars
->myCurrentState
= 0;
260 priv
->imminentState
= 0;
261 priv
->ourDesiredPowerState
= 0;
262 pm_vars
->parentsCurrentPowerFlags
= 0;
263 pm_vars
->maxCapability
= 0;
264 priv
->driverDesire
= 0;
265 priv
->deviceDesire
= 0;
266 priv
->initial_change
= true;
267 priv
->need_to_become_usable
= false;
268 priv
->previousRequest
= 0;
269 priv
->device_overrides
= false;
270 priv
->machine_state
= kIOPM_Finished
;
271 priv
->timerEventSrc
= NULL
;
272 priv
->clampTimerEventSrc
= NULL
;
273 pm_vars
->PMworkloop
= NULL
;
274 priv
->activityLock
= NULL
;
275 pm_vars
->ourName
= getName();
276 pm_vars
->thePlatform
= getPlatform();
277 pm_vars
->parentsKnowState
= false;
278 assert( pm_vars
->thePlatform
!= 0 );
279 priv
->clampOn
= false;
280 pm_vars
->serialNumber
= 0;
281 pm_vars
->responseFlags
= NULL
;
282 pm_vars
->doNotPowerDown
= true;
283 pm_vars
->PMcommandGate
= NULL
;
284 priv
->ackTimer
= thread_call_allocate((thread_call_func_t
)ack_timer_expired
, (thread_call_param_t
)this);
285 priv
->settleTimer
= thread_call_allocate((thread_call_func_t
)settle_timer_expired
, (thread_call_param_t
)this);
291 //*********************************************************************************
294 // Free up the data created in PMinit, if it exists.
295 //*********************************************************************************
296 void IOService::PMfree ( void )
299 if ( priv
->clampTimerEventSrc
!= NULL
) {
300 getPMworkloop()->removeEventSource(priv
->clampTimerEventSrc
);
301 priv
->clampTimerEventSrc
->release();
302 priv
->clampTimerEventSrc
= NULL
;
304 if ( priv
->timerEventSrc
!= NULL
) {
305 pm_vars
->PMworkloop
->removeEventSource(priv
->timerEventSrc
);
306 priv
->timerEventSrc
->release();
307 priv
->timerEventSrc
= NULL
;
309 if ( priv
->settleTimer
) {
310 thread_call_cancel(priv
->settleTimer
);
311 thread_call_free(priv
->settleTimer
);
312 priv
->settleTimer
= NULL
;
314 if ( priv
->ackTimer
) {
315 thread_call_cancel(priv
->ackTimer
);
316 thread_call_free(priv
->ackTimer
);
317 priv
->ackTimer
= NULL
;
319 if ( priv
->our_lock
) {
320 IOLockFree(priv
->our_lock
);
321 priv
->our_lock
= NULL
;
323 if ( priv
->flags_lock
) {
324 IOLockFree(priv
->flags_lock
);
325 priv
->flags_lock
= NULL
;
327 if ( priv
->activityLock
) {
328 IOLockFree(priv
->activityLock
);
329 priv
->activityLock
= NULL
;
331 priv
->interestedDrivers
->release();
332 priv
->changeList
->release();
333 // remove instance variables
338 if ( pm_vars
->PMcommandGate
) {
339 if(pm_vars
->PMworkloop
)
340 pm_vars
->PMworkloop
->removeEventSource(pm_vars
->PMcommandGate
);
341 pm_vars
->PMcommandGate
->release();
342 pm_vars
->PMcommandGate
= NULL
;
344 if ( pm_vars
->PMworkloop
) {
345 // The work loop object returned from getPMworkLoop() is
346 // never retained, therefore it should not be released.
347 // pm_vars->PMworkloop->release();
348 pm_vars
->PMworkloop
= NULL
;
350 if ( pm_vars
->responseFlags
) {
351 pm_vars
->responseFlags
->release();
352 pm_vars
->responseFlags
= NULL
;
354 // remove instance variables
360 //*********************************************************************************
363 // Disconnect the node from its parents and children in the Power Plane.
364 //*********************************************************************************
365 void IOService::PMstop ( void )
369 IOPowerConnection
* connection
;
370 IOService
* theChild
;
371 IOService
* theParent
;
373 // remove the properties
374 removeProperty(prot_key
);
375 removeProperty(priv_key
);
378 iter
= getParentIterator(gIOPowerPlane
);
382 while ( (next
= iter
->getNextObject()) )
384 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
386 theParent
= (IOService
*)connection
->copyParentEntry(gIOPowerPlane
);
389 theParent
->removePowerChild(connection
);
390 theParent
->release();
397 // detach IOConnections
398 detachAbove( gIOPowerPlane
);
402 // no more power state changes
403 pm_vars
->parentsKnowState
= false;
407 iter
= getChildIterator(gIOPowerPlane
);
411 while ( (next
= iter
->getNextObject()) )
413 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
415 theChild
= ((IOService
*)(connection
->copyChildEntry(gIOPowerPlane
)));
418 // detach nub from child
419 connection
->detachFromChild(theChild
,gIOPowerPlane
);
422 // detach us from nub
423 detachFromChild(connection
,gIOPowerPlane
);
429 // Remove all interested drivers from the list, including the power
430 // controlling driver.
432 // Usually, the controlling driver and the policy-maker functionality
433 // are implemented by the same object, and without the deregistration,
434 // the object will be holding an extra retain on itself, and cannot
437 if ( priv
&& priv
->interestedDrivers
)
439 IOPMinformee
* informee
;
441 while (( informee
= priv
->interestedDrivers
->firstInList() ))
442 deRegisterInterestedDriver( informee
->whatObject
);
447 //*********************************************************************************
450 // A policy-maker calls its nub here when initializing, to be attached into
451 // the power management hierarchy. The default function is to call the
452 // platform expert, which knows how to do it. This method is overridden
453 // by a nub subclass which may either know how to do it, or may need
454 // to take other action.
456 // This may be the only "power management" method used in a nub,
457 // meaning it may not be initialized for power management.
458 //*********************************************************************************
459 void IOService::joinPMtree ( IOService
* driver
)
461 IOPlatformExpert
* thePlatform
;
463 thePlatform
= getPlatform();
464 assert(thePlatform
!= 0 );
465 thePlatform
->PMRegisterDevice(this,driver
);
469 //*********************************************************************************
472 // Power Managment is informing us that we are the root power domain.
473 // The only difference between us and any other power domain is that
474 // we have no parent and therefore never call it.
475 //*********************************************************************************
476 IOReturn
IOService::youAreRoot ( void )
478 priv
-> we_are_root
= true;
479 pm_vars
->parentsKnowState
= true;
480 attachToParent( getRegistryRoot(),gIOPowerPlane
);
486 //*********************************************************************************
489 // Power Management is informing us who our parent is.
490 // If we have a controlling driver, find out, given our newly-informed
491 // power domain state, what state it would be in, and then tell it
492 // to assume that state.
493 //*********************************************************************************
494 IOReturn
IOService::setPowerParent ( IOPowerConnection
* theParent
, bool stateKnown
, IOPMPowerFlags currentState
)
498 IOPowerConnection
* connection
;
499 unsigned long tempDesire
;
501 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogSetParent
,stateKnown
,currentState
);
503 IOLockLock(pm_vars
->parentLock
);
505 if ( stateKnown
&& ((pm_vars
->PMworkloop
== NULL
) || (pm_vars
->PMcommandGate
== NULL
)) )
507 // we have a path to the root
508 // find out the workloop
510 if ( pm_vars
->PMworkloop
!= NULL
)
512 if ( pm_vars
->PMcommandGate
== NULL
)
514 // and make our command gate
515 pm_vars
->PMcommandGate
= IOCommandGate::commandGate((OSObject
*)this);
516 if ( pm_vars
->PMcommandGate
!= NULL
)
518 pm_vars
->PMworkloop
->addEventSource(pm_vars
->PMcommandGate
);
524 IOLockUnlock(pm_vars
->parentLock
);
526 // set our connection data
527 theParent
->setParentCurrentPowerFlags(currentState
);
528 theParent
->setParentKnowsState(stateKnown
);
530 // combine parent knowledge
531 pm_vars
->parentsKnowState
= true;
532 pm_vars
->parentsCurrentPowerFlags
= 0;
534 iter
= getParentIterator(gIOPowerPlane
);
538 while ( (next
= iter
->getNextObject()) )
540 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
542 pm_vars
->parentsKnowState
&= connection
->parentKnowsState();
543 pm_vars
->parentsCurrentPowerFlags
|= connection
->parentCurrentPowerFlags();
549 if ( (pm_vars
->theControllingDriver
!= NULL
) &&
550 (pm_vars
->parentsKnowState
) )
552 pm_vars
->maxCapability
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(pm_vars
->parentsCurrentPowerFlags
);
553 // initially change into the state we are already in
554 tempDesire
= priv
->deviceDesire
;
555 priv
->deviceDesire
= pm_vars
->theControllingDriver
->initialPowerStateForDomainState(pm_vars
->parentsCurrentPowerFlags
);
556 computeDesiredState();
557 priv
->previousRequest
= 0xffffffff;
559 // put this back like before
560 priv
->deviceDesire
= tempDesire
;
567 //*********************************************************************************
570 // Power Management is informing us who our children are.
571 //*********************************************************************************
572 IOReturn
IOService::addPowerChild ( IOService
* theChild
)
574 IOPowerConnection
*connection
;
579 // we're not a power-managed IOService
580 return IOPMNotYetInitialized
;
583 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAddChild
,0,0);
585 // Put ourselves into a usable power state.
586 // We must be in an "on" power state, as our children must be able to access
587 // our hardware after joining the power plane.
591 connection
= new IOPowerConnection
;
594 connection
->start(this);
595 connection
->setAwaitingAck(false);
598 attachToChild( connection
,gIOPowerPlane
);
599 connection
->attachToChild( theChild
,gIOPowerPlane
);
600 connection
->release();
602 // tell it the current state of the power domain
603 if ( (pm_vars
->theControllingDriver
== NULL
) ||
604 ! (inPlane(gIOPowerPlane
)) ||
605 ! (pm_vars
->parentsKnowState
) )
607 theChild
->setPowerParent(connection
,false,0);
608 if ( inPlane(gIOPowerPlane
) )
610 for (i
= 0; i
<= kMaxType
; i
++) {
611 if ( pm_vars
->current_aggressiveness_valid
[i
] )
613 theChild
->setAggressiveness (i
, pm_vars
->current_aggressiveness_values
[i
]);
618 theChild
->setPowerParent(connection
,true,pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].outputPowerCharacter
);
619 for (i
= 0; i
<= kMaxType
; i
++)
621 if ( pm_vars
->current_aggressiveness_valid
[i
] )
623 theChild
->setAggressiveness (i
, pm_vars
->current_aggressiveness_values
[i
]);
626 // catch it up if change is in progress
627 add_child_to_active_change(connection
);
634 //*********************************************************************************
637 //*********************************************************************************
638 IOReturn
IOService::removePowerChild ( IOPowerConnection
* theNub
)
640 IORegistryEntry
*theChild
;
643 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRemoveChild
,0,0);
647 // detach nub from child
648 theChild
= theNub
->copyChildEntry(gIOPowerPlane
);
651 theNub
->detachFromChild(theChild
, gIOPowerPlane
);
654 // detach from the nub
655 detachFromChild(theNub
,gIOPowerPlane
);
657 // are we awaiting an ack from this child?
658 if ( theNub
->getAwaitingAck() )
660 // yes, pretend we got one
661 theNub
->setAwaitingAck(false);
662 if ( acquire_lock() )
664 if (priv
->head_note_pendingAcks
!= 0 )
666 // that's one fewer ack to worry about
667 priv
->head_note_pendingAcks
-= 1;
669 if ( priv
->head_note_pendingAcks
== 0 )
671 // yes, stop the timer
673 IOUnlock(priv
->our_lock
);
674 // and now we can continue our power change
677 IOUnlock(priv
->our_lock
);
680 IOUnlock(priv
->our_lock
);
687 // if not fully initialized
688 if ( (pm_vars
->theControllingDriver
== NULL
) ||
689 !(inPlane(gIOPowerPlane
)) ||
690 !(pm_vars
->parentsKnowState
) )
696 // Perhaps the departing child was holding up idle or system sleep - we need to re-evaluate our
697 // childrens' requests. Clear and re-calculate our kIOPMChildClamp and kIOPMChildClamp2 bits.
698 rebuildChildClampBits();
703 iter
= getChildIterator(gIOPowerPlane
);
704 if ( !iter
|| !iter
->getNextObject() )
706 // paired to match the makeUsable() call in addPowerChild()
707 changePowerStateToPriv(0);
709 if(iter
) iter
->release();
712 // this may be different now
713 computeDesiredState();
714 // change state if we can now tolerate lower power
721 //*********************************************************************************
722 // registerPowerDriver
724 // A driver has called us volunteering to control power to our device.
725 // If the power state array it provides is richer than the one we already
726 // know about (supplied by an earlier volunteer), then accept the offer.
727 // Notify all interested parties of our power state, which we now know.
728 //*********************************************************************************
730 IOReturn
IOService::registerPowerDriver ( IOService
* controllingDriver
, IOPMPowerState
* powerStates
, unsigned long numberOfStates
)
733 unsigned long tempDesire
;
735 if ( (numberOfStates
> pm_vars
->theNumberOfPowerStates
)
736 && (numberOfStates
> 1) )
738 if ( priv
->changeList
->currentChange() == -1 )
740 if ( controllingDriver
!= NULL
)
742 if ( numberOfStates
<= IOPMMaxPowerStates
)
744 switch ( powerStates
[0].version
)
747 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriver
,
748 (unsigned long)numberOfStates
, (unsigned long)powerStates
[0].version
);
749 for ( i
= 0; i
< numberOfStates
; i
++ )
751 pm_vars
->thePowerStates
[i
] = powerStates
[i
];
755 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriver
,
756 (unsigned long) numberOfStates
,(unsigned long) powerStates
[0].version
);
757 for ( i
= 0; i
< numberOfStates
; i
++ )
759 pm_vars
->thePowerStates
[i
].version
= powerStates
[i
].version
;
760 pm_vars
->thePowerStates
[i
].capabilityFlags
= powerStates
[i
].capabilityFlags
;
761 pm_vars
->thePowerStates
[i
].outputPowerCharacter
= powerStates
[i
].outputPowerCharacter
;
762 pm_vars
->thePowerStates
[i
].inputPowerRequirement
= powerStates
[i
].inputPowerRequirement
;
763 pm_vars
->thePowerStates
[i
].staticPower
= powerStates
[i
].staticPower
;
764 pm_vars
->thePowerStates
[i
].unbudgetedPower
= powerStates
[i
].unbudgetedPower
;
765 pm_vars
->thePowerStates
[i
].powerToAttain
= powerStates
[i
].powerToAttain
;
766 pm_vars
->thePowerStates
[i
].timeToAttain
= powerStates
[i
].timeToAttain
;
767 pm_vars
->thePowerStates
[i
].settleUpTime
= powerStates
[i
].settleUpTime
;
768 pm_vars
->thePowerStates
[i
].timeToLower
= powerStates
[i
].timeToLower
;
769 pm_vars
->thePowerStates
[i
].settleDownTime
= powerStates
[i
].settleDownTime
;
770 pm_vars
->thePowerStates
[i
].powerDomainBudget
= powerStates
[i
].powerDomainBudget
;
774 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr1
,
775 (unsigned long)powerStates
[0].version
,0);
779 // make a mask of all the character bits we know about
780 pm_vars
->myCharacterFlags
= 0;
781 for ( i
= 0; i
< numberOfStates
; i
++ ) {
782 pm_vars
->myCharacterFlags
|= pm_vars
->thePowerStates
[i
].outputPowerCharacter
;
785 pm_vars
->theNumberOfPowerStates
= numberOfStates
;
786 pm_vars
->theControllingDriver
= controllingDriver
;
787 if ( priv
->interestedDrivers
->findItem(controllingDriver
) == NULL
)
789 // register it as interested, unless already done
790 registerInterestedDriver (controllingDriver
);
792 if ( priv
->need_to_become_usable
) {
793 priv
->need_to_become_usable
= false;
794 priv
->deviceDesire
= pm_vars
->theNumberOfPowerStates
- 1;
797 if ( inPlane(gIOPowerPlane
) &&
798 (pm_vars
->parentsKnowState
) ) {
799 pm_vars
->maxCapability
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(pm_vars
->parentsCurrentPowerFlags
);
800 // initially change into the state we are already in
801 tempDesire
= priv
->deviceDesire
;
802 priv
->deviceDesire
= pm_vars
->theControllingDriver
->initialPowerStateForDomainState(pm_vars
->parentsCurrentPowerFlags
);
803 computeDesiredState();
805 // put this back like before
806 priv
->deviceDesire
= tempDesire
;
809 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr2
,(unsigned long)numberOfStates
,0);
812 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr4
,0,0);
817 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr5
,(unsigned long)numberOfStates
,0);
822 //*********************************************************************************
823 // registerInterestedDriver
825 // Add the caller to our list of interested drivers and return our current
826 // power state. If we don't have a power-controlling driver yet, we will
827 // call this interested driver again later when we do get a driver and find
828 // out what the current power state of the device is.
829 //*********************************************************************************
831 IOPMPowerFlags
IOService::registerInterestedDriver ( IOService
* theDriver
)
833 IOPMinformee
*newInformee
;
834 IOPMPowerFlags futureCapability
;
836 if (theDriver
== NULL
) {
840 // make new driver node
841 newInformee
= new IOPMinformee
;
842 newInformee
->initialize(theDriver
);
843 // add it to list of drivers
844 priv
->interestedDrivers
->addToList(newInformee
);
846 if ( (pm_vars
->theControllingDriver
== NULL
) ||
847 !(inPlane(gIOPowerPlane
)) ||
848 !(pm_vars
->parentsKnowState
) )
850 // can't tell it a state yet
851 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInterestedDriver
,IOPMNotPowerManaged
,0);
852 return IOPMNotPowerManaged
;
855 // can we notify new driver of a change in progress?
856 switch (priv
->machine_state
) {
857 case kIOPM_OurChangeSetPowerState
:
858 case kIOPM_OurChangeFinish
:
859 case kIOPM_ParentDownSetPowerState_Delayed
:
860 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
861 case kIOPM_ParentUpSetPowerState_Delayed
:
862 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
863 // yes, remember what we tell it
864 futureCapability
= priv
->head_note_capabilityFlags
;
865 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInterestedDriver
,(unsigned long)futureCapability
,1);
867 add_driver_to_active_change(newInformee
);
868 // and return the same thing
869 return futureCapability
;
872 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInterestedDriver
,
873 (unsigned long) pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
,2);
875 // no, return current capability
876 return pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
;
880 //*********************************************************************************
881 // deRegisterInterestedDriver
883 //*********************************************************************************
884 IOReturn
IOService::deRegisterInterestedDriver ( IOService
* theDriver
)
886 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRemoveDriver
,0,0);
888 // remove the departing driver
889 priv
->interestedDrivers
->removeFromList(theDriver
);
895 //*********************************************************************************
896 // acknowledgePowerChange
898 // After we notified one of the interested drivers or a power-domain child
899 // of an impending change in power, it has called to say it is now
900 // prepared for the change. If this object is the last to
901 // acknowledge this change, we take whatever action we have been waiting
903 // That may include acknowledging to our parent. In this case, we do it
904 // last of all to insure that this doesn't cause the parent to call us some-
905 // where else and alter data we are relying on here (like the very existance
906 // of a "current change note".)
907 //*********************************************************************************
909 IOReturn
IOService::acknowledgePowerChange ( IOService
* whichObject
)
911 IOPMinformee
*ackingObject
;
912 unsigned long childPower
= kIOPMUnknown
;
915 // one of our interested drivers?
916 ackingObject
= priv
->interestedDrivers
->findItem(whichObject
);
917 if ( ackingObject
== NULL
)
919 if ( ! isChild(whichObject
,gIOPowerPlane
) )
921 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr1
,0,0);
922 //kprintf("errant driver: %s\n",whichObject->getName());
926 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChildAcknowledge
,priv
->head_note_pendingAcks
,0);
929 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogDriverAcknowledge
,priv
->head_note_pendingAcks
,0);
932 if (! acquire_lock() )
937 if (priv
->head_note_pendingAcks
!= 0 )
939 // yes, make sure we're expecting acks
940 if ( ackingObject
!= NULL
)
942 // it's an interested driver
943 // make sure we're expecting this ack
944 if ( ackingObject
->timer
!= 0 )
947 ackingObject
->timer
= 0;
948 // that's one fewer to worry about
949 priv
->head_note_pendingAcks
-= 1;
951 if ( priv
->head_note_pendingAcks
== 0 )
953 // yes, stop the timer
955 IOUnlock(priv
->our_lock
);
956 // and now we can continue
961 // this driver has already acked
962 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr2
,0,0);
963 //kprintf("errant driver: %s\n",whichObject->getName());
967 // make sure we're expecting this ack
968 if ( ((IOPowerConnection
*)whichObject
)->getAwaitingAck() )
970 // that's one fewer to worry about
971 priv
->head_note_pendingAcks
-= 1;
972 ((IOPowerConnection
*)whichObject
)->setAwaitingAck(false);
973 theChild
= (IOService
*)whichObject
->copyChildEntry(gIOPowerPlane
);
976 childPower
= theChild
->currentPowerConsumption();
979 if ( childPower
== kIOPMUnknown
)
981 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
= kIOPMUnknown
;
983 if ( pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
!= kIOPMUnknown
)
985 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
+= childPower
;
989 if ( priv
->head_note_pendingAcks
== 0 ) {
990 // yes, stop the timer
992 IOUnlock(priv
->our_lock
);
993 // and now we can continue
1000 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr3
,0,0); // not expecting anybody to ack
1001 //kprintf("errant driver: %s\n",whichObject->getName());
1003 IOUnlock(priv
->our_lock
);
1007 //*********************************************************************************
1008 // acknowledgeSetPowerState
1010 // After we instructed our controlling driver to change power states,
1011 // it has called to say it has finished doing so.
1012 // We continue to process the power state change.
1013 //*********************************************************************************
1015 IOReturn
IOService::acknowledgeSetPowerState ( void )
1017 if (!acquire_lock())
1020 IOReturn timer
= priv
->driver_timer
;
1021 if ( timer
== -1 ) {
1022 // driver is acking instead of using return code
1023 OUR_PMLog(kPMLogDriverAcknowledgeSet
, (UInt32
) this, timer
);
1024 priv
->driver_timer
= 0;
1026 else if ( timer
> 0 ) { // are we expecting this?
1027 // yes, stop the timer
1029 priv
->driver_timer
= 0;
1030 OUR_PMLog(kPMLogDriverAcknowledgeSet
, (UInt32
) this, timer
);
1031 IOUnlock(priv
->our_lock
);
1035 // not expecting this
1036 OUR_PMLog(kPMLogAcknowledgeErr4
, (UInt32
) this, 0);
1039 IOUnlock(priv
->our_lock
);
1044 //*********************************************************************************
1047 // Either the controlling driver has called acknowledgeSetPowerState
1048 // or the acknowledgement timer has expired while waiting for that.
1049 // We carry on processing the current change note.
1050 //*********************************************************************************
1052 void IOService::driver_acked ( void )
1054 switch (priv
->machine_state
) {
1055 case kIOPM_OurChangeWaitForPowerSettle
:
1056 OurChangeWaitForPowerSettle();
1058 case kIOPM_ParentDownWaitForPowerSettle_Delayed
:
1059 ParentDownWaitForPowerSettle_Delayed();
1061 case kIOPM_ParentUpWaitForSettleTime_Delayed
:
1062 ParentUpWaitForSettleTime_Delayed();
1068 //*********************************************************************************
1069 // powerDomainWillChangeTo
1071 // Called by the power-hierarchy parent notifying of a new power state
1072 // in the power domain.
1073 // We enqueue a parent power-change to our queue of power changes.
1074 // This may or may not cause us to change power, depending on what
1075 // kind of change is occuring in the domain.
1076 //*********************************************************************************
1078 IOReturn
IOService::powerDomainWillChangeTo ( IOPMPowerFlags newPowerStateFlags
, IOPowerConnection
* whichParent
)
1082 IOPowerConnection
*connection
;
1083 unsigned long newStateNumber
;
1084 IOPMPowerFlags combinedPowerFlags
;
1086 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogWillChange
,(unsigned long)newPowerStateFlags
,0);
1088 if ( ! inPlane(gIOPowerPlane
) )
1091 return IOPMAckImplied
;
1094 IOLockLock(pm_vars
->parentLock
);
1096 if ( (pm_vars
->PMworkloop
== NULL
) || (pm_vars
->PMcommandGate
== NULL
) )
1098 // we have a path to the root
1100 // so find out the workloop
1101 if ( pm_vars
->PMworkloop
!= NULL
)
1103 // and make our command gate
1104 if ( pm_vars
->PMcommandGate
== NULL
)
1106 pm_vars
->PMcommandGate
= IOCommandGate::commandGate((OSObject
*)this);
1107 if ( pm_vars
->PMcommandGate
!= NULL
)
1109 pm_vars
->PMworkloop
->addEventSource(pm_vars
->PMcommandGate
);
1115 IOLockUnlock(pm_vars
->parentLock
);
1117 // combine parents' power states
1118 // to determine our maximum state within the new power domain
1119 combinedPowerFlags
= 0;
1121 iter
= getParentIterator(gIOPowerPlane
);
1125 while ( (next
= iter
->getNextObject()) )
1127 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1129 if ( connection
== whichParent
){
1130 combinedPowerFlags
|= newPowerStateFlags
;
1132 combinedPowerFlags
|= connection
->parentCurrentPowerFlags();
1139 if ( pm_vars
->theControllingDriver
== NULL
)
1141 // we can't take any more action
1142 return IOPMAckImplied
;
1144 newStateNumber
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(combinedPowerFlags
);
1146 return enqueuePowerChange(IOPMParentInitiated
| IOPMDomainWillChange
,
1147 newStateNumber
,combinedPowerFlags
,whichParent
,newPowerStateFlags
);
1151 //*********************************************************************************
1152 // powerDomainDidChangeTo
1154 // Called by the power-hierarchy parent after the power state of the power domain
1155 // has settled at a new level.
1156 // We enqueue a parent power-change to our queue of power changes.
1157 // This may or may not cause us to change power, depending on what
1158 // kind of change is occuring in the domain.
1159 //*********************************************************************************
1161 IOReturn
IOService::powerDomainDidChangeTo ( IOPMPowerFlags newPowerStateFlags
, IOPowerConnection
* whichParent
)
1163 unsigned long newStateNumber
;
1165 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogDidChange
,newPowerStateFlags
,0);
1167 setParentInfo(newPowerStateFlags
,whichParent
);
1169 if ( pm_vars
->theControllingDriver
== NULL
) {
1170 return IOPMAckImplied
;
1173 newStateNumber
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(pm_vars
->parentsCurrentPowerFlags
);
1174 // tell interested parties about it
1175 return enqueuePowerChange(IOPMParentInitiated
| IOPMDomainDidChange
,
1176 newStateNumber
,pm_vars
->parentsCurrentPowerFlags
,whichParent
,0);
1180 //*********************************************************************************
1183 // Set our connection data for one specific parent, and then combine all the parent
1185 //*********************************************************************************
1187 void IOService::setParentInfo ( IOPMPowerFlags newPowerStateFlags
, IOPowerConnection
* whichParent
)
1191 IOPowerConnection
*connection
;
1193 // set our connection data
1194 whichParent
->setParentCurrentPowerFlags(newPowerStateFlags
);
1195 whichParent
->setParentKnowsState(true);
1197 IOLockLock(pm_vars
->parentLock
);
1199 // recompute our parent info
1200 pm_vars
->parentsCurrentPowerFlags
= 0;
1201 pm_vars
->parentsKnowState
= true;
1203 iter
= getParentIterator(gIOPowerPlane
);
1207 while ( (next
= iter
->getNextObject()) )
1209 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1211 pm_vars
->parentsKnowState
&= connection
->parentKnowsState();
1212 pm_vars
->parentsCurrentPowerFlags
|= connection
->parentCurrentPowerFlags();
1217 IOLockUnlock(pm_vars
->parentLock
);
1220 //*********************************************************************************
1221 // rebuildChildClampBits
1223 // The ChildClamp bits (kIOPMChildClamp & kIOPMChildClamp2) in our capabilityFlags
1224 // indicate that one of our children (or grandchildren or great-grandchildren or ...)
1225 // doesn't support idle or system sleep in its current state. Since we don't track the
1226 // origin of each bit, every time any child changes state we have to clear these bits
1227 // and rebuild them.
1228 //*********************************************************************************
1230 void IOService::rebuildChildClampBits(void)
1235 IOPowerConnection
*connection
;
1238 // A child's desires has changed. We need to rebuild the child-clamp bits in our
1239 // power state array. Start by clearing the bits in each power state.
1241 for ( i
= 0; i
< pm_vars
->theNumberOfPowerStates
; i
++ )
1243 pm_vars
->thePowerStates
[i
].capabilityFlags
&= ~(kIOPMChildClamp
| kIOPMChildClamp2
);
1246 // Now loop through the children. When we encounter the calling child, save
1247 // the computed state as this child's desire. And while we're at it, set the ChildClamp bits
1248 // in any of our states that some child has requested with clamp on.
1250 iter
= getChildIterator(gIOPowerPlane
);
1254 while ( (next
= iter
->getNextObject()) )
1256 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1258 if ( connection
->getPreventIdleSleepFlag() )
1259 pm_vars
->thePowerStates
[connection
->getDesiredDomainState()].capabilityFlags
|= kIOPMChildClamp
;
1260 if ( connection
->getPreventSystemSleepFlag() )
1261 pm_vars
->thePowerStates
[connection
->getDesiredDomainState()].capabilityFlags
|= kIOPMChildClamp2
;
1270 //*********************************************************************************
1271 // requestPowerDomainState
1273 // The kIOPMPreventIdleSleep and/or kIOPMPreventIdleSleep bits may be be set in the parameter.
1274 // It is not considered part of the state specification.
1275 //*********************************************************************************
1276 IOReturn
IOService::requestPowerDomainState ( IOPMPowerFlags desiredState
, IOPowerConnection
* whichChild
, unsigned long specification
)
1279 unsigned long computedState
;
1280 unsigned long theDesiredState
= desiredState
& ~(kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
1283 IOPowerConnection
*connection
;
1285 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRequestDomain
,
1286 (unsigned long)desiredState
,(unsigned long)specification
);
1288 if ( pm_vars
->theControllingDriver
== NULL
)
1290 return IOPMNotYetInitialized
;
1293 switch (specification
) {
1294 case IOPMLowestState
:
1296 while ( i
< pm_vars
->theNumberOfPowerStates
)
1298 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1304 if ( i
>= pm_vars
->theNumberOfPowerStates
)
1306 return IOPMNoSuchState
;
1310 case IOPMNextLowerState
:
1311 i
= pm_vars
->myCurrentState
- 1;
1312 while ( (int) i
>= 0 )
1314 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1322 return IOPMNoSuchState
;
1326 case IOPMHighestState
:
1327 i
= pm_vars
->theNumberOfPowerStates
;
1328 while ( (int) i
>= 0 )
1331 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1338 return IOPMNoSuchState
;
1342 case IOPMNextHigherState
:
1343 i
= pm_vars
->myCurrentState
+ 1;
1344 while ( i
< pm_vars
->theNumberOfPowerStates
)
1346 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1352 if ( i
== pm_vars
->theNumberOfPowerStates
)
1354 return IOPMNoSuchState
;
1359 return IOPMBadSpecification
;
1364 IOLockLock(pm_vars
->childLock
);
1366 // Now loop through the children. When we encounter the calling child, save
1367 // the computed state as this child's desire.
1368 iter
= getChildIterator(gIOPowerPlane
);
1372 while ( (next
= iter
->getNextObject()) )
1374 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1376 if ( connection
== whichChild
)
1378 connection
->setDesiredDomainState(computedState
);
1379 connection
->setPreventIdleSleepFlag(desiredState
& kIOPMPreventIdleSleep
);
1380 connection
->setPreventSystemSleepFlag(desiredState
& kIOPMPreventSystemSleep
);
1381 connection
->setChildHasRequestedPower();
1388 // Since a child's power requirements may have changed, clear and rebuild
1389 // kIOPMChildClamp and kIOPMChildClamp2 (idle and system sleep clamps)
1390 rebuildChildClampBits();
1392 IOLockUnlock(pm_vars
->childLock
);
1394 // this may be different now
1395 computeDesiredState();
1397 if ( inPlane(gIOPowerPlane
) &&
1398 (pm_vars
->parentsKnowState
) ) {
1399 // change state if all children can now tolerate lower power
1403 // are we clamped on, waiting for this child?
1404 if ( priv
->clampOn
) {
1405 // yes, remove the clamp
1406 priv
->clampOn
= false;
1407 changePowerStateToPriv(0);
1414 //*********************************************************************************
1415 // temporaryPowerClampOn
1417 // A power domain wants to clamp its power on till it has children which
1418 // will thendetermine the power domain state.
1420 // We enter the highest state until addPowerChild is called.
1421 //*********************************************************************************
1423 IOReturn
IOService::temporaryPowerClampOn ( void )
1425 priv
->clampOn
= true;
1431 //*********************************************************************************
1434 // Some client of our device is asking that we become usable. Although
1435 // this has not come from a subclassed device object, treat it exactly
1436 // as if it had. In this way, subsequent requests for lower power from
1437 // a subclassed device object will pre-empt this request.
1439 // We treat this as a subclass object request to switch to the
1440 // highest power state.
1441 //*********************************************************************************
1443 IOReturn
IOService::makeUsable ( void )
1445 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogMakeUsable
,0,0);
1447 if ( pm_vars
->theControllingDriver
== NULL
)
1449 priv
->need_to_become_usable
= true;
1452 priv
->deviceDesire
= pm_vars
->theNumberOfPowerStates
- 1;
1453 computeDesiredState();
1454 if ( inPlane(gIOPowerPlane
) && (pm_vars
->parentsKnowState
) )
1456 return changeState();
1462 //*********************************************************************************
1463 // currentCapability
1465 //*********************************************************************************
1467 IOPMPowerFlags
IOService::currentCapability ( void )
1469 if ( pm_vars
->theControllingDriver
== NULL
)
1473 return pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
;
1478 //*********************************************************************************
1479 // changePowerStateTo
1481 // For some reason, our power-controlling driver has decided it needs to change
1482 // power state. We enqueue the power change so that appropriate parties
1483 // will be notified, and then we will instruct the driver to make the change.
1484 //*********************************************************************************
1486 IOReturn
IOService::changePowerStateTo ( unsigned long ordinal
)
1488 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeStateTo
,ordinal
,0);
1490 if ( ordinal
>= pm_vars
->theNumberOfPowerStates
)
1492 return IOPMParameterError
;
1494 priv
->driverDesire
= ordinal
;
1495 computeDesiredState();
1496 if ( inPlane(gIOPowerPlane
) && (pm_vars
->parentsKnowState
) )
1498 return changeState();
1504 //*********************************************************************************
1505 // changePowerStateToPriv
1507 // For some reason, a subclassed device object has decided it needs to change
1508 // power state. We enqueue the power change so that appropriate parties
1509 // will be notified, and then we will instruct the driver to make the change.
1510 //*********************************************************************************
1512 IOReturn
IOService::changePowerStateToPriv ( unsigned long ordinal
)
1514 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeStateToPriv
,ordinal
,0);
1516 if ( pm_vars
->theControllingDriver
== NULL
)
1518 return IOPMNotYetInitialized
;
1520 if ( ordinal
>= pm_vars
->theNumberOfPowerStates
)
1522 return IOPMParameterError
;
1524 priv
->deviceDesire
= ordinal
;
1525 computeDesiredState();
1526 if ( inPlane(gIOPowerPlane
) && (pm_vars
->parentsKnowState
) )
1528 return changeState();
1535 //*********************************************************************************
1536 // computeDesiredState
1538 //*********************************************************************************
1540 void IOService::computeDesiredState ( void )
1544 IOPowerConnection
*connection
;
1545 unsigned long newDesiredState
= 0;
1547 // Compute the maximum of our children's desires, our controlling driver's desire, and the subclass device's desire.
1548 if ( ! priv
->device_overrides
)
1550 iter
= getChildIterator(gIOPowerPlane
);
1554 while ( (next
= iter
->getNextObject()) )
1556 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1558 if ( connection
->getDesiredDomainState() > newDesiredState
)
1560 newDesiredState
= connection
->getDesiredDomainState();
1567 if ( priv
->driverDesire
> newDesiredState
)
1569 newDesiredState
= priv
->driverDesire
;
1573 if ( priv
->deviceDesire
> newDesiredState
)
1575 newDesiredState
= priv
->deviceDesire
;
1578 priv
->ourDesiredPowerState
= newDesiredState
;
1582 //*********************************************************************************
1585 // A subclass object, our controlling driver, or a power domain child
1586 // has asked for a different power state. Here we compute what new
1587 // state we should enter and enqueue the change (or start it).
1588 //*********************************************************************************
1590 IOReturn
IOService::changeState ( void )
1592 // if not fully initialized
1593 if ( (pm_vars
->theControllingDriver
== NULL
) ||
1594 !(inPlane(gIOPowerPlane
)) ||
1595 !(pm_vars
->parentsKnowState
) )
1597 // we can do no more
1601 return enqueuePowerChange(IOPMWeInitiated
,priv
->ourDesiredPowerState
,0,0,0);
1605 //*********************************************************************************
1606 // currentPowerConsumption
1608 //*********************************************************************************
1610 unsigned long IOService::currentPowerConsumption ( void )
1612 if ( pm_vars
->theControllingDriver
== NULL
)
1614 return kIOPMUnknown
;
1616 if ( pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
& kIOPMStaticPowerValid
)
1618 return pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].staticPower
;
1620 return kIOPMUnknown
;
1623 //*********************************************************************************
1626 // The activity tickle with parameter kIOPMSubclassPolicyis not handled
1627 // here and should have been intercepted by the subclass.
1628 // The tickle with parameter kIOPMSuperclassPolicy1 causes the activity
1629 // flag to be set, and the device state checked. If the device has been
1630 // powered down, it is powered up again.
1631 //*********************************************************************************
1633 bool IOService::activityTickle ( unsigned long type
, unsigned long stateNumber
)
1635 IOPMrootDomain
*pmRootDomain
;
1636 AbsoluteTime uptime
;
1638 if ( type
== kIOPMSuperclassPolicy1
)
1640 if ( pm_vars
->theControllingDriver
== NULL
)
1645 if( priv
->activityLock
== NULL
)
1647 priv
->activityLock
= IOLockAlloc();
1650 IOTakeLock(priv
->activityLock
);
1651 priv
->device_active
= true;
1653 clock_get_uptime(&uptime
);
1654 priv
->device_active_timestamp
= uptime
;
1656 if ( pm_vars
->myCurrentState
>= stateNumber
)
1658 IOUnlock(priv
->activityLock
);
1661 IOUnlock(priv
->activityLock
);
1663 // Transfer execution to the PM workloop
1664 if( (pmRootDomain
= getPMRootDomain()) )
1665 pmRootDomain
->unIdleDevice(this, stateNumber
);
1672 //*********************************************************************************
1675 // A child is calling to get a pointer to the Power Management workloop.
1676 // We got it or get it from one of our parents.
1677 //*********************************************************************************
1679 IOWorkLoop
* IOService::getPMworkloop ( void )
1684 if ( ! inPlane(gIOPowerPlane
) )
1688 // we have no workloop yet
1689 if ( pm_vars
->PMworkloop
== NULL
)
1691 nub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
1694 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
1696 // ask one of our parents for the workloop
1699 pm_vars
->PMworkloop
= parent
->getPMworkloop();
1704 return pm_vars
->PMworkloop
;
1708 //*********************************************************************************
1709 // setIdleTimerPeriod
1711 // A subclass policy-maker is going to use our standard idleness
1712 // detection service. Make a command queue and an idle timer and
1713 // connect them to the power management workloop. Finally,
1715 //*********************************************************************************
1717 IOReturn
IOService::setIdleTimerPeriod ( unsigned long period
)
1719 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMsetIdleTimerPeriod
,period
, 0);
1721 priv
->idle_timer_period
= period
;
1725 if ( getPMworkloop() == NULL
)
1727 return kIOReturnError
;
1730 // make the timer event
1731 if ( priv
->timerEventSrc
== NULL
)
1733 priv
->timerEventSrc
= IOTimerEventSource::timerEventSource(this,
1734 PM_idle_timer_expired
);
1735 if ((!priv
->timerEventSrc
) ||
1736 (pm_vars
->PMworkloop
->addEventSource(priv
->timerEventSrc
) != kIOReturnSuccess
) )
1738 return kIOReturnError
;
1742 if ( priv
->activityLock
== NULL
)
1744 priv
->activityLock
= IOLockAlloc();
1747 start_PM_idle_timer();
1752 //******************************************************************************
1755 // Returns how many "seconds from now" the device should idle into its
1756 // next lowest power state.
1757 //******************************************************************************
1758 SInt32
IOService::nextIdleTimeout(
1759 AbsoluteTime currentTime
,
1760 AbsoluteTime lastActivity
,
1761 unsigned int powerState
)
1768 // Calculate time difference using funky macro from clock.h.
1769 delta
= currentTime
;
1770 SUB_ABSOLUTETIME(&delta
, &lastActivity
);
1772 // Figure it in seconds.
1773 absolutetime_to_nanoseconds(delta
, &delta_ns
);
1774 delta_secs
= (SInt32
)(delta_ns
/ NSEC_PER_SEC
);
1776 // Be paranoid about delta somehow exceeding timer period.
1777 if (delta_secs
< (int) priv
->idle_timer_period
)
1778 delay_secs
= (int) priv
->idle_timer_period
- delta_secs
;
1780 delay_secs
= (int) priv
->idle_timer_period
;
1782 return (SInt32
)delay_secs
;
1785 //******************************************************************************
1786 // start_PM_idle_timer
1788 // The parameter is a pointer to us. Use it to call our timeout method.
1789 //******************************************************************************
1790 void IOService::start_PM_idle_timer ( void )
1792 static const int maxTimeout
= 100000;
1793 static const int minTimeout
= 1;
1794 AbsoluteTime uptime
;
1797 IOLockLock(priv
->activityLock
);
1799 clock_get_uptime(&uptime
);
1801 // Subclasses may modify idle sleep algorithm
1802 idle_in
= nextIdleTimeout(uptime
,
1803 priv
->device_active_timestamp
,
1804 pm_vars
->myCurrentState
);
1806 // Check for out-of range responses
1807 if(idle_in
> maxTimeout
)
1809 // use standard implementation
1810 idle_in
= IOService::nextIdleTimeout(uptime
,
1811 priv
->device_active_timestamp
,
1812 pm_vars
->myCurrentState
);
1813 } else if(idle_in
< minTimeout
) {
1818 priv
->timerEventSrc
->setTimeout(idle_in
, NSEC_PER_SEC
);
1820 IOLockUnlock(priv
->activityLock
);
1825 //*********************************************************************************
1826 // PM_idle_timer_expired
1828 // The parameter is a pointer to us. Use it to call our timeout method.
1829 //*********************************************************************************
1831 void PM_idle_timer_expired(OSObject
* ourSelves
, IOTimerEventSource
*)
1833 ((IOService
*)ourSelves
)->PM_idle_timer_expiration();
1837 //*********************************************************************************
1838 // PM_idle_timer_expiration
1840 // The idle timer has expired. If there has been activity since the last
1841 // expiration, just restart the timer and return. If there has not been
1842 // activity, switch to the next lower power state and restart the timer.
1843 //*********************************************************************************
1845 void IOService::PM_idle_timer_expiration ( void )
1847 if ( ! initialized
)
1853 if ( priv
->idle_timer_period
> 0 )
1855 IOTakeLock(priv
->activityLock
);
1856 if ( priv
->device_active
)
1858 priv
->device_active
= false;
1859 IOUnlock(priv
->activityLock
);
1860 start_PM_idle_timer();
1863 if ( pm_vars
->myCurrentState
> 0 )
1865 IOUnlock(priv
->activityLock
);
1866 changePowerStateToPriv(pm_vars
->myCurrentState
- 1);
1867 start_PM_idle_timer();
1870 IOUnlock(priv
->activityLock
);
1871 start_PM_idle_timer();
1876 // **********************************************************************************
1879 // We are un-idling a device due to its activity tickle. This routine runs on the
1880 // PM workloop, and is initiated by IOService::activityTickle.
1881 // We process all activityTickle state requests on the list.
1882 // **********************************************************************************
1883 void IOService::command_received ( void *statePtr
, void *, void * , void * )
1885 unsigned long stateNumber
;
1887 stateNumber
= (unsigned long)statePtr
;
1889 // If not initialized, we're unloading
1890 if ( ! initialized
) return;
1892 if ( (pm_vars
->myCurrentState
< stateNumber
) &&
1893 (priv
->imminentState
< stateNumber
) )
1895 changePowerStateToPriv(stateNumber
);
1897 // After we raise our state, re-schedule the idle timer.
1898 if(priv
->timerEventSrc
)
1899 start_PM_idle_timer();
1904 //*********************************************************************************
1905 // setAggressiveness
1907 // Pass on the input parameters to all power domain children. All those which are
1908 // power domains will pass it on to their children, etc.
1909 //*********************************************************************************
1911 IOReturn
IOService::setAggressiveness ( unsigned long type
, unsigned long newLevel
)
1915 IOPowerConnection
*connection
;
1918 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogSetAggressiveness
,type
, newLevel
);
1920 if ( type
<= kMaxType
)
1922 pm_vars
->current_aggressiveness_values
[type
] = newLevel
;
1923 pm_vars
->current_aggressiveness_valid
[type
] = true;
1926 iter
= getChildIterator(gIOPowerPlane
);
1930 while ( (next
= iter
->getNextObject()) )
1932 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1934 child
= ((IOService
*)(connection
->copyChildEntry(gIOPowerPlane
)));
1937 child
->setAggressiveness(type
, newLevel
);
1948 //*********************************************************************************
1949 // getAggressiveness
1951 // Called by the user client.
1952 //*********************************************************************************
1954 IOReturn
IOService::getAggressiveness ( unsigned long type
, unsigned long * currentLevel
)
1956 if ( type
> kMaxType
)
1957 return kIOReturnBadArgument
;
1959 if ( !pm_vars
->current_aggressiveness_valid
[type
] )
1960 return kIOReturnInvalid
;
1962 *currentLevel
= pm_vars
->current_aggressiveness_values
[type
];
1964 return kIOReturnSuccess
;
1967 //*********************************************************************************
1970 // Pass this to all power domain children. All those which are
1971 // power domains will pass it on to their children, etc.
1972 //*********************************************************************************
1974 IOReturn
IOService::systemWake ( void )
1978 IOPowerConnection
*connection
;
1979 IOService
*theChild
;
1981 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogSystemWake
,0, 0);
1983 iter
= getChildIterator(gIOPowerPlane
);
1987 while ( (next
= iter
->getNextObject()) )
1989 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1991 theChild
= (IOService
*)connection
->copyChildEntry(gIOPowerPlane
);
1994 theChild
->systemWake();
1995 theChild
->release();
2002 if ( pm_vars
->theControllingDriver
!= NULL
)
2004 if ( pm_vars
->theControllingDriver
->didYouWakeSystem() )
2014 //*********************************************************************************
2015 // temperatureCriticalForZone
2017 //*********************************************************************************
2019 IOReturn
IOService::temperatureCriticalForZone ( IOService
* whichZone
)
2021 IOService
*theParent
;
2024 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogCriticalTemp
,0,0);
2026 if ( inPlane(gIOPowerPlane
) && !(priv
->we_are_root
) )
2028 theNub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
2031 theParent
= (IOService
*)theNub
->copyParentEntry(gIOPowerPlane
);
2035 theParent
->temperatureCriticalForZone(whichZone
);
2036 theParent
->release();
2044 //*********************************************************************************
2045 // powerOverrideOnPriv
2047 //*********************************************************************************
2050 IOReturn
IOService::powerOverrideOnPriv ( void )
2052 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogOverrideOn
,0,0);
2054 // turn on the override
2055 priv
->device_overrides
= true;
2056 computeDesiredState();
2058 // change state if that changed something
2059 return changeState();
2063 //*********************************************************************************
2064 // powerOverrideOffPriv
2066 //*********************************************************************************
2067 IOReturn
IOService::powerOverrideOffPriv ( void )
2069 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogOverrideOff
,0,0);
2071 // turn off the override
2072 priv
->device_overrides
= false;
2073 computeDesiredState();
2076 return makeUsable();
2078 // change state if that changed something
2079 return changeState();
2084 //*********************************************************************************
2085 // enqueuePowerChange
2087 // Allocate a new state change notification, initialize it with fields from the
2088 // caller, and add it to the tail of the list of pending power changes.
2090 // If it is early enough in the list, and almost all the time it is the only one in
2091 // the list, start the power change.
2093 // In rare instances, this change will preempt the previous change in the list.
2094 // If the previous change is un-actioned in any way (because we are still
2095 // processing an even earlier power change), and if both the previous change
2096 // in the list and this change are initiated by us (not the parent), then we
2097 // needn't perform the previous change, so we collapse the list a little.
2098 //*********************************************************************************
2100 IOReturn
IOService::enqueuePowerChange ( unsigned long flags
, unsigned long whatStateOrdinal
, unsigned long domainState
, IOPowerConnection
* whichParent
, unsigned long singleParentState
)
2105 // Create and initialize the new change note
2107 IOLockLock(priv
->queue_lock
);
2108 newNote
= priv
->changeList
->createChangeNote();
2109 if ( newNote
== -1 ) {
2110 // uh-oh, our list is full
2111 IOLockUnlock(priv
->queue_lock
);
2112 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogEnqueueErr
,0,0);
2113 return IOPMAckImplied
;
2116 priv
->changeList
->changeNote
[newNote
].newStateNumber
= whatStateOrdinal
;
2117 priv
->changeList
->changeNote
[newNote
].outputPowerCharacter
= pm_vars
->thePowerStates
[whatStateOrdinal
].outputPowerCharacter
;
2118 priv
->changeList
->changeNote
[newNote
].inputPowerRequirement
= pm_vars
->thePowerStates
[whatStateOrdinal
].inputPowerRequirement
;
2119 priv
->changeList
->changeNote
[newNote
].capabilityFlags
= pm_vars
->thePowerStates
[whatStateOrdinal
].capabilityFlags
;
2120 priv
->changeList
->changeNote
[newNote
].flags
= flags
;
2121 priv
->changeList
->changeNote
[newNote
].parent
= NULL
;
2122 if (flags
& IOPMParentInitiated
)
2124 priv
->changeList
->changeNote
[newNote
].domainState
= domainState
;
2125 priv
->changeList
->changeNote
[newNote
].parent
= whichParent
;
2126 whichParent
->retain();
2127 priv
->changeList
->changeNote
[newNote
].singleParentState
= singleParentState
;
2130 previousNote
= priv
->changeList
->previousChangeNote(newNote
);
2132 if ( previousNote
== -1 )
2135 // Queue is empty, we can start this change.
2137 if (flags
& IOPMWeInitiated
)
2139 IOLockUnlock(priv
->queue_lock
);
2140 start_our_change(newNote
);
2143 IOLockUnlock(priv
->queue_lock
);
2144 return start_parent_change(newNote
);
2148 // The queue is not empty. Try to collapse this new change and the previous one in queue into one change.
2149 // This is possible only if both changes are initiated by us, and neither has been started yet.
2150 // Do this more than once if possible.
2152 // (A change is started iff it is at the head of the queue)
2154 while ( (previousNote
!= priv
->head_note
) && (previousNote
!= -1) &&
2155 (priv
->changeList
->changeNote
[newNote
].flags
& priv
->changeList
->changeNote
[previousNote
].flags
& IOPMWeInitiated
) )
2157 priv
->changeList
->changeNote
[previousNote
].outputPowerCharacter
= priv
->changeList
->changeNote
[newNote
].outputPowerCharacter
;
2158 priv
->changeList
->changeNote
[previousNote
].inputPowerRequirement
= priv
->changeList
->changeNote
[newNote
].inputPowerRequirement
;
2159 priv
->changeList
->changeNote
[previousNote
].capabilityFlags
=priv
-> changeList
->changeNote
[newNote
].capabilityFlags
;
2160 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogCollapseQueue
,priv
->changeList
->changeNote
[newNote
].newStateNumber
,
2161 priv
->changeList
->changeNote
[previousNote
].newStateNumber
);
2162 priv
->changeList
->changeNote
[previousNote
].newStateNumber
= priv
->changeList
->changeNote
[newNote
].newStateNumber
;
2163 priv
->changeList
->releaseTailChangeNote();
2164 newNote
= previousNote
;
2165 previousNote
= priv
->changeList
->previousChangeNote(newNote
);
2167 IOLockUnlock(priv
->queue_lock
);
2168 // in any case, we can't start yet
2169 return IOPMWillAckLater
;
2172 //*********************************************************************************
2175 // Notify all interested parties either that a change is impending or that the
2176 // previously-notified change is done and power has settled.
2177 // The parameter identifies whether this is the
2178 // pre-change notification or the post-change notification.
2180 //*********************************************************************************
2182 IOReturn
IOService::notifyAll ( bool is_prechange
)
2184 IOPMinformee
* nextObject
;
2187 IOPowerConnection
* connection
;
2189 // To prevent acknowledgePowerChange from finishing the change note and removing it from the queue if
2190 // some driver calls it, we inflate the number of pending acks so it cannot become zero. We'll fix it later.
2192 priv
->head_note_pendingAcks
=1;
2194 // OK, we will go through the lists of interested drivers and power domain children
2195 // and notify each one of this change.
2197 nextObject
= priv
->interestedDrivers
->firstInList();
2198 while ( nextObject
!= NULL
) {
2199 priv
->head_note_pendingAcks
+=1;
2200 if (! inform(nextObject
, is_prechange
) )
2203 nextObject
= priv
->interestedDrivers
->nextInList(nextObject
);
2206 if (! acquire_lock() ) {
2209 // did they all ack?
2210 if ( priv
->head_note_pendingAcks
> 1 ) {
2212 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2216 IOUnlock(priv
->our_lock
);
2219 iter
= getChildIterator(gIOPowerPlane
);
2220 // summing their power consumption
2221 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
= 0;
2225 while ( (next
= iter
->getNextObject()) )
2227 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
2229 priv
->head_note_pendingAcks
+=1;
2230 notifyChild(connection
, is_prechange
);
2236 if (! acquire_lock() ) {
2239 // now make this real
2240 priv
->head_note_pendingAcks
-= 1;
2242 if (priv
->head_note_pendingAcks
== 0 ) {
2244 IOUnlock(priv
->our_lock
);
2245 // return ack to parent
2246 return IOPMAckImplied
;
2250 IOUnlock(priv
->our_lock
);
2251 return IOPMWillAckLater
;
2255 //*********************************************************************************
2258 // Notify a power domain child of an upcoming power change.
2260 // If the object acknowledges the current change, we return TRUE.
2261 //*********************************************************************************
2263 bool IOService::notifyChild ( IOPowerConnection
* theNub
, bool is_prechange
)
2265 IOReturn k
= IOPMAckImplied
;
2266 unsigned long childPower
;
2267 IOService
*theChild
;
2269 theChild
= (IOService
*)(theNub
->copyChildEntry(gIOPowerPlane
));
2272 // The child has been detached since we grabbed the child iterator.
2273 // Decrement pending_acks, already incremented in notifyAll,
2274 // to account for this unexpected departure.
2275 priv
->head_note_pendingAcks
--;
2279 // Unless the child handles the notification immediately and returns
2280 // kIOPMAckImplied, we'll be awaiting their acknowledgement later.
2281 theNub
->setAwaitingAck(true);
2285 k
= theChild
->powerDomainWillChangeTo(priv
->head_note_outputFlags
,theNub
);
2287 k
= theChild
->powerDomainDidChangeTo(priv
->head_note_outputFlags
,theNub
);
2290 // did the return code ack?
2291 if ( k
== IOPMAckImplied
)
2294 priv
->head_note_pendingAcks
--;
2295 theNub
->setAwaitingAck(false);
2296 childPower
= theChild
->currentPowerConsumption();
2297 if ( childPower
== kIOPMUnknown
)
2299 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
= kIOPMUnknown
;
2301 if ( pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
!= kIOPMUnknown
)
2303 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
+= childPower
;
2306 theChild
->release();
2309 theChild
->release();
2314 //*********************************************************************************
2317 // Notify an interested driver of an upcoming power change.
2319 // If the object acknowledges the current change, we return TRUE.
2320 //*********************************************************************************
2322 bool IOService::inform ( IOPMinformee
* nextObject
, bool is_prechange
)
2324 IOReturn k
= IOPMAckImplied
;
2327 nextObject
->timer
= -1;
2331 pm_vars
->thePlatform
->PMLog (pm_vars
->ourName
,PMlogInformDriverPreChange
,
2332 (unsigned long)priv
->head_note_capabilityFlags
,(unsigned long)priv
->head_note_state
);
2333 k
= nextObject
->whatObject
->powerStateWillChangeTo( priv
->head_note_capabilityFlags
,priv
->head_note_state
,this);
2335 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInformDriverPostChange
,
2336 (unsigned long)priv
->head_note_capabilityFlags
,(unsigned long)priv
->head_note_state
);
2337 k
= nextObject
->whatObject
->powerStateDidChangeTo(priv
->head_note_capabilityFlags
,priv
->head_note_state
,this);
2340 // did it ack behind our back?
2341 if ( nextObject
->timer
== 0 )
2347 // no, did the return code ack?
2348 if ( k
==IOPMAckImplied
)
2351 nextObject
->timer
= 0;
2352 priv
->head_note_pendingAcks
-= 1;
2358 nextObject
->timer
= 0;
2359 priv
-> head_note_pendingAcks
-= 1;
2364 nextObject
->timer
= (k
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
2370 //*********************************************************************************
2371 // OurChangeTellClientsPowerDown
2373 // All registered applications and kernel clients have positively acknowledged our
2374 // intention of lowering power. Here we notify them all that we will definitely
2375 // lower the power. If we don't have to wait for any of them to acknowledge, we
2376 // carry on by notifying interested drivers. Otherwise, we do wait.
2377 //*********************************************************************************
2379 void IOService::OurChangeTellClientsPowerDown ( void )
2382 priv
->machine_state
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
2384 // are we waiting for responses?
2385 if ( tellChangeDown1(priv
->head_note_state
) )
2387 // no, notify priority clients
2388 OurChangeTellPriorityClientsPowerDown();
2390 // If we are waiting for responses, execution will resume via
2391 // allowCancelCommon() or ack timeout
2395 //*********************************************************************************
2396 // OurChangeTellPriorityClientsPowerDown
2398 // All registered applications and kernel clients have positively acknowledged our
2399 // intention of lowering power. Here we notify "priority" clients that we are
2400 // lowering power. If we don't have to wait for any of them to acknowledge, we
2401 // carry on by notifying interested drivers. Otherwise, we do wait.
2402 //*********************************************************************************
2404 void IOService::OurChangeTellPriorityClientsPowerDown ( void )
2407 priv
->machine_state
= kIOPM_OurChangeNotifyInterestedDriversWillChange
;
2408 // are we waiting for responses?
2409 if ( tellChangeDown2(priv
->head_note_state
) )
2411 // no, notify interested drivers
2412 return OurChangeNotifyInterestedDriversWillChange();
2414 // If we are waiting for responses, execution will resume via
2415 // allowCancelCommon() or ack timeout
2419 //*********************************************************************************
2420 // OurChangeNotifyInterestedDriversWillChange
2422 // All registered applications and kernel clients have acknowledged our notification
2423 // that we are lowering power. Here we notify interested drivers. If we don't have
2424 // to wait for any of them to acknowledge, we instruct our power driver to make the change.
2425 // Otherwise, we do wait.
2426 //*********************************************************************************
2428 void IOService::OurChangeNotifyInterestedDriversWillChange ( void )
2430 // no, in case they don't all ack
2431 priv
->machine_state
= kIOPM_OurChangeSetPowerState
;
2432 if ( notifyAll(true) == IOPMAckImplied
)
2434 // not waiting for responses
2435 OurChangeSetPowerState();
2437 // If we are waiting for responses, execution will resume via
2438 // all_acked() or ack timeout
2442 //*********************************************************************************
2443 // OurChangeSetPowerState
2445 // All interested drivers have acknowledged our pre-change notification of a power
2446 // change we initiated. Here we instruct our controlling driver to make
2447 // the change to the hardware. If it does so, we continue processing
2448 // (waiting for settle and notifying interested parties post-change.)
2449 // If it doesn't, we have to wait for it to acknowledge and then continue.
2450 //*********************************************************************************
2452 void IOService::OurChangeSetPowerState ( void )
2454 priv
->machine_state
= kIOPM_OurChangeWaitForPowerSettle
;
2456 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2458 // it's done, carry on
2459 OurChangeWaitForPowerSettle();
2461 // it's not, wait for it
2462 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2464 // execution will resume via ack_timer_ticked()
2469 //*********************************************************************************
2470 // OurChangeWaitForPowerSettle
2472 // Our controlling driver has changed power state on the hardware
2473 // during a power change we initiated. Here we see if we need to wait
2474 // for power to settle before continuing. If not, we continue processing
2475 // (notifying interested parties post-change). If so, we wait and
2477 //*********************************************************************************
2479 void IOService::OurChangeWaitForPowerSettle ( void )
2481 priv
->settle_time
= compute_settle_time();
2482 if ( priv
->settle_time
== 0 )
2484 OurChangeNotifyInterestedDriversDidChange();
2486 priv
->machine_state
= kIOPM_OurChangeNotifyInterestedDriversDidChange
;
2487 startSettleTimer(priv
->settle_time
);
2492 //*********************************************************************************
2493 // OurChangeNotifyInterestedDriversDidChange
2495 // Power has settled on a power change we initiated. Here we notify
2496 // all our interested parties post-change. If they all acknowledge, we're
2497 // done with this change note, and we can start on the next one.
2498 // Otherwise we have to wait for acknowledgements and finish up later.
2499 //*********************************************************************************
2501 void IOService::OurChangeNotifyInterestedDriversDidChange ( void )
2503 // in case they don't all ack
2504 priv
->machine_state
= kIOPM_OurChangeFinish
;
2505 if ( notifyAll(false) == IOPMAckImplied
)
2507 // not waiting for responses
2510 // If we are waiting for responses, execution will resume via
2511 // all_acked() or ack timeout
2515 //*********************************************************************************
2518 // Power has settled on a power change we initiated, and
2519 // all our interested parties have acknowledged. We're
2520 // done with this change note, and we can start on the next one.
2521 //*********************************************************************************
2523 void IOService::OurChangeFinish ( void )
2529 //*********************************************************************************
2530 // ParentDownTellPriorityClientsPowerDown_Immediate
2532 // All applications and kernel clients have been notified of a power lowering
2533 // initiated by the parent and we didn't have to wait for any responses. Here
2534 // we notify any priority clients. If they all ack, we continue with the power change.
2535 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2536 //*********************************************************************************
2538 IOReturn
IOService::ParentDownTellPriorityClientsPowerDown_Immediate ( void )
2540 // in case they don't all ack
2541 priv
->machine_state
= kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
;
2542 // are we waiting for responses?
2543 if ( tellChangeDown2(priv
->head_note_state
) )
2545 // no, notify interested drivers
2546 return ParentDownNotifyInterestedDriversWillChange_Immediate();
2548 // If we are waiting for responses, execution will resume via
2549 // allowCancelCommon() or ack timeout
2550 return IOPMWillAckLater
;
2554 //*********************************************************************************
2555 // ParentDownTellPriorityClientsPowerDown_Immediate2
2557 // All priority kernel clients have been notified of a power lowering
2558 // initiated by the parent and we didn't have to wait for any responses. Here
2559 // we notify any interested drivers and power domain children. If they all ack,
2560 // we continue with the power change.
2561 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2562 //*********************************************************************************
2564 IOReturn
IOService::ParentDownNotifyInterestedDriversWillChange_Immediate ( void )
2566 // in case they don't all ack
2567 priv
->machine_state
= kIOPM_ParentDownSetPowerState_Delayed
;
2568 if ( notifyAll(true) == IOPMAckImplied
)
2571 return ParentDownSetPowerState_Immediate();
2573 // If we are waiting for responses, execution will resume via
2574 // all_acked() or ack timeout
2575 return IOPMWillAckLater
;
2579 //*********************************************************************************
2580 // ParentDownTellPriorityClientsPowerDown_Immediate4
2582 // All applications and kernel clients have been notified of a power lowering
2583 // initiated by the parent and we had to wait for responses. Here
2584 // we notify any priority clients. If they all ack, we continue with the power change.
2585 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2586 //*********************************************************************************
2588 void IOService::ParentDownTellPriorityClientsPowerDown_Delayed ( void )
2590 // in case they don't all ack
2591 priv
->machine_state
= kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
;
2593 // are we waiting for responses?
2594 if ( tellChangeDown2(priv
->head_note_state
) )
2596 // no, notify interested drivers
2597 ParentDownNotifyInterestedDriversWillChange_Delayed();
2599 // If we are waiting for responses, execution will resume via
2600 // allowCancelCommon() or ack timeout
2604 //*********************************************************************************
2605 // ParentDownTellPriorityClientsPowerDown_Immediate5
2607 // All applications and kernel clients have been notified of a power lowering
2608 // initiated by the parent and we had to wait for their responses. Here we notify
2609 // any interested drivers and power domain children. If they all ack, we continue
2610 // with the power change.
2611 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2612 //*********************************************************************************
2614 void IOService::ParentDownNotifyInterestedDriversWillChange_Delayed ( void )
2616 // in case they don't all ack
2617 priv
->machine_state
= kIOPM_ParentDownSetPowerState_Delayed
;
2618 if ( notifyAll(true) == IOPMAckImplied
)
2621 ParentDownSetPowerState_Delayed();
2623 // If we are waiting for responses, execution will resume via
2624 // all_acked() or ack timeout
2628 //*********************************************************************************
2629 // ParentDownSetPowerState_Immediate
2631 // All parties have acknowledged our pre-change notification of a power
2632 // lowering initiated by the parent. Here we instruct our controlling driver
2633 // to put the hardware in the state it needs to be in when the domain is
2634 // lowered. If it does so, we continue processing
2635 // (waiting for settle and acknowledging the parent.)
2636 // If it doesn't, we have to wait for it to acknowledge and then continue.
2637 //*********************************************************************************
2639 IOReturn
IOService::ParentDownSetPowerState_Immediate ( void )
2641 priv
->machine_state
= kIOPM_ParentDownWaitForPowerSettle_Delayed
;
2643 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2645 // it's done, carry on
2646 return ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate();
2648 // it's not, wait for it
2649 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2651 return IOPMWillAckLater
;
2655 //*********************************************************************************
2656 // ParentDownSetPowerState_Delayed
2658 // We had to wait for it, but all parties have acknowledged our pre-change
2659 // notification of a power lowering initiated by the parent.
2660 // Here we instruct our controlling driver
2661 // to put the hardware in the state it needs to be in when the domain is
2662 // lowered. If it does so, we continue processing
2663 // (waiting for settle and acknowledging the parent.)
2664 // If it doesn't, we have to wait for it to acknowledge and then continue.
2665 //*********************************************************************************
2667 void IOService::ParentDownSetPowerState_Delayed ( void )
2669 priv
-> machine_state
= kIOPM_ParentDownWaitForPowerSettle_Delayed
;
2671 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2673 // it's done, carry on
2674 ParentDownWaitForPowerSettle_Delayed();
2676 // it's not, wait for it
2677 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2683 //*********************************************************************************
2684 // ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate
2686 // Our controlling driver has changed power state on the hardware
2687 // during a power change initiated by our parent. Here we see if we need
2688 // to wait for power to settle before continuing. If not, we continue
2689 // processing (acknowledging our preparedness to the parent).
2690 // If so, we wait and continue later.
2691 //*********************************************************************************
2693 IOReturn
IOService::ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate ( void )
2697 priv
->settle_time
= compute_settle_time();
2698 if ( priv
->settle_time
== 0 )
2700 // store current state in case they don't all ack
2701 priv
->machine_state
= kIOPM_ParentDownAcknowledgeChange_Delayed
;
2702 if ( notifyAll(false) == IOPMAckImplied
)
2704 // not waiting for responses
2705 nub
= priv
->head_note_parent
;
2709 return IOPMAckImplied
;
2711 // If we are waiting for responses, execution will resume via
2712 // all_acked() or ack timeout
2713 return IOPMWillAckLater
;
2715 // let settle time elapse, then notify interest drivers of our power state change in ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
2716 priv
->machine_state
= kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
;
2717 startSettleTimer(priv
->settle_time
);
2718 return IOPMWillAckLater
;
2723 //*********************************************************************************
2724 // ParentDownWaitForPowerSettle_Delayed
2726 // Our controlling driver has changed power state on the hardware
2727 // during a power change initiated by our parent. We have had to wait
2728 // for acknowledgement from interested parties, or we have had to wait
2729 // for the controlling driver to change the state. Here we see if we need
2730 // to wait for power to settle before continuing. If not, we continue
2731 // processing (acknowledging our preparedness to the parent).
2732 // If so, we wait and continue later.
2733 //*********************************************************************************
2735 void IOService::ParentDownWaitForPowerSettle_Delayed ( void )
2737 priv
->settle_time
= compute_settle_time();
2738 if ( priv
->settle_time
== 0 )
2740 ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed();
2742 priv
->machine_state
= kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
;
2743 startSettleTimer(priv
->settle_time
);
2748 //*********************************************************************************
2749 // ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
2751 // Power has settled on a power change initiated by our parent. Here we
2752 // notify interested parties.
2753 //*********************************************************************************
2755 void IOService::ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed ( void )
2757 IORegistryEntry
*nub
;
2760 // in case they don't all ack
2761 priv
->machine_state
= kIOPM_ParentDownAcknowledgeChange_Delayed
;
2762 if ( notifyAll(false) == IOPMAckImplied
) {
2763 nub
= priv
->head_note_parent
;
2766 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
2768 parent
->acknowledgePowerChange((IOService
*)nub
);
2773 // If we are waiting for responses, execution will resume via
2774 // all_acked() or ack timeout in ParentDownAcknowledgeChange_Delayed.
2775 // Notice the duplication of code just above and in ParentDownAcknowledgeChange_Delayed.
2779 //*********************************************************************************
2780 // ParentDownAcknowledgeChange_Delayed
2782 // We had to wait for it, but all parties have acknowledged our post-change
2783 // notification of a power lowering initiated by the parent.
2784 // Here we acknowledge the parent.
2785 // We are done with this change note, and we can start on the next one.
2786 //*********************************************************************************
2788 void IOService::ParentDownAcknowledgeChange_Delayed ( void )
2790 IORegistryEntry
*nub
;
2793 nub
= priv
->head_note_parent
;
2796 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
2799 parent
->acknowledgePowerChange((IOService
*)nub
);
2806 //*********************************************************************************
2807 // ParentUpSetPowerState_Delayed
2809 // Our parent has informed us via powerStateDidChange that it has
2810 // raised the power in our power domain, and we have had to wait
2811 // for some interested party to acknowledge our notification.
2812 // Here we instruct our controlling
2813 // driver to program the hardware to take advantage of the higher domain
2814 // power. If it does so, we continue processing
2815 // (waiting for settle and notifying interested parties post-change.)
2816 // If it doesn't, we have to wait for it to acknowledge and then continue.
2817 //*********************************************************************************
2819 void IOService::ParentUpSetPowerState_Delayed ( void )
2821 priv
->machine_state
= kIOPM_ParentUpWaitForSettleTime_Delayed
;
2823 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2825 // it did it, carry on
2826 ParentUpWaitForSettleTime_Delayed();
2828 // it didn't, wait for it
2829 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2835 //*********************************************************************************
2836 // ParentUpSetPowerState_Immediate
2838 // Our parent has informed us via powerStateDidChange that it has
2839 // raised the power in our power domain. Here we instruct our controlling
2840 // driver to program the hardware to take advantage of the higher domain
2841 // power. If it does so, we continue processing
2842 // (waiting for settle and notifying interested parties post-change.)
2843 // If it doesn't, we have to wait for it to acknowledge and then continue.
2844 //*********************************************************************************
2846 IOReturn
IOService::ParentUpSetPowerState_Immediate ( void )
2848 priv
->machine_state
= kIOPM_ParentUpWaitForSettleTime_Delayed
;
2850 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2852 // it did it, carry on
2853 return ParentUpWaitForSettleTime_Immediate();
2856 // it didn't, wait for it
2857 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2859 return IOPMWillAckLater
;
2864 //*********************************************************************************
2865 // ParentUpWaitForSettleTime_Immediate
2867 // Our controlling driver has changed power state on the hardware
2868 // during a power raise initiated by the parent. Here we see if we need to wait
2869 // for power to settle before continuing. If not, we continue processing
2870 // (notifying interested parties post-change). If so, we wait and
2872 //*********************************************************************************
2874 IOReturn
IOService::ParentUpWaitForSettleTime_Immediate ( void )
2876 priv
->settle_time
= compute_settle_time();
2877 if ( priv
->settle_time
== 0 )
2879 return ParentUpNotifyInterestedDriversDidChange_Immediate();
2881 priv
->machine_state
= kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed
;
2882 startSettleTimer(priv
->settle_time
);
2883 return IOPMWillAckLater
;
2888 //*********************************************************************************
2889 // ParentUpWaitForSettleTime_Delayed
2891 // Our controlling driver has changed power state on the hardware
2892 // during a power raise initiated by the parent, but we had to wait for it.
2893 // Here we see if we need to wait for power to settle before continuing.
2894 // If not, we continue processing (notifying interested parties post-change).
2895 // If so, we wait and continue later.
2896 //*********************************************************************************
2898 void IOService::ParentUpWaitForSettleTime_Delayed ( void )
2900 priv
->settle_time
= compute_settle_time();
2901 if ( priv
->settle_time
== 0 )
2903 ParentUpNotifyInterestedDriversDidChange_Delayed();
2905 priv
->machine_state
= kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed
;
2906 startSettleTimer(priv
->settle_time
);
2911 //*********************************************************************************
2912 // ParentUpNotifyInterestedDriversDidChange_Immediate
2914 // No power settling was required on a power raise initiated by the parent.
2915 // Here we notify all our interested parties post-change. If they all acknowledge,
2916 // we're done with this change note, and we can start on the next one.
2917 // Otherwise we have to wait for acknowledgements and finish up later.
2918 //*********************************************************************************
2920 IOReturn
IOService::ParentUpNotifyInterestedDriversDidChange_Immediate ( void )
2924 // in case they don't all ack
2925 priv
->machine_state
= kIOPM_ParentUpAcknowledgePowerChange_Delayed
;
2926 if ( notifyAll(false) == IOPMAckImplied
)
2928 nub
= priv
->head_note_parent
;
2932 return IOPMAckImplied
;
2934 // If we are waiting for responses, execution will resume via
2935 // all_acked() or ack timeout in ParentUpAcknowledgePowerChange_Delayed.
2936 return IOPMWillAckLater
;
2940 //*********************************************************************************
2941 // ParentUpNotifyInterestedDriversDidChange_Delayed
2943 // Power has settled on a power raise initiated by the parent.
2944 // Here we notify all our interested parties post-change. If they all acknowledge,
2945 // we're done with this change note, and we can start on the next one.
2946 // Otherwise we have to wait for acknowledgements and finish up later.
2947 //*********************************************************************************
2949 void IOService::ParentUpNotifyInterestedDriversDidChange_Delayed ( void )
2951 // in case they don't all ack
2952 priv
->machine_state
= kIOPM_ParentUpAcknowledgePowerChange_Delayed
;
2953 if ( notifyAll(false) == IOPMAckImplied
)
2955 ParentUpAcknowledgePowerChange_Delayed();
2957 // If we are waiting for responses, execution will resume via
2958 // all_acked() or ack timeout in ParentUpAcknowledgePowerChange_Delayed.
2962 //*********************************************************************************
2963 // ParentUpAcknowledgePowerChange_Delayed
2965 // All parties have acknowledged our post-change notification of a power
2966 // raising initiated by the parent. Here we acknowledge the parent.
2967 // We are done with this change note, and we can start on the next one.
2968 //*********************************************************************************
2970 void IOService::ParentUpAcknowledgePowerChange_Delayed ( void )
2972 IORegistryEntry
*nub
;
2975 nub
= priv
->head_note_parent
;
2978 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
2981 parent
->acknowledgePowerChange((IOService
*)nub
);
2988 //*********************************************************************************
2991 // A power change is complete, and the used post-change note is at
2992 // the head of the queue. Remove it and set myCurrentState to the result
2993 // of the change. Start up the next change in queue.
2994 //*********************************************************************************
2996 void IOService::all_done ( void )
2998 unsigned long previous_state
;
2999 IORegistryEntry
*nub
;
3002 priv
->machine_state
= kIOPM_Finished
;
3005 if ( priv
->head_note_flags
& IOPMWeInitiated
)
3007 // could our driver switch to the new state?
3008 if ( !( priv
->head_note_flags
& IOPMNotDone
) )
3010 // yes, did power raise?
3011 if ( pm_vars
->myCurrentState
< priv
->head_note_state
)
3013 // yes, inform clients and apps
3014 tellChangeUp (priv
->head_note_state
);
3016 // no, if this lowers our
3017 if ( ! priv
->we_are_root
)
3019 // power requirements, tell the parent
3020 ask_parent(priv
->head_note_state
);
3023 previous_state
= pm_vars
->myCurrentState
;
3025 pm_vars
->myCurrentState
= priv
->head_note_state
;
3026 priv
->imminentState
= pm_vars
->myCurrentState
;
3027 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeDone
,(unsigned long)pm_vars
->myCurrentState
,0);
3028 // inform subclass policy-maker
3029 powerChangeDone(previous_state
);
3033 // parent's power change
3034 if ( priv
->head_note_flags
& IOPMParentInitiated
)
3036 if ( ((priv
->head_note_flags
& IOPMDomainWillChange
) && (pm_vars
->myCurrentState
>= priv
->head_note_state
)) ||
3037 ((priv
->head_note_flags
& IOPMDomainDidChange
) && (pm_vars
->myCurrentState
< priv
->head_note_state
)) )
3040 if ( pm_vars
->myCurrentState
< priv
->head_note_state
)
3042 // yes, inform clients and apps
3043 tellChangeUp (priv
->head_note_state
);
3046 previous_state
= pm_vars
->myCurrentState
;
3047 pm_vars
->myCurrentState
= priv
->head_note_state
;
3048 priv
->imminentState
= pm_vars
->myCurrentState
;
3049 pm_vars
->maxCapability
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(priv
->head_note_domainState
);
3051 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeDone
,(unsigned long)pm_vars
->myCurrentState
,0);
3052 // inform subclass policy-maker
3053 powerChangeDone(previous_state
);
3057 IOLockLock(priv
->queue_lock
);
3058 // we're done with this
3059 priv
->changeList
->releaseHeadChangeNote();
3061 // start next one in queue
3062 priv
->head_note
= priv
->changeList
->currentChange();
3063 if ( priv
->head_note
!= -1 )
3066 IOLockUnlock(priv
->queue_lock
);
3067 if (priv
->changeList
->changeNote
[priv
->head_note
].flags
& IOPMWeInitiated
)
3069 start_our_change(priv
->head_note
);
3071 nub
= priv
->changeList
->changeNote
[priv
->head_note
].parent
;
3072 if ( start_parent_change(priv
->head_note
) == IOPMAckImplied
)
3074 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
3077 parent
->acknowledgePowerChange((IOService
*)nub
);
3083 IOLockUnlock(priv
->queue_lock
);
3089 //*********************************************************************************
3092 // A driver or child has acknowledged our notification of an upcoming power
3093 // change, and this acknowledgement is the last one pending
3094 // before we change power or after changing power.
3096 //*********************************************************************************
3098 void IOService::all_acked ( void )
3100 switch (priv
->machine_state
) {
3101 case kIOPM_OurChangeSetPowerState
:
3102 OurChangeSetPowerState();
3104 case kIOPM_OurChangeFinish
:
3107 case kIOPM_ParentDownSetPowerState_Delayed
:
3108 ParentDownSetPowerState_Delayed();
3110 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3111 ParentDownAcknowledgeChange_Delayed();
3113 case kIOPM_ParentUpSetPowerState_Delayed
:
3114 ParentUpSetPowerState_Delayed();
3116 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3117 ParentUpAcknowledgePowerChange_Delayed();
3122 //*********************************************************************************
3123 // settleTimerExpired
3125 // Power has settled after our last change. Notify interested parties that
3126 // there is a new power state.
3127 //*********************************************************************************
3129 void IOService::settleTimerExpired ( void )
3131 if ( ! initialized
)
3137 switch (priv
->machine_state
) {
3138 case kIOPM_OurChangeNotifyInterestedDriversDidChange
:
3139 OurChangeNotifyInterestedDriversDidChange();
3141 case kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
:
3142 ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed();
3144 case kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed
:
3145 ParentUpNotifyInterestedDriversDidChange_Delayed();
3151 //*********************************************************************************
3152 // compute_settle_time
3154 // Compute the power-settling delay in microseconds for the
3155 // change from myCurrentState to head_note_state.
3156 //*********************************************************************************
3158 unsigned long IOService::compute_settle_time ( void )
3160 unsigned long totalTime
;
3163 // compute total time to attain the new state
3165 i
= pm_vars
->myCurrentState
;
3167 // we're lowering power
3168 if ( priv
->head_note_state
< pm_vars
->myCurrentState
)
3170 while ( i
> priv
->head_note_state
)
3172 totalTime
+= pm_vars
->thePowerStates
[i
].settleDownTime
;
3177 // we're raising power
3178 if ( priv
->head_note_state
> pm_vars
->myCurrentState
)
3180 while ( i
< priv
->head_note_state
)
3182 totalTime
+= pm_vars
->thePowerStates
[i
+1].settleUpTime
;
3191 //*********************************************************************************
3194 // Enter with a power-settling delay in microseconds and start a nano-second
3195 // timer for that delay.
3196 //*********************************************************************************
3198 IOReturn
IOService::startSettleTimer ( unsigned long delay
)
3200 AbsoluteTime deadline
;
3202 clock_interval_to_deadline(delay
, kMicrosecondScale
, &deadline
);
3204 thread_call_enter_delayed(priv
->settleTimer
, deadline
);
3209 //*********************************************************************************
3212 // The acknowledgement timeout periodic timer has ticked.
3213 // If we are awaiting acks for a power change notification,
3214 // we decrement the timer word of each interested driver which hasn't acked.
3215 // If a timer word becomes zero, we pretend the driver aknowledged.
3216 // If we are waiting for the controlling driver to change the power
3217 // state of the hardware, we decrement its timer word, and if it becomes
3218 // zero, we pretend the driver acknowledged.
3219 //*********************************************************************************
3221 void IOService::ack_timer_ticked ( void )
3223 IOPMinformee
* nextObject
;
3225 if ( ! initialized
)
3231 if (! acquire_lock() )
3236 switch (priv
->machine_state
) {
3237 case kIOPM_OurChangeWaitForPowerSettle
:
3238 case kIOPM_ParentDownWaitForPowerSettle_Delayed
:
3239 case kIOPM_ParentUpWaitForSettleTime_Delayed
:
3240 // are we waiting for our driver to make its change?
3241 if ( priv
->driver_timer
!= 0 ) {
3243 priv
->driver_timer
-= 1;
3244 // it's tardy, we'll go on without it
3245 if ( priv
->driver_timer
== 0 )
3247 IOUnlock(priv
->our_lock
);
3248 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogCtrlDriverTardy
,0,0);
3251 // still waiting, set timer again
3253 IOUnlock(priv
->our_lock
);
3257 IOUnlock(priv
->our_lock
);
3261 case kIOPM_OurChangeSetPowerState
:
3262 case kIOPM_OurChangeFinish
:
3263 case kIOPM_ParentDownSetPowerState_Delayed
:
3264 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3265 case kIOPM_ParentUpSetPowerState_Delayed
:
3266 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3267 // are we waiting for interested parties to acknowledge?
3268 if (priv
->head_note_pendingAcks
!= 0 )
3270 // yes, go through the list of interested drivers
3271 nextObject
= priv
->interestedDrivers
->firstInList();
3272 // and check each one
3273 while ( nextObject
!= NULL
)
3275 if ( nextObject
->timer
> 0 )
3277 nextObject
->timer
-= 1;
3278 // this one should have acked by now
3279 if ( nextObject
->timer
== 0 )
3281 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogIntDriverTardy
,0,0);
3282 //kprintf("interested driver tardy: %s\n",nextObject->whatObject->getName());
3283 priv
->head_note_pendingAcks
-= 1;
3286 nextObject
= priv
->interestedDrivers
->nextInList(nextObject
);
3289 // is that the last?
3290 if ( priv
->head_note_pendingAcks
== 0 )
3292 IOUnlock(priv
->our_lock
);
3293 // yes, we can continue
3296 // no, set timer again
3298 IOUnlock(priv
->our_lock
);
3301 IOUnlock(priv
->our_lock
);
3305 // apps didn't respond to parent-down notification
3306 case kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate
:
3307 IOUnlock(priv
->our_lock
);
3308 IOLockLock(priv
->flags_lock
);
3309 if (pm_vars
->responseFlags
)
3311 // get rid of this stuff
3312 pm_vars
->responseFlags
->release();
3313 pm_vars
->responseFlags
= NULL
;
3315 IOLockUnlock(priv
->flags_lock
);
3316 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,5);
3317 // carry on with the change
3318 ParentDownTellPriorityClientsPowerDown_Delayed();
3321 case kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
:
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,1);
3332 // carry on with the change
3333 ParentDownNotifyInterestedDriversWillChange_Delayed();
3336 case kIOPM_OurChangeTellClientsPowerDown
:
3337 // apps didn't respond to our power-down request
3338 IOUnlock(priv
->our_lock
);
3339 IOLockLock(priv
->flags_lock
);
3340 if (pm_vars
->responseFlags
)
3342 // get rid of this stuff
3343 pm_vars
->responseFlags
->release();
3344 pm_vars
->responseFlags
= NULL
;
3346 IOLockUnlock(priv
->flags_lock
);
3347 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,2);
3348 // rescind the request
3349 tellNoChangeDown(priv
->head_note_state
);
3350 // mark the change note un-actioned
3351 priv
->head_note_flags
|= IOPMNotDone
;
3356 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
3357 // clients didn't respond to our power-down note
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,4);
3368 // carry on with the change
3369 OurChangeTellPriorityClientsPowerDown();
3372 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
3373 // apps didn't respond to our power-down notification
3374 IOUnlock(priv
->our_lock
);
3375 IOLockLock(priv
->flags_lock
);
3376 if (pm_vars
->responseFlags
)
3378 // get rid of this stuff
3379 pm_vars
->responseFlags
->release();
3380 pm_vars
->responseFlags
= NULL
;
3382 IOLockUnlock(priv
->flags_lock
);
3383 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,3);
3384 // carry on with the change
3385 OurChangeNotifyInterestedDriversWillChange();
3389 // not waiting for acks
3390 IOUnlock(priv
->our_lock
);
3396 //*********************************************************************************
3399 //*********************************************************************************
3401 void IOService::start_ack_timer ( void )
3403 AbsoluteTime deadline
;
3405 clock_interval_to_deadline(ACK_TIMER_PERIOD
, kNanosecondScale
, &deadline
);
3407 thread_call_enter_delayed(priv
->ackTimer
, deadline
);
3411 //*********************************************************************************
3414 //*********************************************************************************
3416 void IOService::stop_ack_timer ( void )
3418 thread_call_cancel(priv
->ackTimer
);
3422 //*********************************************************************************
3423 // c-language timer expiration functions
3425 //*********************************************************************************
3427 static void ack_timer_expired ( thread_call_param_t us
)
3429 ((IOService
*)us
)->ack_timer_ticked();
3433 static void settle_timer_expired ( thread_call_param_t us
)
3435 ((IOService
*)us
)->settleTimerExpired();
3439 //*********************************************************************************
3440 // add_child_to_active_change
3442 // A child has just registered with us. If there is
3443 // currently a change in progress, get the new party involved: if we
3444 // have notified all parties and are waiting for acks, notify the new
3446 //*********************************************************************************
3448 IOReturn
IOService::add_child_to_active_change ( IOPowerConnection
* newObject
)
3450 if (! acquire_lock() )
3455 switch (priv
->machine_state
)
3457 case kIOPM_OurChangeSetPowerState
:
3458 case kIOPM_ParentDownSetPowerState_Delayed
:
3459 case kIOPM_ParentUpSetPowerState_Delayed
:
3460 // one for this child and one to prevent
3461 priv
->head_note_pendingAcks
+= 2;
3462 // incoming acks from changing our state
3463 IOUnlock(priv
->our_lock
);
3464 notifyChild(newObject
, true);
3465 if (! acquire_lock() )
3468 --priv
->head_note_pendingAcks
;
3471 // are we still waiting for acks?
3472 if ( --priv
->head_note_pendingAcks
== 0 )
3474 // no, stop the timer
3476 IOUnlock(priv
->our_lock
);
3478 // and now we can continue
3483 case kIOPM_OurChangeFinish
:
3484 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3485 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3486 // one for this child and one to prevent
3487 priv
->head_note_pendingAcks
+= 2;
3488 // incoming acks from changing our state
3489 IOUnlock(priv
->our_lock
);
3490 notifyChild(newObject
, false);
3491 if (! acquire_lock() )
3494 --priv
->head_note_pendingAcks
;
3497 // are we still waiting for acks?
3498 if ( --priv
->head_note_pendingAcks
== 0 )
3500 // no, stop the timer
3502 IOUnlock(priv
->our_lock
);
3504 // and now we can continue
3510 IOUnlock(priv
->our_lock
);
3515 //*********************************************************************************
3516 // add_driver_to_active_change
3518 // An interested driver has just registered with us. If there is
3519 // currently a change in progress, get the new party involved: if we
3520 // have notified all parties and are waiting for acks, notify the new
3522 //*********************************************************************************
3524 IOReturn
IOService::add_driver_to_active_change ( IOPMinformee
* newObject
)
3526 if (! acquire_lock() )
3531 switch (priv
->machine_state
) {
3532 case kIOPM_OurChangeSetPowerState
:
3533 case kIOPM_ParentDownSetPowerState_Delayed
:
3534 case kIOPM_ParentUpSetPowerState_Delayed
:
3535 // one for this driver and one to prevent
3536 priv
->head_note_pendingAcks
+= 2;
3537 // incoming acks from changing our state
3538 IOUnlock(priv
->our_lock
);
3539 // inform the driver
3540 inform(newObject
, true);
3541 if (! acquire_lock() )
3544 --priv
->head_note_pendingAcks
;
3547 // are we still waiting for acks?
3548 if ( --priv
->head_note_pendingAcks
== 0 )
3550 // no, stop the timer
3552 IOUnlock(priv
->our_lock
);
3554 // and now we can continue
3559 case kIOPM_OurChangeFinish
:
3560 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3561 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3562 // one for this driver and one to prevent
3563 priv
->head_note_pendingAcks
+= 2;
3564 // incoming acks from changing our state
3565 IOUnlock(priv
->our_lock
);
3566 // inform the driver
3567 inform(newObject
, false);
3568 if (! acquire_lock() ) {
3570 --priv
->head_note_pendingAcks
;
3573 // are we still waiting for acks?
3574 if ( --priv
->head_note_pendingAcks
== 0 ) {
3575 // no, stop the timer
3577 IOUnlock(priv
->our_lock
);
3579 // and now we can continue
3585 IOUnlock(priv
->our_lock
);
3590 //*********************************************************************************
3591 // start_parent_change
3593 // Here we begin the processing of a change note initiated by our parent
3594 // which is at the head of the queue.
3596 // It is possible for the change to be processed to completion and removed from the queue.
3597 // There are several possible interruptions to the processing, though, and they are:
3598 // we may have to wait for interested parties to acknowledge our pre-change notification,
3599 // we may have to wait for our controlling driver to change the hardware power state,
3600 // there may be a settling time after changing the hardware power state,
3601 // we may have to wait for interested parties to acknowledge our post-change notification,
3602 // we may have to wait for the acknowledgement timer expiration to substitute for the
3603 // acknowledgement from a failing driver.
3604 //*********************************************************************************
3606 IOReturn
IOService::start_parent_change ( unsigned long queue_head
)
3608 priv
->head_note
= queue_head
;
3609 priv
->head_note_flags
= priv
-> changeList
->changeNote
[priv
->head_note
].flags
;
3610 priv
->head_note_state
= priv
->changeList
->changeNote
[priv
->head_note
].newStateNumber
;
3611 priv
->imminentState
= priv
->head_note_state
;
3612 priv
->head_note_outputFlags
= priv
->changeList
->changeNote
[priv
->head_note
].outputPowerCharacter
;
3613 priv
->head_note_domainState
= priv
->changeList
->changeNote
[priv
->head_note
].domainState
;
3614 priv
->head_note_parent
= priv
->changeList
->changeNote
[priv
->head_note
].parent
;
3615 priv
->head_note_capabilityFlags
= priv
->changeList
->changeNote
[priv
->head_note
].capabilityFlags
;
3617 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartParentChange
,
3618 (unsigned long)priv
->head_note_state
,(unsigned long)pm_vars
->myCurrentState
);
3620 // if we need something and haven't told the parent, do so
3621 ask_parent( priv
->ourDesiredPowerState
);
3623 // power domain is lowering
3624 if ( priv
->head_note_state
< pm_vars
->myCurrentState
)
3626 setParentInfo(priv
->changeList
->changeNote
[priv
->head_note
].singleParentState
,priv
->head_note_parent
);
3627 priv
->initial_change
= false;
3628 // tell apps and kernel clients
3629 priv
->machine_state
= kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate
;
3631 // are we waiting for responses?
3632 if ( tellChangeDown1(priv
->head_note_state
) )
3634 // no, notify priority clients
3635 return ParentDownTellPriorityClientsPowerDown_Immediate();
3638 return IOPMWillAckLater
;
3641 // parent is raising power, we may or may not
3642 if ( priv
->head_note_state
> pm_vars
->myCurrentState
)
3644 if ( priv
->ourDesiredPowerState
> pm_vars
->myCurrentState
)
3646 if ( priv
->ourDesiredPowerState
< priv
->head_note_state
)
3648 // we do, but not all the way
3649 priv
->head_note_state
= priv
->ourDesiredPowerState
;
3650 priv
->imminentState
= priv
->head_note_state
;
3651 priv
->head_note_outputFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].outputPowerCharacter
;
3652 priv
->head_note_capabilityFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].capabilityFlags
;
3653 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAmendParentChange
,(unsigned long)priv
->head_note_state
,0);
3657 priv
->head_note_state
= pm_vars
->myCurrentState
;
3658 priv
->imminentState
= priv
->head_note_state
;
3659 priv
->head_note_outputFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].outputPowerCharacter
;
3660 priv
->head_note_capabilityFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].capabilityFlags
;
3661 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAmendParentChange
,(unsigned long)priv
->head_note_state
,0);
3665 if ( (priv
->head_note_state
> pm_vars
->myCurrentState
) &&
3666 (priv
->head_note_flags
& IOPMDomainDidChange
) )
3669 priv
->initial_change
= false;
3670 priv
->machine_state
= kIOPM_ParentUpSetPowerState_Delayed
;
3671 if ( notifyAll(true) == IOPMAckImplied
) {
3672 return ParentUpSetPowerState_Immediate();
3674 // they didn't all ack
3675 return IOPMWillAckLater
;
3679 // a null change or power will go up
3680 return IOPMAckImplied
;
3684 //*********************************************************************************
3687 // Here we begin the processing of a change note initiated by us
3688 // which is at the head of the queue.
3690 // It is possible for the change to be processed to completion and removed from the queue.
3691 // There are several possible interruptions to the processing, though, and they are:
3692 // we may have to wait for interested parties to acknowledge our pre-change notification,
3693 // changes initiated by the parent will wait in the middle for powerStateDidChange,
3694 // we may have to wait for our controlling driver to change the hardware power state,
3695 // there may be a settling time after changing the hardware power state,
3696 // we may have to wait for interested parties to acknowledge our post-change notification,
3697 // we may have to wait for the acknowledgement timer expiration to substitute for the
3698 // acknowledgement from a failing driver.
3699 //*********************************************************************************
3701 void IOService::start_our_change ( unsigned long queue_head
)
3703 priv
->head_note
= queue_head
;
3704 priv
->head_note_flags
= priv
->changeList
->changeNote
[priv
->head_note
].flags
;
3705 priv
->head_note_state
= priv
->changeList
->changeNote
[priv
->head_note
].newStateNumber
;
3706 priv
->imminentState
= priv
->head_note_state
;
3707 priv
->head_note_outputFlags
= priv
->changeList
->changeNote
[priv
->head_note
].outputPowerCharacter
;
3708 priv
->head_note_capabilityFlags
= priv
->changeList
->changeNote
[priv
->head_note
].capabilityFlags
;
3710 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartDeviceChange
,
3711 (unsigned long)priv
->head_note_state
,(unsigned long)pm_vars
->myCurrentState
);
3713 // can our driver switch to the new state?
3714 if ( priv
->head_note_capabilityFlags
& IOPMNotAttainable
)
3716 // no, ask the parent to do it then
3717 if ( ! priv
->we_are_root
)
3719 ask_parent(priv
->head_note_state
);
3721 // mark the change note un-actioned
3722 priv
-> head_note_flags
|= IOPMNotDone
;
3728 // is there enough power in the domain?
3729 if ( (pm_vars
->maxCapability
< priv
->head_note_state
) && (! priv
->we_are_root
) )
3731 // no, ask the parent to raise it
3732 if ( ! priv
->we_are_root
)
3734 ask_parent(priv
->head_note_state
);
3736 // no, mark the change note un-actioned
3737 priv
->head_note_flags
|= IOPMNotDone
;
3739 // till the parent raises power
3744 if ( ! priv
->initial_change
)
3746 if ( priv
->head_note_state
== pm_vars
->myCurrentState
)
3748 // we initiated a null change; forget it
3753 priv
->initial_change
= false;
3756 if ( priv
->head_note_state
< pm_vars
->myCurrentState
)
3758 // yes, in case we have to wait for acks
3759 priv
->machine_state
= kIOPM_OurChangeTellClientsPowerDown
;
3760 pm_vars
->doNotPowerDown
= false;
3762 // ask apps and kernel clients if we can drop power
3763 pm_vars
->outofbandparameter
= kNotifyApps
;
3764 if ( askChangeDown(priv
->head_note_state
) )
3766 // don't have to wait, did any clients veto?
3767 if ( pm_vars
->doNotPowerDown
)
3769 // yes, rescind the warning
3770 tellNoChangeDown(priv
->head_note_state
);
3771 // mark the change note un-actioned
3772 priv
-> head_note_flags
|= IOPMNotDone
;
3776 // no, tell'em we're dropping power
3777 OurChangeTellClientsPowerDown();
3781 // we are raising power
3782 if ( ! priv
->we_are_root
)
3784 // if this changes our power requirement, tell the parent
3785 ask_parent(priv
->head_note_state
);
3787 // in case they don't all ack
3788 priv
->machine_state
= kIOPM_OurChangeSetPowerState
;
3790 // notify interested drivers and children
3791 if ( notifyAll(true) == IOPMAckImplied
)
3793 OurChangeSetPowerState();
3799 //*********************************************************************************
3802 // Call the power domain parent to ask for a higher power state in the domain
3803 // or to suggest a lower power state.
3804 //*********************************************************************************
3806 IOReturn
IOService::ask_parent ( unsigned long requestedState
)
3810 IOPowerConnection
*connection
;
3812 unsigned long ourRequest
= pm_vars
->thePowerStates
[requestedState
].inputPowerRequirement
;
3814 if ( pm_vars
->thePowerStates
[requestedState
].capabilityFlags
& (kIOPMChildClamp
| kIOPMPreventIdleSleep
) )
3816 ourRequest
|= kIOPMPreventIdleSleep
;
3818 if ( pm_vars
->thePowerStates
[requestedState
].capabilityFlags
& (kIOPMChildClamp2
| kIOPMPreventSystemSleep
) )
3820 ourRequest
|= kIOPMPreventSystemSleep
;
3823 // is this a new desire?
3824 if ( priv
->previousRequest
== ourRequest
)
3826 // no, the parent knows already, just return
3830 if ( priv
->we_are_root
)
3834 priv
->previousRequest
= ourRequest
;
3836 iter
= getParentIterator(gIOPowerPlane
);
3840 while ( (next
= iter
->getNextObject()) )
3842 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
3844 parent
= (IOService
*)connection
->copyParentEntry(gIOPowerPlane
);
3846 if ( parent
->requestPowerDomainState(ourRequest
,connection
,IOPMLowestState
)!= IOPMNoErr
)
3848 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRequestDenied
,
3849 (unsigned long)priv
->previousRequest
,0);
3862 //*********************************************************************************
3865 // Call the controlling driver and have it change the power state of the
3866 // hardware. If it returns IOPMAckImplied, the change is complete, and
3867 // we return IOPMAckImplied. Otherwise, it will ack when the change
3868 // is done; we return IOPMWillAckLater.
3869 //*********************************************************************************
3870 IOReturn
IOService::instruct_driver ( unsigned long newState
)
3874 // can our driver switch to the desired state?
3875 if ( pm_vars
->thePowerStates
[newState
].capabilityFlags
& IOPMNotAttainable
)
3878 return IOPMAckImplied
;
3881 priv
->driver_timer
= -1;
3884 OUR_PMLog( kPMLogProgramHardware
, (UInt32
) this, newState
);
3885 delay
= pm_vars
->theControllingDriver
->setPowerState( newState
,this );
3886 OUR_PMLog((UInt32
) -kPMLogProgramHardware
, (UInt32
) this, (UInt32
) delay
);
3889 if ( delay
== IOPMAckImplied
)
3891 priv
->driver_timer
= 0;
3892 return IOPMAckImplied
;
3895 // it acked behind our back
3896 if ( priv
->driver_timer
== 0 )
3898 return IOPMAckImplied
;
3904 return IOPMAckImplied
;
3908 priv
->driver_timer
= (delay
/ ( ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
3909 return IOPMWillAckLater
;
3913 //*********************************************************************************
3916 // We are acquiring the lock we use to protect our queue head from
3917 // simutaneous access by a thread which calls acknowledgePowerStateChange
3918 // or acknowledgeSetPowerState and the ack timer expiration thread.
3919 // Return TRUE if we acquire the lock, and the queue head didn't change
3920 // while we were acquiring the lock (and maybe blocked).
3921 // If there is no queue head, or it changes while we are blocked,
3922 // return FALSE with the lock unlocked.
3923 //*********************************************************************************
3925 bool IOService::acquire_lock ( void )
3927 long current_change_note
;
3929 current_change_note
= priv
->head_note
;
3930 if ( current_change_note
== -1 ) {
3934 IOTakeLock(priv
->our_lock
);
3935 if ( current_change_note
== priv
->head_note
)
3939 // we blocked and something changed radically
3940 // so there's nothing to do any more
3941 IOUnlock(priv
->our_lock
);
3947 //*********************************************************************************
3950 // Ask registered applications and kernel clients if we can change to a lower
3953 // Subclass can override this to send a different message type. Parameter is
3954 // the destination state number.
3956 // Return true if we don't have to wait for acknowledgements
3957 //*********************************************************************************
3959 bool IOService::askChangeDown ( unsigned long stateNum
)
3961 return tellClientsWithResponse(kIOMessageCanDevicePowerOff
);
3965 //*********************************************************************************
3968 // Notify registered applications and kernel clients that we are definitely
3971 // Return true if we don't have to wait for acknowledgements
3972 //*********************************************************************************
3974 bool IOService::tellChangeDown1 ( unsigned long stateNum
)
3976 pm_vars
->outofbandparameter
= kNotifyApps
;
3977 return tellChangeDown(stateNum
);
3981 //*********************************************************************************
3984 // Notify priority clients that we are definitely dropping power.
3986 // Return true if we don't have to wait for acknowledgements
3987 //*********************************************************************************
3989 bool IOService::tellChangeDown2 ( unsigned long stateNum
)
3991 pm_vars
->outofbandparameter
= kNotifyPriority
;
3992 return tellChangeDown(stateNum
);
3996 //*********************************************************************************
3999 // Notify registered applications and kernel clients that we are definitely
4002 // Subclass can override this to send a different message type. Parameter is
4003 // the destination state number.
4005 // Return true if we don't have to wait for acknowledgements
4006 //*********************************************************************************
4008 bool IOService::tellChangeDown ( unsigned long stateNum
)
4010 return tellClientsWithResponse(kIOMessageDeviceWillPowerOff
);
4014 //*********************************************************************************
4015 // tellClientsWithResponse
4017 // Notify registered applications and kernel clients that we are definitely
4020 // Return true if we don't have to wait for acknowledgements
4021 //*********************************************************************************
4023 bool IOService::tellClientsWithResponse ( int messageType
)
4025 struct context theContext
;
4026 AbsoluteTime deadline
;
4029 pm_vars
->responseFlags
= OSArray::withCapacity( 1 );
4030 pm_vars
->serialNumber
+= 1;
4032 theContext
.responseFlags
= pm_vars
->responseFlags
;
4033 theContext
.serialNumber
= pm_vars
->serialNumber
;
4034 theContext
.flags_lock
= priv
->flags_lock
;
4035 theContext
.counter
= 1;
4036 theContext
.msgType
= messageType
;
4037 theContext
.us
= this;
4038 theContext
.maxTimeRequested
= 0;
4039 theContext
.stateNumber
= priv
->head_note_state
;
4040 theContext
.stateFlags
= priv
->head_note_capabilityFlags
;
4042 IOLockLock(priv
->flags_lock
);
4044 // position zero is false to
4045 // prevent allowCancelCommon from succeeding
4046 aBool
= OSBoolean::withBoolean(false);
4047 theContext
.responseFlags
->setObject(0,aBool
);
4049 IOLockUnlock(priv
->flags_lock
);
4051 switch ( pm_vars
->outofbandparameter
) {
4053 applyToInterested(gIOAppPowerStateInterest
,tellAppWithResponse
,(void *)&theContext
);
4054 applyToInterested(gIOGeneralInterest
,tellClientWithResponse
,(void *)&theContext
);
4056 case kNotifyPriority
:
4057 applyToInterested(gIOPriorityPowerStateInterest
,tellClientWithResponse
,(void *)&theContext
);
4061 if (! acquire_lock() )
4065 IOLockLock(priv
->flags_lock
);
4066 // now fix position zero
4067 aBool
= OSBoolean::withBoolean(true);
4068 theContext
.responseFlags
->replaceObject(0,aBool
);
4070 IOLockUnlock(priv
->flags_lock
);
4072 // do we have to wait for somebody?
4073 if ( ! checkForDone() )
4075 // yes, start the ackTimer
4076 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,theContext
.maxTimeRequested
,0);
4077 clock_interval_to_deadline(theContext
.maxTimeRequested
/ 1000, kMillisecondScale
, &deadline
);
4079 thread_call_enter_delayed(priv
->ackTimer
, deadline
);
4081 IOUnlock(priv
->our_lock
);
4085 IOUnlock(priv
->our_lock
);
4086 IOLockLock(priv
->flags_lock
);
4088 // everybody responded
4089 pm_vars
->responseFlags
->release();
4090 pm_vars
->responseFlags
= NULL
;
4091 IOLockUnlock(priv
->flags_lock
);
4097 //*********************************************************************************
4098 // tellAppWithResponse
4100 // We send a message to an application, and we expect a response, so we compute a
4101 // cookie we can identify the response with.
4102 //*********************************************************************************
4103 void tellAppWithResponse ( OSObject
* object
, void * context
)
4105 struct context
*theContext
= (struct context
*)context
;
4107 IOPMprot
*pm_vars
= theContext
->us
->pm_vars
;
4109 if( OSDynamicCast( IOService
, object
) )
4111 // Automatically 'ack' in kernel clients
4112 IOLockLock(theContext
->flags_lock
);
4113 aBool
= OSBoolean::withBoolean(true);
4114 theContext
->responseFlags
->setObject(theContext
->counter
,aBool
);
4116 IOLockUnlock(theContext
->flags_lock
);
4118 const char *who
= ((IOService
*) object
)->getName();
4119 pm_vars
->thePlatform
->PMLog(who
,
4120 kPMLogClientAcknowledge
, theContext
->msgType
, * (UInt32
*) object
);
4122 UInt32 refcon
= ((theContext
->serialNumber
& 0xFFFF)<<16)
4123 + (theContext
->counter
& 0xFFFF);
4124 IOLockLock(theContext
->flags_lock
);
4125 aBool
= OSBoolean::withBoolean(false);
4126 theContext
->responseFlags
->setObject(theContext
->counter
,aBool
);
4128 IOLockUnlock(theContext
->flags_lock
);
4130 OUR_PMLog(kPMLogAppNotify
, theContext
->msgType
, refcon
);
4131 theContext
->us
->messageClient(theContext
->msgType
,object
,(void *)refcon
);
4132 if ( theContext
->maxTimeRequested
< k30seconds
)
4134 theContext
->maxTimeRequested
= k30seconds
;
4137 theContext
->counter
+= 1;
4140 //*********************************************************************************
4141 // tellClientWithResponse
4143 // We send a message to an in-kernel client, and we expect a response, so we compute a
4144 // cookie we can identify the response with.
4145 // If it doesn't understand the notification (it is not power-management savvy)
4146 // we won't wait for it to prepare for sleep. If it tells us via a return code
4147 // in the passed struct that it is currently ready, we won't wait for it to prepare.
4148 // If it tells us via the return code in the struct that it does need time, we will chill.
4149 //*********************************************************************************
4150 void tellClientWithResponse ( OSObject
* object
, void * context
)
4152 struct context
*theContext
= (struct context
*)context
;
4153 IOPowerStateChangeNotification notify
;
4159 refcon
= ((theContext
->serialNumber
& 0xFFFF)<<16) + (theContext
->counter
& 0xFFFF);
4160 IOLockLock(theContext
->flags_lock
);
4161 aBool
= OSBoolean::withBoolean(false);
4162 theContext
->responseFlags
->setObject(theContext
->counter
,aBool
);
4164 IOLockUnlock(theContext
->flags_lock
);
4166 IOPMprot
*pm_vars
= theContext
->us
->pm_vars
;
4167 if (gIOKitDebug
& kIOLogPower
) {
4168 OUR_PMLog(kPMLogClientNotify
, refcon
, (UInt32
) theContext
->msgType
);
4169 if (OSDynamicCast(IOService
, object
)) {
4170 const char *who
= ((IOService
*) object
)->getName();
4171 pm_vars
->thePlatform
->PMLog(who
,
4172 kPMLogClientNotify
, * (UInt32
*) object
, (UInt32
) object
);
4173 } else if (OSDynamicCast(_IOServiceInterestNotifier
, object
)) {
4174 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
4175 OUR_PMLog(kPMLogClientNotify
, (UInt32
) n
->handler
, 0);
4179 notify
.powerRef
= (void *)refcon
;
4180 notify
.returnValue
= 0;
4181 notify
.stateNumber
= theContext
->stateNumber
;
4182 notify
.stateFlags
= theContext
->stateFlags
;
4183 retCode
= theContext
->us
->messageClient(theContext
->msgType
,object
,(void *)¬ify
);
4184 if ( retCode
== kIOReturnSuccess
)
4186 if ( notify
.returnValue
== 0 )
4188 // client doesn't want time to respond
4189 IOLockLock(theContext
->flags_lock
);
4190 aBool
= OSBoolean::withBoolean(true);
4191 // so set its flag true
4192 theContext
->responseFlags
->replaceObject(theContext
->counter
,aBool
);
4194 IOLockUnlock(theContext
->flags_lock
);
4195 OUR_PMLog(kPMLogClientAcknowledge
, refcon
, (UInt32
) object
);
4197 IOLockLock(theContext
->flags_lock
);
4199 // it does want time, and it hasn't responded yet
4200 theFlag
= theContext
->responseFlags
->getObject(theContext
->counter
);
4203 if ( ((OSBoolean
*)theFlag
)->isFalse() )
4205 // so note its time requirement
4206 if ( theContext
->maxTimeRequested
< notify
.returnValue
)
4208 theContext
->maxTimeRequested
= notify
.returnValue
;
4212 IOLockUnlock(theContext
->flags_lock
);
4215 OUR_PMLog(kPMLogClientAcknowledge
, refcon
, 0);
4216 // not a client of ours
4217 IOLockLock(theContext
->flags_lock
);
4218 // so we won't be waiting for response
4219 aBool
= OSBoolean::withBoolean(true);
4220 theContext
->responseFlags
->replaceObject(theContext
->counter
,aBool
);
4222 IOLockUnlock(theContext
->flags_lock
);
4224 theContext
->counter
+= 1;
4228 //*********************************************************************************
4231 // Notify registered applications and kernel clients that we are not
4234 // Subclass can override this to send a different message type. Parameter is
4235 // the aborted destination state number.
4236 //*********************************************************************************
4238 void IOService::tellNoChangeDown ( unsigned long )
4240 return tellClients(kIOMessageDeviceWillNotPowerOff
);
4244 //*********************************************************************************
4247 // Notify registered applications and kernel clients that we are raising power.
4249 // Subclass can override this to send a different message type. Parameter is
4250 // the aborted destination state number.
4251 //*********************************************************************************
4253 void IOService::tellChangeUp ( unsigned long )
4255 return tellClients(kIOMessageDeviceHasPoweredOn
);
4259 //*********************************************************************************
4262 // Notify registered applications and kernel clients of something.
4263 //*********************************************************************************
4265 void IOService::tellClients ( int messageType
)
4267 struct context theContext
;
4269 theContext
.msgType
= messageType
;
4270 theContext
.us
= this;
4271 theContext
.stateNumber
= priv
->head_note_state
;
4272 theContext
.stateFlags
= priv
->head_note_capabilityFlags
;
4274 applyToInterested(gIOAppPowerStateInterest
,tellClient
,(void *)&theContext
);
4275 applyToInterested(gIOGeneralInterest
,tellClient
,(void *)&theContext
);
4279 //*********************************************************************************
4282 // Notify a registered application or kernel client of something.
4283 //*********************************************************************************
4284 void tellClient ( OSObject
* object
, void * context
)
4286 struct context
*theContext
= (struct context
*)context
;
4287 IOPowerStateChangeNotification notify
;
4289 notify
.powerRef
= (void *) 0;
4290 notify
.returnValue
= 0;
4291 notify
.stateNumber
= theContext
->stateNumber
;
4292 notify
.stateFlags
= theContext
->stateFlags
;
4294 theContext
->us
->messageClient(theContext
->msgType
,object
, ¬ify
);
4298 // **********************************************************************************
4301 // **********************************************************************************
4302 bool IOService::checkForDone ( void )
4307 IOLockLock(priv
->flags_lock
);
4308 if ( pm_vars
->responseFlags
== NULL
)
4310 IOLockUnlock(priv
->flags_lock
);
4314 for ( i
= 0; ; i
++ )
4316 theFlag
= pm_vars
->responseFlags
->getObject(i
);
4317 if ( theFlag
== NULL
)
4321 if ( ((OSBoolean
*)theFlag
)->isFalse() )
4323 IOLockUnlock(priv
->flags_lock
);
4327 IOLockUnlock(priv
->flags_lock
);
4332 // **********************************************************************************
4335 // **********************************************************************************
4336 bool IOService::responseValid ( unsigned long x
)
4338 UInt16 serialComponent
;
4339 UInt16 ordinalComponent
;
4341 unsigned long refcon
= (unsigned long)x
;
4344 serialComponent
= (refcon
>>16) & 0xFFFF;
4345 ordinalComponent
= refcon
& 0xFFFF;
4347 if ( serialComponent
!= pm_vars
->serialNumber
)
4352 IOLockLock(priv
->flags_lock
);
4353 if ( pm_vars
->responseFlags
== NULL
)
4355 IOLockUnlock(priv
->flags_lock
);
4359 theFlag
= pm_vars
->responseFlags
->getObject(ordinalComponent
);
4363 IOLockUnlock(priv
->flags_lock
);
4367 if ( ((OSBoolean
*)theFlag
)->isFalse() )
4369 aBool
= OSBoolean::withBoolean(true);
4370 pm_vars
->responseFlags
->replaceObject(ordinalComponent
,aBool
);
4374 IOLockUnlock(priv
->flags_lock
);
4379 // **********************************************************************************
4382 // Our power state is about to lower, and we have notified applications
4383 // and kernel clients, and one of them has acknowledged. If this is the last to do
4384 // so, and all acknowledgements are positive, we continue with the power change.
4386 // We serialize this processing with timer expiration with a command gate on the
4387 // power management workloop, which the timer expiration is command gated to as well.
4388 // **********************************************************************************
4389 IOReturn
IOService::allowPowerChange ( unsigned long refcon
)
4391 if ( ! initialized
)
4394 return kIOReturnSuccess
;
4397 return pm_vars
->PMcommandGate
->runAction(serializedAllowPowerChange
,(void *)refcon
);
4401 IOReturn
serializedAllowPowerChange ( OSObject
*owner
, void * refcon
, void *, void *, void *)
4403 return ((IOService
*)owner
)->serializedAllowPowerChange2((unsigned long)refcon
);
4406 IOReturn
IOService::serializedAllowPowerChange2 ( unsigned long refcon
)
4409 if ( ! responseValid(refcon
) )
4411 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr5
,refcon
,0);
4413 return kIOReturnSuccess
;
4415 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientAcknowledge
,refcon
,0);
4417 return allowCancelCommon();
4421 // **********************************************************************************
4422 // cancelPowerChange
4424 // Our power state is about to lower, and we have notified applications
4425 // and kernel clients, and one of them has vetoed the change. If this is the last
4426 // client to respond, we abandon the power change.
4428 // We serialize this processing with timer expiration with a command gate on the
4429 // power management workloop, which the timer expiration is command gated to as well.
4430 // **********************************************************************************
4431 IOReturn
IOService::cancelPowerChange ( unsigned long refcon
)
4433 if ( ! initialized
)
4436 return kIOReturnSuccess
;
4439 return pm_vars
->PMcommandGate
->runAction(serializedCancelPowerChange
,(void *)refcon
);
4443 IOReturn
serializedCancelPowerChange ( OSObject
*owner
, void * refcon
, void *, void *, void *)
4445 return ((IOService
*)owner
)->serializedCancelPowerChange2((unsigned long)refcon
);
4448 IOReturn
IOService::serializedCancelPowerChange2 ( unsigned long refcon
)
4451 if ( ! responseValid(refcon
) )
4453 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr5
,refcon
,0);
4455 return kIOReturnSuccess
;
4457 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientCancel
,refcon
,0);
4459 pm_vars
->doNotPowerDown
= true;
4461 return allowCancelCommon();
4465 // **********************************************************************************
4466 // allowCancelCommon
4468 // **********************************************************************************
4469 IOReturn
IOService::allowCancelCommon ( void )
4471 if (! acquire_lock() )
4473 return kIOReturnSuccess
;
4476 // is this the last response?
4477 if ( checkForDone() )
4479 // yes, stop the timer
4481 IOUnlock(priv
->our_lock
);
4482 IOLockLock(priv
->flags_lock
);
4483 if ( pm_vars
->responseFlags
)
4485 pm_vars
->responseFlags
->release();
4486 pm_vars
->responseFlags
= NULL
;
4488 IOLockUnlock(priv
->flags_lock
);
4489 switch (priv
->machine_state
) {
4490 case kIOPM_OurChangeTellClientsPowerDown
:
4491 // our change, was it vetoed?
4492 if ( ! pm_vars
->doNotPowerDown
)
4494 // no, we can continue
4495 OurChangeTellClientsPowerDown();
4497 // yes, rescind the warning
4498 tellNoChangeDown(priv
->head_note_state
);
4499 // mark the change note un-actioned
4500 priv
->head_note_flags
|= IOPMNotDone
;
4506 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
4507 OurChangeTellPriorityClientsPowerDown();
4509 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
4510 // our change, continue
4511 OurChangeNotifyInterestedDriversWillChange();
4513 case kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate
:
4514 // parent change, continue
4515 ParentDownTellPriorityClientsPowerDown_Delayed();
4517 case kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
:
4518 // parent change, continue
4519 ParentDownNotifyInterestedDriversWillChange_Delayed();
4524 IOUnlock(priv
->our_lock
);
4527 return kIOReturnSuccess
;
4532 //*********************************************************************************
4533 // c_PM_clamp_Timer_Expired (C Func)
4535 // Called when our clamp timer expires...we will call the object method.
4536 //*********************************************************************************
4538 static void c_PM_Clamp_Timer_Expired (OSObject
* client
, IOTimerEventSource
*)
4541 ((IOService
*)client
)->PM_Clamp_Timer_Expired ();
4546 //*********************************************************************************
4547 // PM_Clamp_Timer_Expired
4549 // called when clamp timer expires...set power state to 0.
4550 //*********************************************************************************
4552 void IOService::PM_Clamp_Timer_Expired (void)
4555 if ( ! initialized
)
4561 changePowerStateToPriv (0);
4565 //******************************************************************************
4568 // Set to highest available power state for a minimum of duration milliseconds
4569 //******************************************************************************
4571 #define kFiveMinutesInNanoSeconds (300 * NSEC_PER_SEC)
4573 void IOService::clampPowerOn (unsigned long duration
)
4576 changePowerStateToPriv (pm_vars
->theNumberOfPowerStates
-1);
4578 if ( priv
->clampTimerEventSrc
== NULL
) {
4579 priv
->clampTimerEventSrc
= IOTimerEventSource::timerEventSource(this,
4580 c_PM_Clamp_Timer_Expired
);
4582 IOWorkLoop
* workLoop
= getPMworkloop ();
4584 if ( !priv
->clampTimerEventSrc
|| !workLoop
||
4585 ( workLoop
->addEventSource( priv
->clampTimerEventSrc
) != kIOReturnSuccess
) ) {
4590 priv
->clampTimerEventSrc
->setTimeout(300*USEC_PER_SEC
, USEC_PER_SEC
);
4594 //*********************************************************************************
4597 // Does nothing here. This should be implemented in a subclass driver.
4598 //*********************************************************************************
4600 IOReturn
IOService::setPowerState ( unsigned long powerStateOrdinal
, IOService
* whatDevice
)
4606 //*********************************************************************************
4607 // maxCapabilityForDomainState
4609 // Finds the highest power state in the array whose input power
4610 // requirement is equal to the input parameter. Where a more intelligent
4611 // decision is possible, override this in the subclassed driver.
4612 //*********************************************************************************
4614 unsigned long IOService::maxCapabilityForDomainState ( IOPMPowerFlags domainState
)
4618 if (pm_vars
->theNumberOfPowerStates
== 0 )
4622 for ( i
= (pm_vars
->theNumberOfPowerStates
)-1; i
>= 0; i
-- )
4624 if ( (domainState
& pm_vars
->thePowerStates
[i
].inputPowerRequirement
) == pm_vars
->thePowerStates
[i
].inputPowerRequirement
)
4633 //*********************************************************************************
4634 // initialPowerStateForDomainState
4636 // Finds the highest power state in the array whose input power
4637 // requirement is equal to the input parameter. Where a more intelligent
4638 // decision is possible, override this in the subclassed driver.
4639 //*********************************************************************************
4641 unsigned long IOService::initialPowerStateForDomainState ( IOPMPowerFlags domainState
)
4645 if (pm_vars
->theNumberOfPowerStates
== 0 )
4649 for ( i
= (pm_vars
->theNumberOfPowerStates
)-1; i
>= 0; i
-- )
4651 if ( (domainState
& pm_vars
->thePowerStates
[i
].inputPowerRequirement
) == pm_vars
->thePowerStates
[i
].inputPowerRequirement
)
4660 //*********************************************************************************
4661 // powerStateForDomainState
4663 // Finds the highest power state in the array whose input power
4664 // requirement is equal to the input parameter. Where a more intelligent
4665 // decision is possible, override this in the subclassed driver.
4666 //*********************************************************************************
4668 unsigned long IOService::powerStateForDomainState ( IOPMPowerFlags domainState
)
4672 if (pm_vars
->theNumberOfPowerStates
== 0 )
4676 for ( i
= (pm_vars
->theNumberOfPowerStates
)-1; i
>= 0; i
-- )
4678 if ( (domainState
& pm_vars
->thePowerStates
[i
].inputPowerRequirement
) == pm_vars
->thePowerStates
[i
].inputPowerRequirement
)
4687 //*********************************************************************************
4690 // Does nothing here. This should be implemented in a subclass driver.
4691 //*********************************************************************************
4693 bool IOService::didYouWakeSystem ( void )
4699 //*********************************************************************************
4700 // powerStateWillChangeTo
4702 // Does nothing here. This should be implemented in a subclass driver.
4703 //*********************************************************************************
4705 IOReturn
IOService::powerStateWillChangeTo ( IOPMPowerFlags
, unsigned long, IOService
*)
4711 //*********************************************************************************
4712 // powerStateDidChangeTo
4714 // Does nothing here. This should be implemented in a subclass driver.
4715 //*********************************************************************************
4717 IOReturn
IOService::powerStateDidChangeTo ( IOPMPowerFlags
, unsigned long, IOService
*)
4723 //*********************************************************************************
4726 // Does nothing here. This should be implemented in a subclass policy-maker.
4727 //*********************************************************************************
4729 void IOService::powerChangeDone ( unsigned long )
4734 //*********************************************************************************
4737 // Does nothing here. This should be implemented in a subclass driver.
4738 //*********************************************************************************
4740 IOReturn
IOService::newTemperature ( long currentTemp
, IOService
* whichZone
)
4748 #define super OSObject
4750 OSDefineMetaClassAndStructors(IOPMprot
, OSObject
)
4751 //*********************************************************************************
4754 // Serialize protected instance variables for debug output.
4755 //*********************************************************************************
4756 bool IOPMprot::serialize(OSSerialize
*s
) const
4758 OSString
* theOSString
;
4765 // estimate how many bytes we need to present all power states
4766 buf_size
= 150 // beginning and end of string
4767 + (275 * (int)theNumberOfPowerStates
) // size per state
4768 + 100; // extra room just for kicks
4770 buffer
= ptr
= IONew(char, buf_size
);
4774 ptr
+= sprintf(ptr
,"{ theNumberOfPowerStates = %d, ",(unsigned int)theNumberOfPowerStates
);
4776 if ( theNumberOfPowerStates
!= 0 ) {
4777 ptr
+= sprintf(ptr
,"version %d, ",(unsigned int)thePowerStates
[0].version
);
4780 if ( theNumberOfPowerStates
!= 0 ) {
4781 for ( i
= 0; i
< (int)theNumberOfPowerStates
; i
++ ) {
4782 ptr
+= sprintf(ptr
, "power state %d = { ",i
);
4783 ptr
+= sprintf(ptr
,"capabilityFlags %08x, ",(unsigned int)thePowerStates
[i
].capabilityFlags
);
4784 ptr
+= sprintf(ptr
,"outputPowerCharacter %08x, ",(unsigned int)thePowerStates
[i
].outputPowerCharacter
);
4785 ptr
+= sprintf(ptr
,"inputPowerRequirement %08x, ",(unsigned int)thePowerStates
[i
].inputPowerRequirement
);
4786 ptr
+= sprintf(ptr
,"staticPower %d, ",(unsigned int)thePowerStates
[i
].staticPower
);
4787 ptr
+= sprintf(ptr
,"unbudgetedPower %d, ",(unsigned int)thePowerStates
[i
].unbudgetedPower
);
4788 ptr
+= sprintf(ptr
,"powerToAttain %d, ",(unsigned int)thePowerStates
[i
].powerToAttain
);
4789 ptr
+= sprintf(ptr
,"timeToAttain %d, ",(unsigned int)thePowerStates
[i
].timeToAttain
);
4790 ptr
+= sprintf(ptr
,"settleUpTime %d, ",(unsigned int)thePowerStates
[i
].settleUpTime
);
4791 ptr
+= sprintf(ptr
,"timeToLower %d, ",(unsigned int)thePowerStates
[i
].timeToLower
);
4792 ptr
+= sprintf(ptr
,"settleDownTime %d, ",(unsigned int)thePowerStates
[i
].settleDownTime
);
4793 ptr
+= sprintf(ptr
,"powerDomainBudget %d }, ",(unsigned int)thePowerStates
[i
].powerDomainBudget
);
4797 ptr
+= sprintf(ptr
,"aggressiveness = %d, ",(unsigned int)aggressiveness
);
4798 ptr
+= sprintf(ptr
,"myCurrentState = %d, ",(unsigned int)myCurrentState
);
4799 ptr
+= sprintf(ptr
,"parentsCurrentPowerFlags = %08x, ",(unsigned int)parentsCurrentPowerFlags
);
4800 ptr
+= sprintf(ptr
,"maxCapability = %d }",(unsigned int)maxCapability
);
4802 theOSString
= OSString::withCString(buffer
);
4803 rtn_code
= theOSString
->serialize(s
);
4804 theOSString
->release();
4805 IODelete(buffer
, char, buf_size
);
4812 #define super OSObject
4814 OSDefineMetaClassAndStructors(IOPMpriv
, OSObject
)
4815 //*********************************************************************************
4818 // Serialize private instance variables for debug output.
4819 //*********************************************************************************
4820 bool IOPMpriv::serialize(OSSerialize
*s
) const
4822 OSString
* theOSString
;
4826 IOPMinformee
* nextObject
;
4828 buffer
= ptr
= IONew(char, 2000);
4832 ptr
+= sprintf(ptr
,"{ this object = %08x",(unsigned int)owner
);
4833 if ( we_are_root
) {
4834 ptr
+= sprintf(ptr
," (root)");
4836 ptr
+= sprintf(ptr
,", ");
4838 nextObject
= interestedDrivers
->firstInList(); // display interested drivers
4839 while ( nextObject
!= NULL
) {
4840 ptr
+= sprintf(ptr
,"interested driver = %08x, ",(unsigned int)nextObject
->whatObject
);
4841 nextObject
= interestedDrivers
->nextInList(nextObject
);
4844 if ( machine_state
!= kIOPM_Finished
) {
4845 ptr
+= sprintf(ptr
,"machine_state = %d, ",(unsigned int)machine_state
);
4846 ptr
+= sprintf(ptr
,"driver_timer = %d, ",(unsigned int)driver_timer
);
4847 ptr
+= sprintf(ptr
,"settle_time = %d, ",(unsigned int)settle_time
);
4848 ptr
+= sprintf(ptr
,"head_note_flags = %08x, ",(unsigned int)head_note_flags
);
4849 ptr
+= sprintf(ptr
,"head_note_state = %d, ",(unsigned int)head_note_state
);
4850 ptr
+= sprintf(ptr
,"head_note_outputFlags = %08x, ",(unsigned int)head_note_outputFlags
);
4851 ptr
+= sprintf(ptr
,"head_note_domainState = %08x, ",(unsigned int)head_note_domainState
);
4852 ptr
+= sprintf(ptr
,"head_note_capabilityFlags = %08x, ",(unsigned int)head_note_capabilityFlags
);
4853 ptr
+= sprintf(ptr
,"head_note_pendingAcks = %d, ",(unsigned int)head_note_pendingAcks
);
4856 if ( device_overrides
) {
4857 ptr
+= sprintf(ptr
,"device overrides, ");
4859 ptr
+= sprintf(ptr
,"driverDesire = %d, ",(unsigned int)driverDesire
);
4860 ptr
+= sprintf(ptr
,"deviceDesire = %d, ",(unsigned int)deviceDesire
);
4861 ptr
+= sprintf(ptr
,"ourDesiredPowerState = %d, ",(unsigned int)ourDesiredPowerState
);
4862 ptr
+= sprintf(ptr
,"previousRequest = %d }",(unsigned int)previousRequest
);
4864 theOSString
= OSString::withCString(buffer
);
4865 rtn_code
= theOSString
->serialize(s
);
4866 theOSString
->release();
4867 IODelete(buffer
, char, 2000);