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.
588 temporaryMakeUsable();
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
;
642 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRemoveChild
,0,0);
646 // detach nub from child
647 theChild
= theNub
->copyChildEntry(gIOPowerPlane
);
650 theNub
->detachFromChild(theChild
, gIOPowerPlane
);
653 // detach from the nub
654 detachFromChild(theNub
,gIOPowerPlane
);
656 // are we awaiting an ack from this child?
657 if ( theNub
->getAwaitingAck() )
659 // yes, pretend we got one
660 theNub
->setAwaitingAck(false);
661 if ( acquire_lock() )
663 if (priv
->head_note_pendingAcks
!= 0 )
665 // that's one fewer ack to worry about
666 priv
->head_note_pendingAcks
-= 1;
668 if ( priv
->head_note_pendingAcks
== 0 )
670 // yes, stop the timer
672 IOUnlock(priv
->our_lock
);
673 // and now we can continue our power change
676 IOUnlock(priv
->our_lock
);
679 IOUnlock(priv
->our_lock
);
686 // if not fully initialized
687 if ( (pm_vars
->theControllingDriver
== NULL
) ||
688 !(inPlane(gIOPowerPlane
)) ||
689 !(pm_vars
->parentsKnowState
) )
695 // Perhaps the departing child was holding up idle or system sleep - we
696 // need to re-evaluate our childrens' requests.
697 // Clear and re-calculate our kIOPMChildClamp and kIOPMChildClamp2 bits.
698 rebuildChildClampBits();
700 // Change state if we can now tolerate lower power
701 computeDesiredState();
708 //*********************************************************************************
709 // registerPowerDriver
711 // A driver has called us volunteering to control power to our device.
712 // If the power state array it provides is richer than the one we already
713 // know about (supplied by an earlier volunteer), then accept the offer.
714 // Notify all interested parties of our power state, which we now know.
715 //*********************************************************************************
717 IOReturn
IOService::registerPowerDriver ( IOService
* controllingDriver
, IOPMPowerState
* powerStates
, unsigned long numberOfStates
)
720 unsigned long tempDesire
;
722 if ( (numberOfStates
> pm_vars
->theNumberOfPowerStates
)
723 && (numberOfStates
> 1) )
725 if ( priv
->changeList
->currentChange() == -1 )
727 if ( controllingDriver
!= NULL
)
729 if ( numberOfStates
<= IOPMMaxPowerStates
)
731 switch ( powerStates
[0].version
)
734 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriver
,
735 (unsigned long)numberOfStates
, (unsigned long)powerStates
[0].version
);
736 for ( i
= 0; i
< numberOfStates
; i
++ )
738 pm_vars
->thePowerStates
[i
] = powerStates
[i
];
742 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriver
,
743 (unsigned long) numberOfStates
,(unsigned long) powerStates
[0].version
);
744 for ( i
= 0; i
< numberOfStates
; i
++ )
746 pm_vars
->thePowerStates
[i
].version
= powerStates
[i
].version
;
747 pm_vars
->thePowerStates
[i
].capabilityFlags
= powerStates
[i
].capabilityFlags
;
748 pm_vars
->thePowerStates
[i
].outputPowerCharacter
= powerStates
[i
].outputPowerCharacter
;
749 pm_vars
->thePowerStates
[i
].inputPowerRequirement
= powerStates
[i
].inputPowerRequirement
;
750 pm_vars
->thePowerStates
[i
].staticPower
= powerStates
[i
].staticPower
;
751 pm_vars
->thePowerStates
[i
].unbudgetedPower
= powerStates
[i
].unbudgetedPower
;
752 pm_vars
->thePowerStates
[i
].powerToAttain
= powerStates
[i
].powerToAttain
;
753 pm_vars
->thePowerStates
[i
].timeToAttain
= powerStates
[i
].timeToAttain
;
754 pm_vars
->thePowerStates
[i
].settleUpTime
= powerStates
[i
].settleUpTime
;
755 pm_vars
->thePowerStates
[i
].timeToLower
= powerStates
[i
].timeToLower
;
756 pm_vars
->thePowerStates
[i
].settleDownTime
= powerStates
[i
].settleDownTime
;
757 pm_vars
->thePowerStates
[i
].powerDomainBudget
= powerStates
[i
].powerDomainBudget
;
761 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr1
,
762 (unsigned long)powerStates
[0].version
,0);
766 // make a mask of all the character bits we know about
767 pm_vars
->myCharacterFlags
= 0;
768 for ( i
= 0; i
< numberOfStates
; i
++ ) {
769 pm_vars
->myCharacterFlags
|= pm_vars
->thePowerStates
[i
].outputPowerCharacter
;
772 pm_vars
->theNumberOfPowerStates
= numberOfStates
;
773 pm_vars
->theControllingDriver
= controllingDriver
;
774 if ( priv
->interestedDrivers
->findItem(controllingDriver
) == NULL
)
776 // register it as interested, unless already done
777 registerInterestedDriver (controllingDriver
);
779 if ( priv
->need_to_become_usable
) {
780 priv
->need_to_become_usable
= false;
781 priv
->deviceDesire
= pm_vars
->theNumberOfPowerStates
- 1;
784 if ( inPlane(gIOPowerPlane
) &&
785 (pm_vars
->parentsKnowState
) ) {
786 pm_vars
->maxCapability
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(pm_vars
->parentsCurrentPowerFlags
);
787 // initially change into the state we are already in
788 tempDesire
= priv
->deviceDesire
;
789 priv
->deviceDesire
= pm_vars
->theControllingDriver
->initialPowerStateForDomainState(pm_vars
->parentsCurrentPowerFlags
);
790 computeDesiredState();
792 // put this back like before
793 priv
->deviceDesire
= tempDesire
;
796 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr2
,(unsigned long)numberOfStates
,0);
799 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr4
,0,0);
804 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr5
,(unsigned long)numberOfStates
,0);
809 //*********************************************************************************
810 // registerInterestedDriver
812 // Add the caller to our list of interested drivers and return our current
813 // power state. If we don't have a power-controlling driver yet, we will
814 // call this interested driver again later when we do get a driver and find
815 // out what the current power state of the device is.
816 //*********************************************************************************
818 IOPMPowerFlags
IOService::registerInterestedDriver ( IOService
* theDriver
)
820 IOPMinformee
*newInformee
;
821 IOPMPowerFlags futureCapability
;
823 if (theDriver
== NULL
) {
827 // make new driver node
828 newInformee
= new IOPMinformee
;
829 newInformee
->initialize(theDriver
);
830 // add it to list of drivers
831 priv
->interestedDrivers
->addToList(newInformee
);
833 if ( (pm_vars
->theControllingDriver
== NULL
) ||
834 !(inPlane(gIOPowerPlane
)) ||
835 !(pm_vars
->parentsKnowState
) )
837 // can't tell it a state yet
838 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInterestedDriver
,IOPMNotPowerManaged
,0);
839 return IOPMNotPowerManaged
;
842 // can we notify new driver of a change in progress?
843 switch (priv
->machine_state
) {
844 case kIOPM_OurChangeSetPowerState
:
845 case kIOPM_OurChangeFinish
:
846 case kIOPM_ParentDownSetPowerState_Delayed
:
847 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
848 case kIOPM_ParentUpSetPowerState_Delayed
:
849 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
850 // yes, remember what we tell it
851 futureCapability
= priv
->head_note_capabilityFlags
;
852 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInterestedDriver
,(unsigned long)futureCapability
,1);
854 add_driver_to_active_change(newInformee
);
855 // and return the same thing
856 return futureCapability
;
859 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInterestedDriver
,
860 (unsigned long) pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
,2);
862 // no, return current capability
863 return pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
;
867 //*********************************************************************************
868 // deRegisterInterestedDriver
870 //*********************************************************************************
871 IOReturn
IOService::deRegisterInterestedDriver ( IOService
* theDriver
)
873 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRemoveDriver
,0,0);
875 // remove the departing driver
876 priv
->interestedDrivers
->removeFromList(theDriver
);
882 //*********************************************************************************
883 // acknowledgePowerChange
885 // After we notified one of the interested drivers or a power-domain child
886 // of an impending change in power, it has called to say it is now
887 // prepared for the change. If this object is the last to
888 // acknowledge this change, we take whatever action we have been waiting
890 // That may include acknowledging to our parent. In this case, we do it
891 // last of all to insure that this doesn't cause the parent to call us some-
892 // where else and alter data we are relying on here (like the very existance
893 // of a "current change note".)
894 //*********************************************************************************
896 IOReturn
IOService::acknowledgePowerChange ( IOService
* whichObject
)
898 IOPMinformee
*ackingObject
;
899 unsigned long childPower
= kIOPMUnknown
;
902 // one of our interested drivers?
903 ackingObject
= priv
->interestedDrivers
->findItem(whichObject
);
904 if ( ackingObject
== NULL
)
906 if ( ! isChild(whichObject
,gIOPowerPlane
) )
908 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr1
,0,0);
909 //kprintf("errant driver: %s\n",whichObject->getName());
913 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChildAcknowledge
,priv
->head_note_pendingAcks
,0);
916 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogDriverAcknowledge
,priv
->head_note_pendingAcks
,0);
919 if (! acquire_lock() )
924 if (priv
->head_note_pendingAcks
!= 0 )
926 // yes, make sure we're expecting acks
927 if ( ackingObject
!= NULL
)
929 // it's an interested driver
930 // make sure we're expecting this ack
931 if ( ackingObject
->timer
!= 0 )
934 ackingObject
->timer
= 0;
935 // that's one fewer to worry about
936 priv
->head_note_pendingAcks
-= 1;
938 if ( priv
->head_note_pendingAcks
== 0 )
940 // yes, stop the timer
942 IOUnlock(priv
->our_lock
);
943 // and now we can continue
948 // this driver has already acked
949 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr2
,0,0);
950 //kprintf("errant driver: %s\n",whichObject->getName());
954 // make sure we're expecting this ack
955 if ( ((IOPowerConnection
*)whichObject
)->getAwaitingAck() )
957 // that's one fewer to worry about
958 priv
->head_note_pendingAcks
-= 1;
959 ((IOPowerConnection
*)whichObject
)->setAwaitingAck(false);
960 theChild
= (IOService
*)whichObject
->copyChildEntry(gIOPowerPlane
);
963 childPower
= theChild
->currentPowerConsumption();
966 if ( childPower
== kIOPMUnknown
)
968 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
= kIOPMUnknown
;
970 if ( pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
!= kIOPMUnknown
)
972 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
+= childPower
;
976 if ( priv
->head_note_pendingAcks
== 0 ) {
977 // yes, stop the timer
979 IOUnlock(priv
->our_lock
);
980 // and now we can continue
987 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr3
,0,0); // not expecting anybody to ack
988 //kprintf("errant driver: %s\n",whichObject->getName());
990 IOUnlock(priv
->our_lock
);
994 //*********************************************************************************
995 // acknowledgeSetPowerState
997 // After we instructed our controlling driver to change power states,
998 // it has called to say it has finished doing so.
999 // We continue to process the power state change.
1000 //*********************************************************************************
1002 IOReturn
IOService::acknowledgeSetPowerState ( void )
1004 if (!acquire_lock())
1007 IOReturn timer
= priv
->driver_timer
;
1008 if ( timer
== -1 ) {
1009 // driver is acking instead of using return code
1010 OUR_PMLog(kPMLogDriverAcknowledgeSet
, (UInt32
) this, timer
);
1011 priv
->driver_timer
= 0;
1013 else if ( timer
> 0 ) { // are we expecting this?
1014 // yes, stop the timer
1016 priv
->driver_timer
= 0;
1017 OUR_PMLog(kPMLogDriverAcknowledgeSet
, (UInt32
) this, timer
);
1018 IOUnlock(priv
->our_lock
);
1022 // not expecting this
1023 OUR_PMLog(kPMLogAcknowledgeErr4
, (UInt32
) this, 0);
1026 IOUnlock(priv
->our_lock
);
1031 //*********************************************************************************
1034 // Either the controlling driver has called acknowledgeSetPowerState
1035 // or the acknowledgement timer has expired while waiting for that.
1036 // We carry on processing the current change note.
1037 //*********************************************************************************
1039 void IOService::driver_acked ( void )
1041 switch (priv
->machine_state
) {
1042 case kIOPM_OurChangeWaitForPowerSettle
:
1043 OurChangeWaitForPowerSettle();
1045 case kIOPM_ParentDownWaitForPowerSettle_Delayed
:
1046 ParentDownWaitForPowerSettle_Delayed();
1048 case kIOPM_ParentUpWaitForSettleTime_Delayed
:
1049 ParentUpWaitForSettleTime_Delayed();
1055 //*********************************************************************************
1056 // powerDomainWillChangeTo
1058 // Called by the power-hierarchy parent notifying of a new power state
1059 // in the power domain.
1060 // We enqueue a parent power-change to our queue of power changes.
1061 // This may or may not cause us to change power, depending on what
1062 // kind of change is occuring in the domain.
1063 //*********************************************************************************
1065 IOReturn
IOService::powerDomainWillChangeTo ( IOPMPowerFlags newPowerStateFlags
, IOPowerConnection
* whichParent
)
1069 IOPowerConnection
*connection
;
1070 unsigned long newStateNumber
;
1071 IOPMPowerFlags combinedPowerFlags
;
1073 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogWillChange
,(unsigned long)newPowerStateFlags
,0);
1075 if ( ! inPlane(gIOPowerPlane
) )
1078 return IOPMAckImplied
;
1081 IOLockLock(pm_vars
->parentLock
);
1083 if ( (pm_vars
->PMworkloop
== NULL
) || (pm_vars
->PMcommandGate
== NULL
) )
1085 // we have a path to the root
1087 // so find out the workloop
1088 if ( pm_vars
->PMworkloop
!= NULL
)
1090 // and make our command gate
1091 if ( pm_vars
->PMcommandGate
== NULL
)
1093 pm_vars
->PMcommandGate
= IOCommandGate::commandGate((OSObject
*)this);
1094 if ( pm_vars
->PMcommandGate
!= NULL
)
1096 pm_vars
->PMworkloop
->addEventSource(pm_vars
->PMcommandGate
);
1102 IOLockUnlock(pm_vars
->parentLock
);
1104 // combine parents' power states
1105 // to determine our maximum state within the new power domain
1106 combinedPowerFlags
= 0;
1108 iter
= getParentIterator(gIOPowerPlane
);
1112 while ( (next
= iter
->getNextObject()) )
1114 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1116 if ( connection
== whichParent
){
1117 combinedPowerFlags
|= newPowerStateFlags
;
1119 combinedPowerFlags
|= connection
->parentCurrentPowerFlags();
1126 if ( pm_vars
->theControllingDriver
== NULL
)
1128 // we can't take any more action
1129 return IOPMAckImplied
;
1131 newStateNumber
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(combinedPowerFlags
);
1133 return enqueuePowerChange(IOPMParentInitiated
| IOPMDomainWillChange
,
1134 newStateNumber
,combinedPowerFlags
,whichParent
,newPowerStateFlags
);
1138 //*********************************************************************************
1139 // powerDomainDidChangeTo
1141 // Called by the power-hierarchy parent after the power state of the power domain
1142 // has settled at a new level.
1143 // We enqueue a parent power-change to our queue of power changes.
1144 // This may or may not cause us to change power, depending on what
1145 // kind of change is occuring in the domain.
1146 //*********************************************************************************
1148 IOReturn
IOService::powerDomainDidChangeTo ( IOPMPowerFlags newPowerStateFlags
, IOPowerConnection
* whichParent
)
1150 unsigned long newStateNumber
;
1152 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogDidChange
,newPowerStateFlags
,0);
1154 setParentInfo(newPowerStateFlags
,whichParent
);
1156 if ( pm_vars
->theControllingDriver
== NULL
) {
1157 return IOPMAckImplied
;
1160 newStateNumber
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(pm_vars
->parentsCurrentPowerFlags
);
1161 // tell interested parties about it
1162 return enqueuePowerChange(IOPMParentInitiated
| IOPMDomainDidChange
,
1163 newStateNumber
,pm_vars
->parentsCurrentPowerFlags
,whichParent
,0);
1167 //*********************************************************************************
1170 // Set our connection data for one specific parent, and then combine all the parent
1172 //*********************************************************************************
1174 void IOService::setParentInfo ( IOPMPowerFlags newPowerStateFlags
, IOPowerConnection
* whichParent
)
1178 IOPowerConnection
*connection
;
1180 // set our connection data
1181 whichParent
->setParentCurrentPowerFlags(newPowerStateFlags
);
1182 whichParent
->setParentKnowsState(true);
1184 IOLockLock(pm_vars
->parentLock
);
1186 // recompute our parent info
1187 pm_vars
->parentsCurrentPowerFlags
= 0;
1188 pm_vars
->parentsKnowState
= true;
1190 iter
= getParentIterator(gIOPowerPlane
);
1194 while ( (next
= iter
->getNextObject()) )
1196 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1198 pm_vars
->parentsKnowState
&= connection
->parentKnowsState();
1199 pm_vars
->parentsCurrentPowerFlags
|= connection
->parentCurrentPowerFlags();
1204 IOLockUnlock(pm_vars
->parentLock
);
1207 //*********************************************************************************
1208 // rebuildChildClampBits
1210 // The ChildClamp bits (kIOPMChildClamp & kIOPMChildClamp2) in our capabilityFlags
1211 // indicate that one of our children (or grandchildren or great-grandchildren or ...)
1212 // doesn't support idle or system sleep in its current state. Since we don't track the
1213 // origin of each bit, every time any child changes state we have to clear these bits
1214 // and rebuild them.
1215 //*********************************************************************************
1217 void IOService::rebuildChildClampBits(void)
1222 IOPowerConnection
*connection
;
1225 // A child's desires has changed. We need to rebuild the child-clamp bits in our
1226 // power state array. Start by clearing the bits in each power state.
1228 for ( i
= 0; i
< pm_vars
->theNumberOfPowerStates
; i
++ )
1230 pm_vars
->thePowerStates
[i
].capabilityFlags
&= ~(kIOPMChildClamp
| kIOPMChildClamp2
);
1233 // Now loop through the children. When we encounter the calling child, save
1234 // the computed state as this child's desire. And while we're at it, set the ChildClamp bits
1235 // in any of our states that some child has requested with clamp on.
1237 iter
= getChildIterator(gIOPowerPlane
);
1241 while ( (next
= iter
->getNextObject()) )
1243 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1245 if ( connection
->getPreventIdleSleepFlag() )
1246 pm_vars
->thePowerStates
[connection
->getDesiredDomainState()].capabilityFlags
|= kIOPMChildClamp
;
1247 if ( connection
->getPreventSystemSleepFlag() )
1248 pm_vars
->thePowerStates
[connection
->getDesiredDomainState()].capabilityFlags
|= kIOPMChildClamp2
;
1257 //*********************************************************************************
1258 // requestPowerDomainState
1260 // The kIOPMPreventIdleSleep and/or kIOPMPreventIdleSleep bits may be be set in the parameter.
1261 // It is not considered part of the state specification.
1262 //*********************************************************************************
1263 IOReturn
IOService::requestPowerDomainState ( IOPMPowerFlags desiredState
, IOPowerConnection
* whichChild
, unsigned long specification
)
1266 unsigned long computedState
;
1267 unsigned long theDesiredState
= desiredState
& ~(kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
1270 IOPowerConnection
*connection
;
1272 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRequestDomain
,
1273 (unsigned long)desiredState
,(unsigned long)specification
);
1275 if ( pm_vars
->theControllingDriver
== NULL
)
1277 return IOPMNotYetInitialized
;
1280 switch (specification
) {
1281 case IOPMLowestState
:
1283 while ( i
< pm_vars
->theNumberOfPowerStates
)
1285 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1291 if ( i
>= pm_vars
->theNumberOfPowerStates
)
1293 return IOPMNoSuchState
;
1297 case IOPMNextLowerState
:
1298 i
= pm_vars
->myCurrentState
- 1;
1299 while ( (int) i
>= 0 )
1301 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1309 return IOPMNoSuchState
;
1313 case IOPMHighestState
:
1314 i
= pm_vars
->theNumberOfPowerStates
;
1315 while ( (int) i
>= 0 )
1318 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1325 return IOPMNoSuchState
;
1329 case IOPMNextHigherState
:
1330 i
= pm_vars
->myCurrentState
+ 1;
1331 while ( i
< pm_vars
->theNumberOfPowerStates
)
1333 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1339 if ( i
== pm_vars
->theNumberOfPowerStates
)
1341 return IOPMNoSuchState
;
1346 return IOPMBadSpecification
;
1351 IOLockLock(pm_vars
->childLock
);
1353 // Now loop through the children. When we encounter the calling child, save
1354 // the computed state as this child's desire.
1355 iter
= getChildIterator(gIOPowerPlane
);
1359 while ( (next
= iter
->getNextObject()) )
1361 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1363 if ( connection
== whichChild
)
1365 connection
->setDesiredDomainState(computedState
);
1366 connection
->setPreventIdleSleepFlag(desiredState
& kIOPMPreventIdleSleep
);
1367 connection
->setPreventSystemSleepFlag(desiredState
& kIOPMPreventSystemSleep
);
1368 connection
->setChildHasRequestedPower();
1375 // Since a child's power requirements may have changed, clear and rebuild
1376 // kIOPMChildClamp and kIOPMChildClamp2 (idle and system sleep clamps)
1377 rebuildChildClampBits();
1379 IOLockUnlock(pm_vars
->childLock
);
1381 // this may be different now
1382 computeDesiredState();
1384 if ( inPlane(gIOPowerPlane
) &&
1385 (pm_vars
->parentsKnowState
) ) {
1386 // change state if all children can now tolerate lower power
1390 // are we clamped on, waiting for this child?
1391 if ( priv
->clampOn
) {
1392 // yes, remove the clamp
1393 priv
->clampOn
= false;
1394 changePowerStateToPriv(0);
1401 //*********************************************************************************
1402 // temporaryPowerClampOn
1404 // A power domain wants to clamp its power on till it has children which
1405 // will thendetermine the power domain state.
1407 // We enter the highest state until addPowerChild is called.
1408 //*********************************************************************************
1410 IOReturn
IOService::temporaryPowerClampOn ( void )
1412 priv
->clampOn
= true;
1418 //*********************************************************************************
1421 // Some client of our device is asking that we become usable. Although
1422 // this has not come from a subclassed device object, treat it exactly
1423 // as if it had. In this way, subsequent requests for lower power from
1424 // a subclassed device object will pre-empt this request.
1426 // We treat this as a subclass object request to switch to the
1427 // highest power state.
1428 //*********************************************************************************
1430 IOReturn
IOService::makeUsable ( void )
1432 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogMakeUsable
,0,0);
1434 if ( pm_vars
->theControllingDriver
== NULL
)
1436 priv
->need_to_become_usable
= true;
1439 priv
->deviceDesire
= pm_vars
->theNumberOfPowerStates
- 1;
1440 computeDesiredState();
1441 if ( inPlane(gIOPowerPlane
) && (pm_vars
->parentsKnowState
) )
1443 return changeState();
1448 //******************************************************************************
1449 // temporaryMakeUsable
1451 // Private function, called by IOService::addPowerChild to ensure that the
1452 // device is temporarily in a usable power state so that attached power
1453 // children may properly initialize.
1454 //******************************************************************************
1456 IOReturn
IOService::temporaryMakeUsable ( void )
1458 IOReturn ret
= kIOReturnSuccess
;
1459 unsigned long tempDesire
;
1461 pm_vars
->thePlatform
->PMLog( pm_vars
->ourName
,
1464 priv
->deviceDesire
);
1466 if ( pm_vars
->theControllingDriver
== NULL
)
1468 priv
->need_to_become_usable
= true;
1471 tempDesire
= priv
->deviceDesire
;
1472 priv
->deviceDesire
= pm_vars
->theNumberOfPowerStates
- 1;
1473 computeDesiredState();
1474 if ( inPlane(gIOPowerPlane
) && (pm_vars
->parentsKnowState
) )
1476 ret
= changeState();
1478 priv
->deviceDesire
= tempDesire
;
1483 //*********************************************************************************
1484 // currentCapability
1486 //*********************************************************************************
1488 IOPMPowerFlags
IOService::currentCapability ( void )
1490 if ( pm_vars
->theControllingDriver
== NULL
)
1494 return pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
;
1499 //*********************************************************************************
1500 // changePowerStateTo
1502 // For some reason, our power-controlling driver has decided it needs to change
1503 // power state. We enqueue the power change so that appropriate parties
1504 // will be notified, and then we will instruct the driver to make the change.
1505 //*********************************************************************************
1507 IOReturn
IOService::changePowerStateTo ( unsigned long ordinal
)
1509 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeStateTo
,ordinal
,0);
1511 if ( ordinal
>= pm_vars
->theNumberOfPowerStates
)
1513 return IOPMParameterError
;
1515 priv
->driverDesire
= ordinal
;
1516 computeDesiredState();
1517 if ( inPlane(gIOPowerPlane
) && (pm_vars
->parentsKnowState
) )
1519 return changeState();
1525 //*********************************************************************************
1526 // changePowerStateToPriv
1528 // For some reason, a subclassed device object has decided it needs to change
1529 // power state. We enqueue the power change so that appropriate parties
1530 // will be notified, and then we will instruct the driver to make the change.
1531 //*********************************************************************************
1533 IOReturn
IOService::changePowerStateToPriv ( unsigned long ordinal
)
1535 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeStateToPriv
,ordinal
,0);
1537 if ( pm_vars
->theControllingDriver
== NULL
)
1539 return IOPMNotYetInitialized
;
1541 if ( ordinal
>= pm_vars
->theNumberOfPowerStates
)
1543 return IOPMParameterError
;
1545 priv
->deviceDesire
= ordinal
;
1546 computeDesiredState();
1547 if ( inPlane(gIOPowerPlane
) && (pm_vars
->parentsKnowState
) )
1549 return changeState();
1556 //*********************************************************************************
1557 // computeDesiredState
1559 //*********************************************************************************
1561 void IOService::computeDesiredState ( void )
1565 IOPowerConnection
*connection
;
1566 unsigned long newDesiredState
= 0;
1568 // Compute the maximum of our children's desires, our controlling driver's desire, and the subclass device's desire.
1569 if ( ! priv
->device_overrides
)
1571 iter
= getChildIterator(gIOPowerPlane
);
1575 while ( (next
= iter
->getNextObject()) )
1577 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1579 if ( connection
->getDesiredDomainState() > newDesiredState
)
1581 newDesiredState
= connection
->getDesiredDomainState();
1588 if ( priv
->driverDesire
> newDesiredState
)
1590 newDesiredState
= priv
->driverDesire
;
1594 if ( priv
->deviceDesire
> newDesiredState
)
1596 newDesiredState
= priv
->deviceDesire
;
1599 priv
->ourDesiredPowerState
= newDesiredState
;
1603 //*********************************************************************************
1606 // A subclass object, our controlling driver, or a power domain child
1607 // has asked for a different power state. Here we compute what new
1608 // state we should enter and enqueue the change (or start it).
1609 //*********************************************************************************
1611 IOReturn
IOService::changeState ( void )
1613 // if not fully initialized
1614 if ( (pm_vars
->theControllingDriver
== NULL
) ||
1615 !(inPlane(gIOPowerPlane
)) ||
1616 !(pm_vars
->parentsKnowState
) )
1618 // we can do no more
1622 return enqueuePowerChange(IOPMWeInitiated
,priv
->ourDesiredPowerState
,0,0,0);
1626 //*********************************************************************************
1627 // currentPowerConsumption
1629 //*********************************************************************************
1631 unsigned long IOService::currentPowerConsumption ( void )
1633 if ( pm_vars
->theControllingDriver
== NULL
)
1635 return kIOPMUnknown
;
1637 if ( pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
& kIOPMStaticPowerValid
)
1639 return pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].staticPower
;
1641 return kIOPMUnknown
;
1644 //*********************************************************************************
1647 // The activity tickle with parameter kIOPMSubclassPolicyis not handled
1648 // here and should have been intercepted by the subclass.
1649 // The tickle with parameter kIOPMSuperclassPolicy1 causes the activity
1650 // flag to be set, and the device state checked. If the device has been
1651 // powered down, it is powered up again.
1652 //*********************************************************************************
1654 bool IOService::activityTickle ( unsigned long type
, unsigned long stateNumber
)
1656 IOPMrootDomain
*pmRootDomain
;
1657 AbsoluteTime uptime
;
1659 if ( type
== kIOPMSuperclassPolicy1
)
1661 if ( pm_vars
->theControllingDriver
== NULL
)
1666 if( priv
->activityLock
== NULL
)
1668 priv
->activityLock
= IOLockAlloc();
1671 IOTakeLock(priv
->activityLock
);
1672 priv
->device_active
= true;
1674 clock_get_uptime(&uptime
);
1675 priv
->device_active_timestamp
= uptime
;
1677 if ( pm_vars
->myCurrentState
>= stateNumber
)
1679 IOUnlock(priv
->activityLock
);
1682 IOUnlock(priv
->activityLock
);
1684 // Transfer execution to the PM workloop
1685 if( (pmRootDomain
= getPMRootDomain()) )
1686 pmRootDomain
->unIdleDevice(this, stateNumber
);
1693 //*********************************************************************************
1696 // A child is calling to get a pointer to the Power Management workloop.
1697 // We got it or get it from one of our parents.
1698 //*********************************************************************************
1700 IOWorkLoop
* IOService::getPMworkloop ( void )
1705 if ( ! inPlane(gIOPowerPlane
) )
1709 // we have no workloop yet
1710 if ( pm_vars
->PMworkloop
== NULL
)
1712 nub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
1715 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
1717 // ask one of our parents for the workloop
1720 pm_vars
->PMworkloop
= parent
->getPMworkloop();
1725 return pm_vars
->PMworkloop
;
1729 //*********************************************************************************
1730 // setIdleTimerPeriod
1732 // A subclass policy-maker is going to use our standard idleness
1733 // detection service. Make a command queue and an idle timer and
1734 // connect them to the power management workloop. Finally,
1736 //*********************************************************************************
1738 IOReturn
IOService::setIdleTimerPeriod ( unsigned long period
)
1740 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMsetIdleTimerPeriod
,period
, 0);
1742 priv
->idle_timer_period
= period
;
1746 if ( getPMworkloop() == NULL
)
1748 return kIOReturnError
;
1751 // make the timer event
1752 if ( priv
->timerEventSrc
== NULL
)
1754 priv
->timerEventSrc
= IOTimerEventSource::timerEventSource(this,
1755 PM_idle_timer_expired
);
1756 if ((!priv
->timerEventSrc
) ||
1757 (pm_vars
->PMworkloop
->addEventSource(priv
->timerEventSrc
) != kIOReturnSuccess
) )
1759 return kIOReturnError
;
1763 if ( priv
->activityLock
== NULL
)
1765 priv
->activityLock
= IOLockAlloc();
1768 start_PM_idle_timer();
1773 //******************************************************************************
1776 // Returns how many "seconds from now" the device should idle into its
1777 // next lowest power state.
1778 //******************************************************************************
1779 SInt32
IOService::nextIdleTimeout(
1780 AbsoluteTime currentTime
,
1781 AbsoluteTime lastActivity
,
1782 unsigned int powerState
)
1789 // Calculate time difference using funky macro from clock.h.
1790 delta
= currentTime
;
1791 SUB_ABSOLUTETIME(&delta
, &lastActivity
);
1793 // Figure it in seconds.
1794 absolutetime_to_nanoseconds(delta
, &delta_ns
);
1795 delta_secs
= (SInt32
)(delta_ns
/ NSEC_PER_SEC
);
1797 // Be paranoid about delta somehow exceeding timer period.
1798 if (delta_secs
< (int) priv
->idle_timer_period
)
1799 delay_secs
= (int) priv
->idle_timer_period
- delta_secs
;
1801 delay_secs
= (int) priv
->idle_timer_period
;
1803 return (SInt32
)delay_secs
;
1806 //******************************************************************************
1807 // start_PM_idle_timer
1809 // The parameter is a pointer to us. Use it to call our timeout method.
1810 //******************************************************************************
1811 void IOService::start_PM_idle_timer ( void )
1813 static const int maxTimeout
= 100000;
1814 static const int minTimeout
= 1;
1815 AbsoluteTime uptime
;
1818 IOLockLock(priv
->activityLock
);
1820 clock_get_uptime(&uptime
);
1822 // Subclasses may modify idle sleep algorithm
1823 idle_in
= nextIdleTimeout(uptime
,
1824 priv
->device_active_timestamp
,
1825 pm_vars
->myCurrentState
);
1827 // Check for out-of range responses
1828 if(idle_in
> maxTimeout
)
1830 // use standard implementation
1831 idle_in
= IOService::nextIdleTimeout(uptime
,
1832 priv
->device_active_timestamp
,
1833 pm_vars
->myCurrentState
);
1834 } else if(idle_in
< minTimeout
) {
1839 priv
->timerEventSrc
->setTimeout(idle_in
, NSEC_PER_SEC
);
1841 IOLockUnlock(priv
->activityLock
);
1846 //*********************************************************************************
1847 // PM_idle_timer_expired
1849 // The parameter is a pointer to us. Use it to call our timeout method.
1850 //*********************************************************************************
1852 void PM_idle_timer_expired(OSObject
* ourSelves
, IOTimerEventSource
*)
1854 ((IOService
*)ourSelves
)->PM_idle_timer_expiration();
1858 //*********************************************************************************
1859 // PM_idle_timer_expiration
1861 // The idle timer has expired. If there has been activity since the last
1862 // expiration, just restart the timer and return. If there has not been
1863 // activity, switch to the next lower power state and restart the timer.
1864 //*********************************************************************************
1866 void IOService::PM_idle_timer_expiration ( void )
1868 if ( ! initialized
)
1874 if ( priv
->idle_timer_period
> 0 )
1876 IOTakeLock(priv
->activityLock
);
1877 if ( priv
->device_active
)
1879 priv
->device_active
= false;
1880 IOUnlock(priv
->activityLock
);
1881 start_PM_idle_timer();
1884 if ( pm_vars
->myCurrentState
> 0 )
1887 unsigned long newState
= pm_vars
->myCurrentState
- 1;
1889 IOUnlock(priv
->activityLock
);
1890 changePowerStateToPriv(newState
);
1891 if ( newState
>= priv
->ourDesiredPowerState
)
1892 start_PM_idle_timer();
1895 IOUnlock(priv
->activityLock
);
1896 start_PM_idle_timer();
1901 // **********************************************************************************
1904 // We are un-idling a device due to its activity tickle. This routine runs on the
1905 // PM workloop, and is initiated by IOService::activityTickle.
1906 // We process all activityTickle state requests on the list.
1907 // **********************************************************************************
1908 void IOService::command_received ( void *statePtr
, void *, void * , void * )
1910 unsigned long stateNumber
;
1912 stateNumber
= (unsigned long)statePtr
;
1914 // If not initialized, we're unloading
1915 if ( ! initialized
) return;
1917 if ( (pm_vars
->myCurrentState
< stateNumber
) &&
1918 (priv
->imminentState
< stateNumber
) )
1920 changePowerStateToPriv(stateNumber
);
1922 // After we raise our state, re-schedule the idle timer.
1923 if(priv
->timerEventSrc
)
1924 start_PM_idle_timer();
1929 //*********************************************************************************
1930 // setAggressiveness
1932 // Pass on the input parameters to all power domain children. All those which are
1933 // power domains will pass it on to their children, etc.
1934 //*********************************************************************************
1936 IOReturn
IOService::setAggressiveness ( unsigned long type
, unsigned long newLevel
)
1940 IOPowerConnection
*connection
;
1943 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogSetAggressiveness
,type
, newLevel
);
1945 if ( type
<= kMaxType
)
1947 pm_vars
->current_aggressiveness_values
[type
] = newLevel
;
1948 pm_vars
->current_aggressiveness_valid
[type
] = true;
1951 iter
= getChildIterator(gIOPowerPlane
);
1955 while ( (next
= iter
->getNextObject()) )
1957 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1959 child
= ((IOService
*)(connection
->copyChildEntry(gIOPowerPlane
)));
1962 child
->setAggressiveness(type
, newLevel
);
1973 //*********************************************************************************
1974 // getAggressiveness
1976 // Called by the user client.
1977 //*********************************************************************************
1979 IOReturn
IOService::getAggressiveness ( unsigned long type
, unsigned long * currentLevel
)
1981 if ( type
> kMaxType
)
1982 return kIOReturnBadArgument
;
1984 if ( !pm_vars
->current_aggressiveness_valid
[type
] )
1985 return kIOReturnInvalid
;
1987 *currentLevel
= pm_vars
->current_aggressiveness_values
[type
];
1989 return kIOReturnSuccess
;
1992 //*********************************************************************************
1995 // Pass this to all power domain children. All those which are
1996 // power domains will pass it on to their children, etc.
1997 //*********************************************************************************
1999 IOReturn
IOService::systemWake ( void )
2003 IOPowerConnection
*connection
;
2004 IOService
*theChild
;
2006 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogSystemWake
,0, 0);
2008 iter
= getChildIterator(gIOPowerPlane
);
2012 while ( (next
= iter
->getNextObject()) )
2014 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
2016 theChild
= (IOService
*)connection
->copyChildEntry(gIOPowerPlane
);
2019 theChild
->systemWake();
2020 theChild
->release();
2027 if ( pm_vars
->theControllingDriver
!= NULL
)
2029 if ( pm_vars
->theControllingDriver
->didYouWakeSystem() )
2039 //*********************************************************************************
2040 // temperatureCriticalForZone
2042 //*********************************************************************************
2044 IOReturn
IOService::temperatureCriticalForZone ( IOService
* whichZone
)
2046 IOService
*theParent
;
2049 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogCriticalTemp
,0,0);
2051 if ( inPlane(gIOPowerPlane
) && !(priv
->we_are_root
) )
2053 theNub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
2056 theParent
= (IOService
*)theNub
->copyParentEntry(gIOPowerPlane
);
2060 theParent
->temperatureCriticalForZone(whichZone
);
2061 theParent
->release();
2069 //*********************************************************************************
2070 // powerOverrideOnPriv
2072 //*********************************************************************************
2075 IOReturn
IOService::powerOverrideOnPriv ( void )
2077 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogOverrideOn
,0,0);
2079 // turn on the override
2080 priv
->device_overrides
= true;
2081 computeDesiredState();
2083 // change state if that changed something
2084 return changeState();
2088 //*********************************************************************************
2089 // powerOverrideOffPriv
2091 //*********************************************************************************
2092 IOReturn
IOService::powerOverrideOffPriv ( void )
2094 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogOverrideOff
,0,0);
2096 // turn off the override
2097 priv
->device_overrides
= false;
2098 computeDesiredState();
2101 return makeUsable();
2103 // change state if that changed something
2104 return changeState();
2109 //*********************************************************************************
2110 // enqueuePowerChange
2112 // Allocate a new state change notification, initialize it with fields from the
2113 // caller, and add it to the tail of the list of pending power changes.
2115 // If it is early enough in the list, and almost all the time it is the only one in
2116 // the list, start the power change.
2118 // In rare instances, this change will preempt the previous change in the list.
2119 // If the previous change is un-actioned in any way (because we are still
2120 // processing an even earlier power change), and if both the previous change
2121 // in the list and this change are initiated by us (not the parent), then we
2122 // needn't perform the previous change, so we collapse the list a little.
2123 //*********************************************************************************
2125 IOReturn
IOService::enqueuePowerChange (
2126 unsigned long flags
,
2127 unsigned long whatStateOrdinal
,
2128 unsigned long domainState
,
2129 IOPowerConnection
* whichParent
,
2130 unsigned long singleParentState
)
2135 // Create and initialize the new change note
2137 IOLockLock(priv
->queue_lock
);
2138 newNote
= priv
->changeList
->createChangeNote();
2139 if ( newNote
== -1 ) {
2140 // uh-oh, our list is full
2141 IOLockUnlock(priv
->queue_lock
);
2142 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogEnqueueErr
,0,0);
2143 return IOPMAckImplied
;
2146 priv
->changeList
->changeNote
[newNote
].newStateNumber
= whatStateOrdinal
;
2147 priv
->changeList
->changeNote
[newNote
].outputPowerCharacter
= pm_vars
->thePowerStates
[whatStateOrdinal
].outputPowerCharacter
;
2148 priv
->changeList
->changeNote
[newNote
].inputPowerRequirement
= pm_vars
->thePowerStates
[whatStateOrdinal
].inputPowerRequirement
;
2149 priv
->changeList
->changeNote
[newNote
].capabilityFlags
= pm_vars
->thePowerStates
[whatStateOrdinal
].capabilityFlags
;
2150 priv
->changeList
->changeNote
[newNote
].flags
= flags
;
2151 priv
->changeList
->changeNote
[newNote
].parent
= NULL
;
2152 if (flags
& IOPMParentInitiated
)
2154 priv
->changeList
->changeNote
[newNote
].domainState
= domainState
;
2155 priv
->changeList
->changeNote
[newNote
].parent
= whichParent
;
2156 whichParent
->retain();
2157 priv
->changeList
->changeNote
[newNote
].singleParentState
= singleParentState
;
2160 previousNote
= priv
->changeList
->previousChangeNote(newNote
);
2162 if ( previousNote
== -1 )
2165 // Queue is empty, we can start this change.
2167 if (flags
& IOPMWeInitiated
)
2169 IOLockUnlock(priv
->queue_lock
);
2170 start_our_change(newNote
);
2173 IOLockUnlock(priv
->queue_lock
);
2174 return start_parent_change(newNote
);
2178 // The queue is not empty. Try to collapse this new change and the previous one in queue into one change.
2179 // This is possible only if both changes are initiated by us, and neither has been started yet.
2180 // Do this more than once if possible.
2182 // (A change is started iff it is at the head of the queue)
2184 while ( (previousNote
!= priv
->head_note
) && (previousNote
!= -1) &&
2185 (priv
->changeList
->changeNote
[newNote
].flags
& priv
->changeList
->changeNote
[previousNote
].flags
& IOPMWeInitiated
) )
2187 priv
->changeList
->changeNote
[previousNote
].outputPowerCharacter
= priv
->changeList
->changeNote
[newNote
].outputPowerCharacter
;
2188 priv
->changeList
->changeNote
[previousNote
].inputPowerRequirement
= priv
->changeList
->changeNote
[newNote
].inputPowerRequirement
;
2189 priv
->changeList
->changeNote
[previousNote
].capabilityFlags
=priv
-> changeList
->changeNote
[newNote
].capabilityFlags
;
2190 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogCollapseQueue
,priv
->changeList
->changeNote
[newNote
].newStateNumber
,
2191 priv
->changeList
->changeNote
[previousNote
].newStateNumber
);
2192 priv
->changeList
->changeNote
[previousNote
].newStateNumber
= priv
->changeList
->changeNote
[newNote
].newStateNumber
;
2193 priv
->changeList
->releaseTailChangeNote();
2194 newNote
= previousNote
;
2195 previousNote
= priv
->changeList
->previousChangeNote(newNote
);
2197 IOLockUnlock(priv
->queue_lock
);
2198 // in any case, we can't start yet
2199 return IOPMWillAckLater
;
2202 //*********************************************************************************
2205 // Notify all interested parties either that a change is impending or that the
2206 // previously-notified change is done and power has settled.
2207 // The parameter identifies whether this is the
2208 // pre-change notification or the post-change notification.
2210 //*********************************************************************************
2212 IOReturn
IOService::notifyAll ( bool is_prechange
)
2214 IOPMinformee
* nextObject
;
2217 IOPowerConnection
* connection
;
2219 // To prevent acknowledgePowerChange from finishing the change note and
2220 // removing it from the queue if
2221 // some driver calls it, we inflate the number of pending acks so it
2222 // cannot become zero. We'll fix it later.
2224 if(!acquire_lock()) return IOPMAckImplied
;
2226 priv
->head_note_pendingAcks
= 1;
2228 // OK, we will go through the lists of interested drivers and
2229 // power domain children and notify each one of this change.
2231 nextObject
= priv
->interestedDrivers
->firstInList();
2232 while ( nextObject
!= NULL
) {
2234 priv
->head_note_pendingAcks
+=1;
2236 IOUnlock(priv
->our_lock
);
2238 inform(nextObject
, is_prechange
);
2245 nextObject
= priv
->interestedDrivers
->nextInList(nextObject
);
2248 // did they all ack?
2249 if ( priv
->head_note_pendingAcks
> 1 ) {
2251 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2255 IOUnlock(priv
->our_lock
);
2258 iter
= getChildIterator(gIOPowerPlane
);
2259 // summing their power consumption
2260 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
= 0;
2262 if ( iter
&& acquire_lock())
2264 while ( (next
= iter
->getNextObject()) )
2266 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
2268 priv
->head_note_pendingAcks
+=1;
2270 IOUnlock(priv
->our_lock
);
2272 notifyChild(connection
, is_prechange
);
2281 IOUnlock(priv
->our_lock
);
2284 if (! acquire_lock() ) {
2287 // now make this real
2288 priv
->head_note_pendingAcks
-= 1;
2290 if (priv
->head_note_pendingAcks
== 0 ) {
2292 IOUnlock(priv
->our_lock
);
2293 // return ack to parent
2294 return IOPMAckImplied
;
2298 IOUnlock(priv
->our_lock
);
2300 exit
: // unable to acquire_lock exit case
2302 return IOPMWillAckLater
;
2306 //*********************************************************************************
2309 // Notify a power domain child of an upcoming power change.
2311 // If the object acknowledges the current change, we return TRUE.
2312 //*********************************************************************************
2314 bool IOService::notifyChild ( IOPowerConnection
* theNub
, bool is_prechange
)
2316 IOReturn k
= IOPMAckImplied
;
2317 unsigned long childPower
;
2318 IOService
*theChild
;
2320 theChild
= (IOService
*)(theNub
->copyChildEntry(gIOPowerPlane
));
2323 // The child has been detached since we grabbed the child iterator.
2324 // Decrement pending_acks, already incremented in notifyAll,
2325 // to account for this unexpected departure.
2327 if( acquire_lock() )
2329 priv
->head_note_pendingAcks
--;
2330 IOUnlock(priv
->our_lock
);
2335 // Unless the child handles the notification immediately and returns
2336 // kIOPMAckImplied, we'll be awaiting their acknowledgement later.
2337 theNub
->setAwaitingAck(true);
2341 k
= theChild
->powerDomainWillChangeTo(priv
->head_note_outputFlags
,theNub
);
2343 k
= theChild
->powerDomainDidChangeTo(priv
->head_note_outputFlags
,theNub
);
2346 // did the return code ack?
2347 if ( k
== IOPMAckImplied
)
2350 if( acquire_lock() )
2352 priv
->head_note_pendingAcks
--;
2353 IOUnlock(priv
->our_lock
);
2356 theNub
->setAwaitingAck(false);
2357 childPower
= theChild
->currentPowerConsumption();
2358 if ( childPower
== kIOPMUnknown
)
2360 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
= kIOPMUnknown
;
2362 if ( pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
!= kIOPMUnknown
)
2364 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
+= childPower
;
2367 theChild
->release();
2370 theChild
->release();
2375 //*********************************************************************************
2378 // Notify an interested driver of an upcoming power change.
2380 // If the object acknowledges the current change, we return TRUE.
2381 //*********************************************************************************
2383 bool IOService::inform ( IOPMinformee
* nextObject
, bool is_prechange
)
2385 IOReturn k
= IOPMAckImplied
;
2388 nextObject
->timer
= -1;
2392 pm_vars
->thePlatform
->PMLog (pm_vars
->ourName
,PMlogInformDriverPreChange
,
2393 (unsigned long)priv
->head_note_capabilityFlags
,(unsigned long)priv
->head_note_state
);
2394 k
= nextObject
->whatObject
->powerStateWillChangeTo( priv
->head_note_capabilityFlags
,priv
->head_note_state
,this);
2396 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInformDriverPostChange
,
2397 (unsigned long)priv
->head_note_capabilityFlags
,(unsigned long)priv
->head_note_state
);
2398 k
= nextObject
->whatObject
->powerStateDidChangeTo(priv
->head_note_capabilityFlags
,priv
->head_note_state
,this);
2401 // did it ack behind our back?
2402 if ( nextObject
->timer
== 0 )
2408 if ( (k
==IOPMAckImplied
) // no, did the return code ack?
2409 || (k
< 0) ) // somebody goofed
2412 nextObject
->timer
= 0;
2414 if( acquire_lock() )
2416 priv
->head_note_pendingAcks
--;
2417 IOUnlock(priv
->our_lock
);
2423 nextObject
->timer
= (k
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
2429 //*********************************************************************************
2430 // OurChangeTellClientsPowerDown
2432 // All registered applications and kernel clients have positively acknowledged our
2433 // intention of lowering power. Here we notify them all that we will definitely
2434 // lower the power. If we don't have to wait for any of them to acknowledge, we
2435 // carry on by notifying interested drivers. Otherwise, we do wait.
2436 //*********************************************************************************
2438 void IOService::OurChangeTellClientsPowerDown ( void )
2441 priv
->machine_state
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
2443 // are we waiting for responses?
2444 if ( tellChangeDown1(priv
->head_note_state
) )
2446 // no, notify priority clients
2447 OurChangeTellPriorityClientsPowerDown();
2449 // If we are waiting for responses, execution will resume via
2450 // allowCancelCommon() or ack timeout
2454 //*********************************************************************************
2455 // OurChangeTellPriorityClientsPowerDown
2457 // All registered applications and kernel clients have positively acknowledged our
2458 // intention of lowering power. Here we notify "priority" clients that we are
2459 // lowering power. If we don't have to wait for any of them to acknowledge, we
2460 // carry on by notifying interested drivers. Otherwise, we do wait.
2461 //*********************************************************************************
2463 void IOService::OurChangeTellPriorityClientsPowerDown ( void )
2466 priv
->machine_state
= kIOPM_OurChangeNotifyInterestedDriversWillChange
;
2467 // are we waiting for responses?
2468 if ( tellChangeDown2(priv
->head_note_state
) )
2470 // no, notify interested drivers
2471 return OurChangeNotifyInterestedDriversWillChange();
2473 // If we are waiting for responses, execution will resume via
2474 // allowCancelCommon() or ack timeout
2478 //*********************************************************************************
2479 // OurChangeNotifyInterestedDriversWillChange
2481 // All registered applications and kernel clients have acknowledged our notification
2482 // that we are lowering power. Here we notify interested drivers. If we don't have
2483 // to wait for any of them to acknowledge, we instruct our power driver to make the change.
2484 // Otherwise, we do wait.
2485 //*********************************************************************************
2487 void IOService::OurChangeNotifyInterestedDriversWillChange ( void )
2489 // no, in case they don't all ack
2490 priv
->machine_state
= kIOPM_OurChangeSetPowerState
;
2491 if ( notifyAll(true) == IOPMAckImplied
)
2493 // not waiting for responses
2494 OurChangeSetPowerState();
2496 // If we are waiting for responses, execution will resume via
2497 // all_acked() or ack timeout
2501 //*********************************************************************************
2502 // OurChangeSetPowerState
2504 // All interested drivers have acknowledged our pre-change notification of a power
2505 // change we initiated. Here we instruct our controlling driver to make
2506 // the change to the hardware. If it does so, we continue processing
2507 // (waiting for settle and notifying interested parties post-change.)
2508 // If it doesn't, we have to wait for it to acknowledge and then continue.
2509 //*********************************************************************************
2511 void IOService::OurChangeSetPowerState ( void )
2513 priv
->machine_state
= kIOPM_OurChangeWaitForPowerSettle
;
2515 IOLockLock(priv
->our_lock
);
2517 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2519 // it's done, carry on
2520 IOLockUnlock(priv
->our_lock
);
2521 OurChangeWaitForPowerSettle();
2523 // it's not, wait for it
2524 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2526 IOLockUnlock(priv
->our_lock
);
2527 // execution will resume via ack_timer_ticked()
2532 //*********************************************************************************
2533 // OurChangeWaitForPowerSettle
2535 // Our controlling driver has changed power state on the hardware
2536 // during a power change we initiated. Here we see if we need to wait
2537 // for power to settle before continuing. If not, we continue processing
2538 // (notifying interested parties post-change). If so, we wait and
2540 //*********************************************************************************
2542 void IOService::OurChangeWaitForPowerSettle ( void )
2544 priv
->settle_time
= compute_settle_time();
2545 if ( priv
->settle_time
== 0 )
2547 OurChangeNotifyInterestedDriversDidChange();
2549 priv
->machine_state
= kIOPM_OurChangeNotifyInterestedDriversDidChange
;
2550 startSettleTimer(priv
->settle_time
);
2555 //*********************************************************************************
2556 // OurChangeNotifyInterestedDriversDidChange
2558 // Power has settled on a power change we initiated. Here we notify
2559 // all our interested parties post-change. If they all acknowledge, we're
2560 // done with this change note, and we can start on the next one.
2561 // Otherwise we have to wait for acknowledgements and finish up later.
2562 //*********************************************************************************
2564 void IOService::OurChangeNotifyInterestedDriversDidChange ( void )
2566 // in case they don't all ack
2567 priv
->machine_state
= kIOPM_OurChangeFinish
;
2568 if ( notifyAll(false) == IOPMAckImplied
)
2570 // not waiting for responses
2573 // If we are waiting for responses, execution will resume via
2574 // all_acked() or ack timeout
2578 //*********************************************************************************
2581 // Power has settled on a power change we initiated, and
2582 // all our interested parties have acknowledged. We're
2583 // done with this change note, and we can start on the next one.
2584 //*********************************************************************************
2586 void IOService::OurChangeFinish ( void )
2592 //*********************************************************************************
2593 // ParentDownTellPriorityClientsPowerDown_Immediate
2595 // All applications and kernel clients have been notified of a power lowering
2596 // initiated by the parent and we didn't have to wait for any responses. Here
2597 // we notify any priority clients. If they all ack, we continue with the power change.
2598 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2599 //*********************************************************************************
2601 IOReturn
IOService::ParentDownTellPriorityClientsPowerDown_Immediate ( void )
2603 // in case they don't all ack
2604 priv
->machine_state
= kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
;
2605 // are we waiting for responses?
2606 if ( tellChangeDown2(priv
->head_note_state
) )
2608 // no, notify interested drivers
2609 return ParentDownNotifyInterestedDriversWillChange_Immediate();
2611 // If we are waiting for responses, execution will resume via
2612 // allowCancelCommon() or ack timeout
2613 return IOPMWillAckLater
;
2617 //*********************************************************************************
2618 // ParentDownTellPriorityClientsPowerDown_Immediate2
2620 // All priority kernel clients have been notified of a power lowering
2621 // initiated by the parent and we didn't have to wait for any responses. Here
2622 // we notify any interested drivers and power domain children. If they all ack,
2623 // we continue with the power change.
2624 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2625 //*********************************************************************************
2627 IOReturn
IOService::ParentDownNotifyInterestedDriversWillChange_Immediate ( void )
2629 // in case they don't all ack
2630 priv
->machine_state
= kIOPM_ParentDownSetPowerState_Delayed
;
2631 if ( notifyAll(true) == IOPMAckImplied
)
2634 return ParentDownSetPowerState_Immediate();
2636 // If we are waiting for responses, execution will resume via
2637 // all_acked() or ack timeout
2638 return IOPMWillAckLater
;
2642 //*********************************************************************************
2643 // ParentDownTellPriorityClientsPowerDown_Immediate4
2645 // All applications and kernel clients have been notified of a power lowering
2646 // initiated by the parent and we had to wait for responses. Here
2647 // we notify any priority clients. If they all ack, we continue with the power change.
2648 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2649 //*********************************************************************************
2651 void IOService::ParentDownTellPriorityClientsPowerDown_Delayed ( void )
2653 // in case they don't all ack
2654 priv
->machine_state
= kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
;
2656 // are we waiting for responses?
2657 if ( tellChangeDown2(priv
->head_note_state
) )
2659 // no, notify interested drivers
2660 ParentDownNotifyInterestedDriversWillChange_Delayed();
2662 // If we are waiting for responses, execution will resume via
2663 // allowCancelCommon() or ack timeout
2667 //*********************************************************************************
2668 // ParentDownTellPriorityClientsPowerDown_Immediate5
2670 // All applications and kernel clients have been notified of a power lowering
2671 // initiated by the parent and we had to wait for their responses. Here we notify
2672 // any interested drivers and power domain children. If they all ack, we continue
2673 // with the power change.
2674 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2675 //*********************************************************************************
2677 void IOService::ParentDownNotifyInterestedDriversWillChange_Delayed ( void )
2679 // in case they don't all ack
2680 priv
->machine_state
= kIOPM_ParentDownSetPowerState_Delayed
;
2681 if ( notifyAll(true) == IOPMAckImplied
)
2684 ParentDownSetPowerState_Delayed();
2686 // If we are waiting for responses, execution will resume via
2687 // all_acked() or ack timeout
2691 //*********************************************************************************
2692 // ParentDownSetPowerState_Immediate
2694 // All parties have acknowledged our pre-change notification of a power
2695 // lowering initiated by the parent. Here we instruct our controlling driver
2696 // to put the hardware in the state it needs to be in when the domain is
2697 // lowered. If it does so, we continue processing
2698 // (waiting for settle and acknowledging the parent.)
2699 // If it doesn't, we have to wait for it to acknowledge and then continue.
2700 //*********************************************************************************
2702 IOReturn
IOService::ParentDownSetPowerState_Immediate ( void )
2704 priv
->machine_state
= kIOPM_ParentDownWaitForPowerSettle_Delayed
;
2706 IOLockLock(priv
->our_lock
);
2708 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2710 // it's done, carry on
2711 IOLockUnlock(priv
->our_lock
);
2712 return ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate();
2714 // it's not, wait for it
2715 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2717 IOLockUnlock(priv
->our_lock
);
2718 return IOPMWillAckLater
;
2722 //*********************************************************************************
2723 // ParentDownSetPowerState_Delayed
2725 // We had to wait for it, but all parties have acknowledged our pre-change
2726 // notification of a power lowering initiated by the parent.
2727 // Here we instruct our controlling driver
2728 // to put the hardware in the state it needs to be in when the domain is
2729 // lowered. If it does so, we continue processing
2730 // (waiting for settle and acknowledging the parent.)
2731 // If it doesn't, we have to wait for it to acknowledge and then continue.
2732 //*********************************************************************************
2734 void IOService::ParentDownSetPowerState_Delayed ( void )
2736 priv
-> machine_state
= kIOPM_ParentDownWaitForPowerSettle_Delayed
;
2738 IOLockLock(priv
->our_lock
);
2740 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2742 // it's done, carry on
2743 IOLockUnlock(priv
->our_lock
);
2744 ParentDownWaitForPowerSettle_Delayed();
2746 // it's not, wait for it
2747 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2749 IOLockUnlock(priv
->our_lock
);
2754 //*********************************************************************************
2755 // ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate
2757 // Our controlling driver has changed power state on the hardware
2758 // during a power change initiated by our parent. Here we see if we need
2759 // to wait for power to settle before continuing. If not, we continue
2760 // processing (acknowledging our preparedness to the parent).
2761 // If so, we wait and continue later.
2762 //*********************************************************************************
2764 IOReturn
IOService::ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate ( void )
2768 priv
->settle_time
= compute_settle_time();
2769 if ( priv
->settle_time
== 0 )
2771 // store current state in case they don't all ack
2772 priv
->machine_state
= kIOPM_ParentDownAcknowledgeChange_Delayed
;
2773 if ( notifyAll(false) == IOPMAckImplied
)
2775 // not waiting for responses
2776 nub
= priv
->head_note_parent
;
2780 return IOPMAckImplied
;
2782 // If we are waiting for responses, execution will resume via
2783 // all_acked() or ack timeout
2784 return IOPMWillAckLater
;
2786 // let settle time elapse, then notify interest drivers of our power state change in ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
2787 priv
->machine_state
= kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
;
2788 startSettleTimer(priv
->settle_time
);
2789 return IOPMWillAckLater
;
2794 //*********************************************************************************
2795 // ParentDownWaitForPowerSettle_Delayed
2797 // Our controlling driver has changed power state on the hardware
2798 // during a power change initiated by our parent. We have had to wait
2799 // for acknowledgement from interested parties, or we have had to wait
2800 // for the controlling driver to change the state. Here we see if we need
2801 // to wait for power to settle before continuing. If not, we continue
2802 // processing (acknowledging our preparedness to the parent).
2803 // If so, we wait and continue later.
2804 //*********************************************************************************
2806 void IOService::ParentDownWaitForPowerSettle_Delayed ( void )
2808 priv
->settle_time
= compute_settle_time();
2809 if ( priv
->settle_time
== 0 )
2811 ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed();
2813 priv
->machine_state
= kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
;
2814 startSettleTimer(priv
->settle_time
);
2819 //*********************************************************************************
2820 // ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
2822 // Power has settled on a power change initiated by our parent. Here we
2823 // notify interested parties.
2824 //*********************************************************************************
2826 void IOService::ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed ( void )
2828 IORegistryEntry
*nub
;
2831 // in case they don't all ack
2832 priv
->machine_state
= kIOPM_ParentDownAcknowledgeChange_Delayed
;
2833 if ( notifyAll(false) == IOPMAckImplied
) {
2834 nub
= priv
->head_note_parent
;
2837 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
2839 parent
->acknowledgePowerChange((IOService
*)nub
);
2844 // If we are waiting for responses, execution will resume via
2845 // all_acked() or ack timeout in ParentDownAcknowledgeChange_Delayed.
2846 // Notice the duplication of code just above and in ParentDownAcknowledgeChange_Delayed.
2850 //*********************************************************************************
2851 // ParentDownAcknowledgeChange_Delayed
2853 // We had to wait for it, but all parties have acknowledged our post-change
2854 // notification of a power lowering initiated by the parent.
2855 // Here we acknowledge the parent.
2856 // We are done with this change note, and we can start on the next one.
2857 //*********************************************************************************
2859 void IOService::ParentDownAcknowledgeChange_Delayed ( void )
2861 IORegistryEntry
*nub
;
2864 nub
= priv
->head_note_parent
;
2867 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
2870 parent
->acknowledgePowerChange((IOService
*)nub
);
2877 //*********************************************************************************
2878 // ParentUpSetPowerState_Delayed
2880 // Our parent has informed us via powerStateDidChange that it has
2881 // raised the power in our power domain, and we have had to wait
2882 // for some interested party to acknowledge our notification.
2883 // Here we instruct our controlling
2884 // driver to program the hardware to take advantage of the higher domain
2885 // power. If it does so, we continue processing
2886 // (waiting for settle and notifying interested parties post-change.)
2887 // If it doesn't, we have to wait for it to acknowledge and then continue.
2888 //*********************************************************************************
2890 void IOService::ParentUpSetPowerState_Delayed ( void )
2892 priv
->machine_state
= kIOPM_ParentUpWaitForSettleTime_Delayed
;
2894 IOLockLock(priv
->our_lock
);
2896 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2898 // it did it, carry on
2899 IOLockUnlock(priv
->our_lock
);
2900 ParentUpWaitForSettleTime_Delayed();
2902 // it didn't, wait for it
2903 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2905 IOLockUnlock(priv
->our_lock
);
2910 //*********************************************************************************
2911 // ParentUpSetPowerState_Immediate
2913 // Our parent has informed us via powerStateDidChange that it has
2914 // raised the power in our power domain. Here we instruct our controlling
2915 // driver to program the hardware to take advantage of the higher domain
2916 // power. If it does so, we continue processing
2917 // (waiting for settle and notifying interested parties post-change.)
2918 // If it doesn't, we have to wait for it to acknowledge and then continue.
2919 //*********************************************************************************
2921 IOReturn
IOService::ParentUpSetPowerState_Immediate ( void )
2923 priv
->machine_state
= kIOPM_ParentUpWaitForSettleTime_Delayed
;
2925 IOLockLock(priv
->our_lock
);
2927 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2929 // it did it, carry on
2930 IOLockUnlock(priv
->our_lock
);
2931 return ParentUpWaitForSettleTime_Immediate();
2934 // it didn't, wait for it
2935 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2937 IOLockUnlock(priv
->our_lock
);
2938 return IOPMWillAckLater
;
2943 //*********************************************************************************
2944 // ParentUpWaitForSettleTime_Immediate
2946 // Our controlling driver has changed power state on the hardware
2947 // during a power raise initiated by the parent. Here we see if we need to wait
2948 // for power to settle before continuing. If not, we continue processing
2949 // (notifying interested parties post-change). If so, we wait and
2951 //*********************************************************************************
2953 IOReturn
IOService::ParentUpWaitForSettleTime_Immediate ( void )
2955 priv
->settle_time
= compute_settle_time();
2956 if ( priv
->settle_time
== 0 )
2958 return ParentUpNotifyInterestedDriversDidChange_Immediate();
2960 priv
->machine_state
= kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed
;
2961 startSettleTimer(priv
->settle_time
);
2962 return IOPMWillAckLater
;
2967 //*********************************************************************************
2968 // ParentUpWaitForSettleTime_Delayed
2970 // Our controlling driver has changed power state on the hardware
2971 // during a power raise initiated by the parent, but we had to wait for it.
2972 // Here we see if we need to wait for power to settle before continuing.
2973 // If not, we continue processing (notifying interested parties post-change).
2974 // If so, we wait and continue later.
2975 //*********************************************************************************
2977 void IOService::ParentUpWaitForSettleTime_Delayed ( void )
2979 priv
->settle_time
= compute_settle_time();
2980 if ( priv
->settle_time
== 0 )
2982 ParentUpNotifyInterestedDriversDidChange_Delayed();
2984 priv
->machine_state
= kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed
;
2985 startSettleTimer(priv
->settle_time
);
2990 //*********************************************************************************
2991 // ParentUpNotifyInterestedDriversDidChange_Immediate
2993 // No power settling was required on a power raise initiated by the parent.
2994 // Here we notify all our interested parties post-change. If they all acknowledge,
2995 // we're done with this change note, and we can start on the next one.
2996 // Otherwise we have to wait for acknowledgements and finish up later.
2997 //*********************************************************************************
2999 IOReturn
IOService::ParentUpNotifyInterestedDriversDidChange_Immediate ( void )
3003 // in case they don't all ack
3004 priv
->machine_state
= kIOPM_ParentUpAcknowledgePowerChange_Delayed
;
3005 if ( notifyAll(false) == IOPMAckImplied
)
3007 nub
= priv
->head_note_parent
;
3011 return IOPMAckImplied
;
3013 // If we are waiting for responses, execution will resume via
3014 // all_acked() or ack timeout in ParentUpAcknowledgePowerChange_Delayed.
3015 return IOPMWillAckLater
;
3019 //*********************************************************************************
3020 // ParentUpNotifyInterestedDriversDidChange_Delayed
3022 // Power has settled on a power raise initiated by the parent.
3023 // Here we notify all our interested parties post-change. If they all acknowledge,
3024 // we're done with this change note, and we can start on the next one.
3025 // Otherwise we have to wait for acknowledgements and finish up later.
3026 //*********************************************************************************
3028 void IOService::ParentUpNotifyInterestedDriversDidChange_Delayed ( void )
3030 // in case they don't all ack
3031 priv
->machine_state
= kIOPM_ParentUpAcknowledgePowerChange_Delayed
;
3032 if ( notifyAll(false) == IOPMAckImplied
)
3034 ParentUpAcknowledgePowerChange_Delayed();
3036 // If we are waiting for responses, execution will resume via
3037 // all_acked() or ack timeout in ParentUpAcknowledgePowerChange_Delayed.
3041 //*********************************************************************************
3042 // ParentUpAcknowledgePowerChange_Delayed
3044 // All parties have acknowledged our post-change notification of a power
3045 // raising initiated by the parent. Here we acknowledge the parent.
3046 // We are done with this change note, and we can start on the next one.
3047 //*********************************************************************************
3049 void IOService::ParentUpAcknowledgePowerChange_Delayed ( void )
3051 IORegistryEntry
*nub
;
3054 nub
= priv
->head_note_parent
;
3057 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
3060 parent
->acknowledgePowerChange((IOService
*)nub
);
3067 //*********************************************************************************
3070 // A power change is complete, and the used post-change note is at
3071 // the head of the queue. Remove it and set myCurrentState to the result
3072 // of the change. Start up the next change in queue.
3073 //*********************************************************************************
3075 void IOService::all_done ( void )
3077 unsigned long previous_state
;
3078 IORegistryEntry
*nub
;
3081 priv
->machine_state
= kIOPM_Finished
;
3084 if ( priv
->head_note_flags
& IOPMWeInitiated
)
3086 // could our driver switch to the new state?
3087 if ( !( priv
->head_note_flags
& IOPMNotDone
) )
3089 // yes, did power raise?
3090 if ( pm_vars
->myCurrentState
< priv
->head_note_state
)
3092 // yes, inform clients and apps
3093 tellChangeUp (priv
->head_note_state
);
3095 // no, if this lowers our
3096 if ( ! priv
->we_are_root
)
3098 // power requirements, tell the parent
3099 ask_parent(priv
->head_note_state
);
3102 previous_state
= pm_vars
->myCurrentState
;
3104 pm_vars
->myCurrentState
= priv
->head_note_state
;
3105 priv
->imminentState
= pm_vars
->myCurrentState
;
3106 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeDone
,(unsigned long)pm_vars
->myCurrentState
,0);
3107 // inform subclass policy-maker
3108 powerChangeDone(previous_state
);
3112 // parent's power change
3113 if ( priv
->head_note_flags
& IOPMParentInitiated
)
3115 if ( ((priv
->head_note_flags
& IOPMDomainWillChange
) && (pm_vars
->myCurrentState
>= priv
->head_note_state
)) ||
3116 ((priv
->head_note_flags
& IOPMDomainDidChange
) && (pm_vars
->myCurrentState
< priv
->head_note_state
)) )
3119 if ( pm_vars
->myCurrentState
< priv
->head_note_state
)
3121 // yes, inform clients and apps
3122 tellChangeUp (priv
->head_note_state
);
3125 previous_state
= pm_vars
->myCurrentState
;
3126 pm_vars
->myCurrentState
= priv
->head_note_state
;
3127 priv
->imminentState
= pm_vars
->myCurrentState
;
3128 pm_vars
->maxCapability
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(priv
->head_note_domainState
);
3130 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeDone
,(unsigned long)pm_vars
->myCurrentState
,0);
3131 // inform subclass policy-maker
3132 powerChangeDone(previous_state
);
3136 IOLockLock(priv
->queue_lock
);
3137 // we're done with this
3138 priv
->changeList
->releaseHeadChangeNote();
3140 // start next one in queue
3141 priv
->head_note
= priv
->changeList
->currentChange();
3142 if ( priv
->head_note
!= -1 )
3145 IOLockUnlock(priv
->queue_lock
);
3146 if (priv
->changeList
->changeNote
[priv
->head_note
].flags
& IOPMWeInitiated
)
3148 start_our_change(priv
->head_note
);
3150 nub
= priv
->changeList
->changeNote
[priv
->head_note
].parent
;
3151 if ( start_parent_change(priv
->head_note
) == IOPMAckImplied
)
3153 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
3156 parent
->acknowledgePowerChange((IOService
*)nub
);
3162 IOLockUnlock(priv
->queue_lock
);
3168 //*********************************************************************************
3171 // A driver or child has acknowledged our notification of an upcoming power
3172 // change, and this acknowledgement is the last one pending
3173 // before we change power or after changing power.
3175 //*********************************************************************************
3177 void IOService::all_acked ( void )
3179 switch (priv
->machine_state
) {
3180 case kIOPM_OurChangeSetPowerState
:
3181 OurChangeSetPowerState();
3183 case kIOPM_OurChangeFinish
:
3186 case kIOPM_ParentDownSetPowerState_Delayed
:
3187 ParentDownSetPowerState_Delayed();
3189 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3190 ParentDownAcknowledgeChange_Delayed();
3192 case kIOPM_ParentUpSetPowerState_Delayed
:
3193 ParentUpSetPowerState_Delayed();
3195 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3196 ParentUpAcknowledgePowerChange_Delayed();
3201 //*********************************************************************************
3202 // settleTimerExpired
3204 // Power has settled after our last change. Notify interested parties that
3205 // there is a new power state.
3206 //*********************************************************************************
3208 void IOService::settleTimerExpired ( void )
3210 if ( ! initialized
)
3216 switch (priv
->machine_state
) {
3217 case kIOPM_OurChangeNotifyInterestedDriversDidChange
:
3218 OurChangeNotifyInterestedDriversDidChange();
3220 case kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
:
3221 ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed();
3223 case kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed
:
3224 ParentUpNotifyInterestedDriversDidChange_Delayed();
3230 //*********************************************************************************
3231 // compute_settle_time
3233 // Compute the power-settling delay in microseconds for the
3234 // change from myCurrentState to head_note_state.
3235 //*********************************************************************************
3237 unsigned long IOService::compute_settle_time ( void )
3239 unsigned long totalTime
;
3242 // compute total time to attain the new state
3244 i
= pm_vars
->myCurrentState
;
3246 // we're lowering power
3247 if ( priv
->head_note_state
< pm_vars
->myCurrentState
)
3249 while ( i
> priv
->head_note_state
)
3251 totalTime
+= pm_vars
->thePowerStates
[i
].settleDownTime
;
3256 // we're raising power
3257 if ( priv
->head_note_state
> pm_vars
->myCurrentState
)
3259 while ( i
< priv
->head_note_state
)
3261 totalTime
+= pm_vars
->thePowerStates
[i
+1].settleUpTime
;
3270 //*********************************************************************************
3273 // Enter with a power-settling delay in microseconds and start a nano-second
3274 // timer for that delay.
3275 //*********************************************************************************
3277 IOReturn
IOService::startSettleTimer ( unsigned long delay
)
3279 AbsoluteTime deadline
;
3281 clock_interval_to_deadline(delay
, kMicrosecondScale
, &deadline
);
3283 thread_call_enter_delayed(priv
->settleTimer
, deadline
);
3288 //*********************************************************************************
3291 // The acknowledgement timeout periodic timer has ticked.
3292 // If we are awaiting acks for a power change notification,
3293 // we decrement the timer word of each interested driver which hasn't acked.
3294 // If a timer word becomes zero, we pretend the driver aknowledged.
3295 // If we are waiting for the controlling driver to change the power
3296 // state of the hardware, we decrement its timer word, and if it becomes
3297 // zero, we pretend the driver acknowledged.
3298 //*********************************************************************************
3300 void IOService::ack_timer_ticked ( void )
3302 IOPMinformee
* nextObject
;
3304 if ( ! initialized
)
3310 if (! acquire_lock() )
3315 switch (priv
->machine_state
) {
3316 case kIOPM_OurChangeWaitForPowerSettle
:
3317 case kIOPM_ParentDownWaitForPowerSettle_Delayed
:
3318 case kIOPM_ParentUpWaitForSettleTime_Delayed
:
3319 // are we waiting for our driver to make its change?
3320 if ( priv
->driver_timer
!= 0 ) {
3322 priv
->driver_timer
-= 1;
3323 // it's tardy, we'll go on without it
3324 if ( priv
->driver_timer
== 0 )
3326 IOUnlock(priv
->our_lock
);
3327 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogCtrlDriverTardy
,0,0);
3330 // still waiting, set timer again
3332 IOUnlock(priv
->our_lock
);
3336 IOUnlock(priv
->our_lock
);
3340 case kIOPM_OurChangeSetPowerState
:
3341 case kIOPM_OurChangeFinish
:
3342 case kIOPM_ParentDownSetPowerState_Delayed
:
3343 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3344 case kIOPM_ParentUpSetPowerState_Delayed
:
3345 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3346 // are we waiting for interested parties to acknowledge?
3347 if (priv
->head_note_pendingAcks
!= 0 )
3349 // yes, go through the list of interested drivers
3350 nextObject
= priv
->interestedDrivers
->firstInList();
3351 // and check each one
3352 while ( nextObject
!= NULL
)
3354 if ( nextObject
->timer
> 0 )
3356 nextObject
->timer
-= 1;
3357 // this one should have acked by now
3358 if ( nextObject
->timer
== 0 )
3360 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogIntDriverTardy
,0,0);
3361 //kprintf("interested driver tardy: %s\n",nextObject->whatObject->getName());
3362 priv
->head_note_pendingAcks
-= 1;
3365 nextObject
= priv
->interestedDrivers
->nextInList(nextObject
);
3368 // is that the last?
3369 if ( priv
->head_note_pendingAcks
== 0 )
3371 IOUnlock(priv
->our_lock
);
3372 // yes, we can continue
3375 // no, set timer again
3377 IOUnlock(priv
->our_lock
);
3380 IOUnlock(priv
->our_lock
);
3384 // apps didn't respond to parent-down notification
3385 case kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate
:
3386 IOUnlock(priv
->our_lock
);
3387 IOLockLock(priv
->flags_lock
);
3388 if (pm_vars
->responseFlags
)
3390 // get rid of this stuff
3391 pm_vars
->responseFlags
->release();
3392 pm_vars
->responseFlags
= NULL
;
3394 IOLockUnlock(priv
->flags_lock
);
3395 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,5);
3396 // carry on with the change
3397 ParentDownTellPriorityClientsPowerDown_Delayed();
3400 case kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
:
3401 IOUnlock(priv
->our_lock
);
3402 IOLockLock(priv
->flags_lock
);
3403 if (pm_vars
->responseFlags
)
3405 // get rid of this stuff
3406 pm_vars
->responseFlags
->release();
3407 pm_vars
->responseFlags
= NULL
;
3409 IOLockUnlock(priv
->flags_lock
);
3410 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,1);
3411 // carry on with the change
3412 ParentDownNotifyInterestedDriversWillChange_Delayed();
3415 case kIOPM_OurChangeTellClientsPowerDown
:
3416 // apps didn't respond to our power-down request
3417 IOUnlock(priv
->our_lock
);
3418 IOLockLock(priv
->flags_lock
);
3419 if (pm_vars
->responseFlags
)
3421 // get rid of this stuff
3422 pm_vars
->responseFlags
->release();
3423 pm_vars
->responseFlags
= NULL
;
3425 IOLockUnlock(priv
->flags_lock
);
3426 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,2);
3427 // rescind the request
3428 tellNoChangeDown(priv
->head_note_state
);
3429 // mark the change note un-actioned
3430 priv
->head_note_flags
|= IOPMNotDone
;
3435 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
3436 // clients didn't respond to our power-down note
3437 IOUnlock(priv
->our_lock
);
3438 IOLockLock(priv
->flags_lock
);
3439 if (pm_vars
->responseFlags
)
3441 // get rid of this stuff
3442 pm_vars
->responseFlags
->release();
3443 pm_vars
->responseFlags
= NULL
;
3445 IOLockUnlock(priv
->flags_lock
);
3446 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,4);
3447 // carry on with the change
3448 OurChangeTellPriorityClientsPowerDown();
3451 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
3452 // apps didn't respond to our power-down notification
3453 IOUnlock(priv
->our_lock
);
3454 IOLockLock(priv
->flags_lock
);
3455 if (pm_vars
->responseFlags
)
3457 // get rid of this stuff
3458 pm_vars
->responseFlags
->release();
3459 pm_vars
->responseFlags
= NULL
;
3461 IOLockUnlock(priv
->flags_lock
);
3462 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,3);
3463 // carry on with the change
3464 OurChangeNotifyInterestedDriversWillChange();
3468 // not waiting for acks
3469 IOUnlock(priv
->our_lock
);
3475 //*********************************************************************************
3478 //*********************************************************************************
3480 void IOService::start_ack_timer ( void )
3482 AbsoluteTime deadline
;
3484 clock_interval_to_deadline(ACK_TIMER_PERIOD
, kNanosecondScale
, &deadline
);
3486 thread_call_enter_delayed(priv
->ackTimer
, deadline
);
3490 //*********************************************************************************
3493 //*********************************************************************************
3495 void IOService::stop_ack_timer ( void )
3497 thread_call_cancel(priv
->ackTimer
);
3501 //*********************************************************************************
3502 // c-language timer expiration functions
3504 //*********************************************************************************
3506 static void ack_timer_expired ( thread_call_param_t us
)
3508 ((IOService
*)us
)->ack_timer_ticked();
3512 static void settle_timer_expired ( thread_call_param_t us
)
3514 ((IOService
*)us
)->settleTimerExpired();
3518 //*********************************************************************************
3519 // add_child_to_active_change
3521 // A child has just registered with us. If there is
3522 // currently a change in progress, get the new party involved: if we
3523 // have notified all parties and are waiting for acks, notify the new
3525 //*********************************************************************************
3527 IOReturn
IOService::add_child_to_active_change ( IOPowerConnection
* newObject
)
3529 if (! acquire_lock() )
3534 switch (priv
->machine_state
)
3536 case kIOPM_OurChangeSetPowerState
:
3537 case kIOPM_ParentDownSetPowerState_Delayed
:
3538 case kIOPM_ParentUpSetPowerState_Delayed
:
3539 // one for this child and one to prevent
3540 priv
->head_note_pendingAcks
+= 2;
3541 // incoming acks from changing our state
3542 IOUnlock(priv
->our_lock
);
3543 notifyChild(newObject
, true);
3544 if (! acquire_lock() )
3547 --priv
->head_note_pendingAcks
;
3550 // are we still waiting for acks?
3551 if ( --priv
->head_note_pendingAcks
== 0 )
3553 // no, stop the timer
3555 IOUnlock(priv
->our_lock
);
3557 // and now we can continue
3562 case kIOPM_OurChangeFinish
:
3563 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3564 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3565 // one for this child and one to prevent
3566 priv
->head_note_pendingAcks
+= 2;
3567 // incoming acks from changing our state
3568 IOUnlock(priv
->our_lock
);
3569 notifyChild(newObject
, false);
3570 if (! acquire_lock() )
3573 --priv
->head_note_pendingAcks
;
3576 // are we still waiting for acks?
3577 if ( --priv
->head_note_pendingAcks
== 0 )
3579 // no, stop the timer
3581 IOUnlock(priv
->our_lock
);
3583 // and now we can continue
3589 IOUnlock(priv
->our_lock
);
3594 //*********************************************************************************
3595 // add_driver_to_active_change
3597 // An interested driver has just registered with us. If there is
3598 // currently a change in progress, get the new party involved: if we
3599 // have notified all parties and are waiting for acks, notify the new
3601 //*********************************************************************************
3603 IOReturn
IOService::add_driver_to_active_change ( IOPMinformee
* newObject
)
3605 if (! acquire_lock() )
3610 switch (priv
->machine_state
) {
3611 case kIOPM_OurChangeSetPowerState
:
3612 case kIOPM_ParentDownSetPowerState_Delayed
:
3613 case kIOPM_ParentUpSetPowerState_Delayed
:
3614 // one for this driver and one to prevent
3615 priv
->head_note_pendingAcks
+= 2;
3616 // incoming acks from changing our state
3617 IOUnlock(priv
->our_lock
);
3618 // inform the driver
3619 inform(newObject
, true);
3620 if (! acquire_lock() )
3623 --priv
->head_note_pendingAcks
;
3626 // are we still waiting for acks?
3627 if ( --priv
->head_note_pendingAcks
== 0 )
3629 // no, stop the timer
3631 IOUnlock(priv
->our_lock
);
3633 // and now we can continue
3638 case kIOPM_OurChangeFinish
:
3639 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3640 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3641 // one for this driver and one to prevent
3642 priv
->head_note_pendingAcks
+= 2;
3643 // incoming acks from changing our state
3644 IOUnlock(priv
->our_lock
);
3645 // inform the driver
3646 inform(newObject
, false);
3647 if (! acquire_lock() ) {
3649 --priv
->head_note_pendingAcks
;
3652 // are we still waiting for acks?
3653 if ( --priv
->head_note_pendingAcks
== 0 ) {
3654 // no, stop the timer
3656 IOUnlock(priv
->our_lock
);
3658 // and now we can continue
3664 IOUnlock(priv
->our_lock
);
3669 //*********************************************************************************
3670 // start_parent_change
3672 // Here we begin the processing of a change note initiated by our parent
3673 // which is at the head of the queue.
3675 // It is possible for the change to be processed to completion and removed from the queue.
3676 // There are several possible interruptions to the processing, though, and they are:
3677 // we may have to wait for interested parties to acknowledge our pre-change notification,
3678 // we may have to wait for our controlling driver to change the hardware power state,
3679 // there may be a settling time after changing the hardware power state,
3680 // we may have to wait for interested parties to acknowledge our post-change notification,
3681 // we may have to wait for the acknowledgement timer expiration to substitute for the
3682 // acknowledgement from a failing driver.
3683 //*********************************************************************************
3685 IOReturn
IOService::start_parent_change ( unsigned long queue_head
)
3687 priv
->head_note
= queue_head
;
3688 priv
->head_note_flags
= priv
-> changeList
->changeNote
[priv
->head_note
].flags
;
3689 priv
->head_note_state
= priv
->changeList
->changeNote
[priv
->head_note
].newStateNumber
;
3690 priv
->imminentState
= priv
->head_note_state
;
3691 priv
->head_note_outputFlags
= priv
->changeList
->changeNote
[priv
->head_note
].outputPowerCharacter
;
3692 priv
->head_note_domainState
= priv
->changeList
->changeNote
[priv
->head_note
].domainState
;
3693 priv
->head_note_parent
= priv
->changeList
->changeNote
[priv
->head_note
].parent
;
3694 priv
->head_note_capabilityFlags
= priv
->changeList
->changeNote
[priv
->head_note
].capabilityFlags
;
3696 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartParentChange
,
3697 (unsigned long)priv
->head_note_state
,(unsigned long)pm_vars
->myCurrentState
);
3699 // if we need something and haven't told the parent, do so
3700 ask_parent( priv
->ourDesiredPowerState
);
3702 // power domain is lowering
3703 if ( priv
->head_note_state
< pm_vars
->myCurrentState
)
3705 setParentInfo(priv
->changeList
->changeNote
[priv
->head_note
].singleParentState
,priv
->head_note_parent
);
3706 priv
->initial_change
= false;
3707 // tell apps and kernel clients
3708 priv
->machine_state
= kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate
;
3710 // are we waiting for responses?
3711 if ( tellChangeDown1(priv
->head_note_state
) )
3713 // no, notify priority clients
3714 return ParentDownTellPriorityClientsPowerDown_Immediate();
3717 return IOPMWillAckLater
;
3720 // parent is raising power, we may or may not
3721 if ( priv
->head_note_state
> pm_vars
->myCurrentState
)
3723 if ( priv
->ourDesiredPowerState
> pm_vars
->myCurrentState
)
3725 if ( priv
->ourDesiredPowerState
< priv
->head_note_state
)
3727 // we do, but not all the way
3728 priv
->head_note_state
= priv
->ourDesiredPowerState
;
3729 priv
->imminentState
= priv
->head_note_state
;
3730 priv
->head_note_outputFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].outputPowerCharacter
;
3731 priv
->head_note_capabilityFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].capabilityFlags
;
3732 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAmendParentChange
,(unsigned long)priv
->head_note_state
,0);
3736 priv
->head_note_state
= pm_vars
->myCurrentState
;
3737 priv
->imminentState
= priv
->head_note_state
;
3738 priv
->head_note_outputFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].outputPowerCharacter
;
3739 priv
->head_note_capabilityFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].capabilityFlags
;
3740 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAmendParentChange
,(unsigned long)priv
->head_note_state
,0);
3744 if ( (priv
->head_note_state
> pm_vars
->myCurrentState
) &&
3745 (priv
->head_note_flags
& IOPMDomainDidChange
) )
3748 priv
->initial_change
= false;
3749 priv
->machine_state
= kIOPM_ParentUpSetPowerState_Delayed
;
3750 if ( notifyAll(true) == IOPMAckImplied
) {
3751 return ParentUpSetPowerState_Immediate();
3753 // they didn't all ack
3754 return IOPMWillAckLater
;
3758 // a null change or power will go up
3759 return IOPMAckImplied
;
3763 //*********************************************************************************
3766 // Here we begin the processing of a change note initiated by us
3767 // which is at the head of the queue.
3769 // It is possible for the change to be processed to completion and removed from the queue.
3770 // There are several possible interruptions to the processing, though, and they are:
3771 // we may have to wait for interested parties to acknowledge our pre-change notification,
3772 // changes initiated by the parent will wait in the middle for powerStateDidChange,
3773 // we may have to wait for our controlling driver to change the hardware power state,
3774 // there may be a settling time after changing the hardware power state,
3775 // we may have to wait for interested parties to acknowledge our post-change notification,
3776 // we may have to wait for the acknowledgement timer expiration to substitute for the
3777 // acknowledgement from a failing driver.
3778 //*********************************************************************************
3780 void IOService::start_our_change ( unsigned long queue_head
)
3782 priv
->head_note
= queue_head
;
3783 priv
->head_note_flags
= priv
->changeList
->changeNote
[priv
->head_note
].flags
;
3784 priv
->head_note_state
= priv
->changeList
->changeNote
[priv
->head_note
].newStateNumber
;
3785 priv
->imminentState
= priv
->head_note_state
;
3786 priv
->head_note_outputFlags
= priv
->changeList
->changeNote
[priv
->head_note
].outputPowerCharacter
;
3787 priv
->head_note_capabilityFlags
= priv
->changeList
->changeNote
[priv
->head_note
].capabilityFlags
;
3789 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartDeviceChange
,
3790 (unsigned long)priv
->head_note_state
,(unsigned long)pm_vars
->myCurrentState
);
3792 // can our driver switch to the new state?
3793 if ( priv
->head_note_capabilityFlags
& IOPMNotAttainable
)
3795 // no, ask the parent to do it then
3796 if ( ! priv
->we_are_root
)
3798 ask_parent(priv
->head_note_state
);
3800 // mark the change note un-actioned
3801 priv
-> head_note_flags
|= IOPMNotDone
;
3807 // is there enough power in the domain?
3808 if ( (pm_vars
->maxCapability
< priv
->head_note_state
) && (! priv
->we_are_root
) )
3810 // no, ask the parent to raise it
3811 if ( ! priv
->we_are_root
)
3813 ask_parent(priv
->head_note_state
);
3815 // no, mark the change note un-actioned
3816 priv
->head_note_flags
|= IOPMNotDone
;
3818 // till the parent raises power
3823 if ( ! priv
->initial_change
)
3825 if ( priv
->head_note_state
== pm_vars
->myCurrentState
)
3827 // we initiated a null change; forget it
3832 priv
->initial_change
= false;
3835 if ( priv
->head_note_state
< pm_vars
->myCurrentState
)
3837 // yes, in case we have to wait for acks
3838 priv
->machine_state
= kIOPM_OurChangeTellClientsPowerDown
;
3839 pm_vars
->doNotPowerDown
= false;
3841 // ask apps and kernel clients if we can drop power
3842 pm_vars
->outofbandparameter
= kNotifyApps
;
3843 if ( askChangeDown(priv
->head_note_state
) )
3845 // don't have to wait, did any clients veto?
3846 if ( pm_vars
->doNotPowerDown
)
3848 // yes, rescind the warning
3849 tellNoChangeDown(priv
->head_note_state
);
3850 // mark the change note un-actioned
3851 priv
-> head_note_flags
|= IOPMNotDone
;
3855 // no, tell'em we're dropping power
3856 OurChangeTellClientsPowerDown();
3860 // we are raising power
3861 if ( ! priv
->we_are_root
)
3863 // if this changes our power requirement, tell the parent
3864 ask_parent(priv
->head_note_state
);
3866 // in case they don't all ack
3867 priv
->machine_state
= kIOPM_OurChangeSetPowerState
;
3869 // notify interested drivers and children
3870 if ( notifyAll(true) == IOPMAckImplied
)
3872 OurChangeSetPowerState();
3878 //*********************************************************************************
3881 // Call the power domain parent to ask for a higher power state in the domain
3882 // or to suggest a lower power state.
3883 //*********************************************************************************
3885 IOReturn
IOService::ask_parent ( unsigned long requestedState
)
3889 IOPowerConnection
*connection
;
3891 unsigned long ourRequest
= pm_vars
->thePowerStates
[requestedState
].inputPowerRequirement
;
3893 if ( pm_vars
->thePowerStates
[requestedState
].capabilityFlags
& (kIOPMChildClamp
| kIOPMPreventIdleSleep
) )
3895 ourRequest
|= kIOPMPreventIdleSleep
;
3897 if ( pm_vars
->thePowerStates
[requestedState
].capabilityFlags
& (kIOPMChildClamp2
| kIOPMPreventSystemSleep
) )
3899 ourRequest
|= kIOPMPreventSystemSleep
;
3902 // is this a new desire?
3903 if ( priv
->previousRequest
== ourRequest
)
3905 // no, the parent knows already, just return
3909 if ( priv
->we_are_root
)
3913 priv
->previousRequest
= ourRequest
;
3915 iter
= getParentIterator(gIOPowerPlane
);
3919 while ( (next
= iter
->getNextObject()) )
3921 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
3923 parent
= (IOService
*)connection
->copyParentEntry(gIOPowerPlane
);
3925 if ( parent
->requestPowerDomainState(ourRequest
,connection
,IOPMLowestState
)!= IOPMNoErr
)
3927 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRequestDenied
,
3928 (unsigned long)priv
->previousRequest
,0);
3941 //*********************************************************************************
3944 // Call the controlling driver and have it change the power state of the
3945 // hardware. If it returns IOPMAckImplied, the change is complete, and
3946 // we return IOPMAckImplied. Otherwise, it will ack when the change
3947 // is done; we return IOPMWillAckLater.
3948 //*********************************************************************************
3949 IOReturn
IOService::instruct_driver ( unsigned long newState
)
3953 // can our driver switch to the desired state?
3954 if ( pm_vars
->thePowerStates
[newState
].capabilityFlags
& IOPMNotAttainable
)
3957 return IOPMAckImplied
;
3960 priv
->driver_timer
= -1;
3963 IOLockUnlock(priv
->our_lock
);
3964 OUR_PMLog( kPMLogProgramHardware
, (UInt32
) this, newState
);
3965 delay
= pm_vars
->theControllingDriver
->setPowerState( newState
,this );
3966 OUR_PMLog((UInt32
) -kPMLogProgramHardware
, (UInt32
) this, (UInt32
) delay
);
3967 IOLockLock(priv
->our_lock
);
3970 if ( delay
== IOPMAckImplied
)
3972 priv
->driver_timer
= 0;
3973 return IOPMAckImplied
;
3976 // it acked behind our back
3977 if ( priv
->driver_timer
== 0 )
3979 return IOPMAckImplied
;
3985 return IOPMAckImplied
;
3989 priv
->driver_timer
= (delay
/ ( ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
3990 return IOPMWillAckLater
;
3994 //*********************************************************************************
3997 // We are acquiring the lock we use to protect our queue head from
3998 // simutaneous access by a thread which calls acknowledgePowerStateChange
3999 // or acknowledgeSetPowerState and the ack timer expiration thread.
4000 // Return TRUE if we acquire the lock, and the queue head didn't change
4001 // while we were acquiring the lock (and maybe blocked).
4002 // If there is no queue head, or it changes while we are blocked,
4003 // return FALSE with the lock unlocked.
4004 //*********************************************************************************
4006 bool IOService::acquire_lock ( void )
4008 long current_change_note
;
4010 current_change_note
= priv
->head_note
;
4011 if ( current_change_note
== -1 ) {
4015 IOTakeLock(priv
->our_lock
);
4016 if ( current_change_note
== priv
->head_note
)
4020 // we blocked and something changed radically
4021 // so there's nothing to do any more
4022 IOUnlock(priv
->our_lock
);
4028 //*********************************************************************************
4031 // Ask registered applications and kernel clients if we can change to a lower
4034 // Subclass can override this to send a different message type. Parameter is
4035 // the destination state number.
4037 // Return true if we don't have to wait for acknowledgements
4038 //*********************************************************************************
4040 bool IOService::askChangeDown ( unsigned long stateNum
)
4042 return tellClientsWithResponse(kIOMessageCanDevicePowerOff
);
4046 //*********************************************************************************
4049 // Notify registered applications and kernel clients that we are definitely
4052 // Return true if we don't have to wait for acknowledgements
4053 //*********************************************************************************
4055 bool IOService::tellChangeDown1 ( unsigned long stateNum
)
4057 pm_vars
->outofbandparameter
= kNotifyApps
;
4058 return tellChangeDown(stateNum
);
4062 //*********************************************************************************
4065 // Notify priority clients that we are definitely dropping power.
4067 // Return true if we don't have to wait for acknowledgements
4068 //*********************************************************************************
4070 bool IOService::tellChangeDown2 ( unsigned long stateNum
)
4072 pm_vars
->outofbandparameter
= kNotifyPriority
;
4073 return tellChangeDown(stateNum
);
4077 //*********************************************************************************
4080 // Notify registered applications and kernel clients that we are definitely
4083 // Subclass can override this to send a different message type. Parameter is
4084 // the destination state number.
4086 // Return true if we don't have to wait for acknowledgements
4087 //*********************************************************************************
4089 bool IOService::tellChangeDown ( unsigned long stateNum
)
4091 return tellClientsWithResponse(kIOMessageDeviceWillPowerOff
);
4095 //*********************************************************************************
4096 // tellClientsWithResponse
4098 // Notify registered applications and kernel clients that we are definitely
4101 // Return true if we don't have to wait for acknowledgements
4102 //*********************************************************************************
4104 bool IOService::tellClientsWithResponse ( int messageType
)
4106 struct context theContext
;
4107 AbsoluteTime deadline
;
4110 pm_vars
->responseFlags
= OSArray::withCapacity( 1 );
4111 pm_vars
->serialNumber
+= 1;
4113 theContext
.responseFlags
= pm_vars
->responseFlags
;
4114 theContext
.serialNumber
= pm_vars
->serialNumber
;
4115 theContext
.flags_lock
= priv
->flags_lock
;
4116 theContext
.counter
= 1;
4117 theContext
.msgType
= messageType
;
4118 theContext
.us
= this;
4119 theContext
.maxTimeRequested
= 0;
4120 theContext
.stateNumber
= priv
->head_note_state
;
4121 theContext
.stateFlags
= priv
->head_note_capabilityFlags
;
4123 IOLockLock(priv
->flags_lock
);
4125 // position zero is false to
4126 // prevent allowCancelCommon from succeeding
4127 aBool
= OSBoolean::withBoolean(false);
4128 theContext
.responseFlags
->setObject(0,aBool
);
4130 IOLockUnlock(priv
->flags_lock
);
4132 switch ( pm_vars
->outofbandparameter
) {
4134 applyToInterested(gIOAppPowerStateInterest
,tellAppWithResponse
,(void *)&theContext
);
4135 applyToInterested(gIOGeneralInterest
,tellClientWithResponse
,(void *)&theContext
);
4137 case kNotifyPriority
:
4138 applyToInterested(gIOPriorityPowerStateInterest
,tellClientWithResponse
,(void *)&theContext
);
4142 if (! acquire_lock() )
4146 IOLockLock(priv
->flags_lock
);
4147 // now fix position zero
4148 aBool
= OSBoolean::withBoolean(true);
4149 theContext
.responseFlags
->replaceObject(0,aBool
);
4151 IOLockUnlock(priv
->flags_lock
);
4153 // do we have to wait for somebody?
4154 if ( ! checkForDone() )
4156 // yes, start the ackTimer
4157 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,theContext
.maxTimeRequested
,0);
4158 clock_interval_to_deadline(theContext
.maxTimeRequested
/ 1000, kMillisecondScale
, &deadline
);
4160 thread_call_enter_delayed(priv
->ackTimer
, deadline
);
4162 IOUnlock(priv
->our_lock
);
4166 IOUnlock(priv
->our_lock
);
4167 IOLockLock(priv
->flags_lock
);
4169 // everybody responded
4170 pm_vars
->responseFlags
->release();
4171 pm_vars
->responseFlags
= NULL
;
4172 IOLockUnlock(priv
->flags_lock
);
4178 //*********************************************************************************
4179 // tellAppWithResponse
4181 // We send a message to an application, and we expect a response, so we compute a
4182 // cookie we can identify the response with.
4183 //*********************************************************************************
4184 void tellAppWithResponse ( OSObject
* object
, void * context
)
4186 struct context
*theContext
= (struct context
*)context
;
4188 IOPMprot
*pm_vars
= theContext
->us
->pm_vars
;
4190 if( OSDynamicCast( IOService
, object
) )
4192 // Automatically 'ack' in kernel clients
4193 IOLockLock(theContext
->flags_lock
);
4194 aBool
= OSBoolean::withBoolean(true);
4195 theContext
->responseFlags
->setObject(theContext
->counter
,aBool
);
4197 IOLockUnlock(theContext
->flags_lock
);
4199 const char *who
= ((IOService
*) object
)->getName();
4200 pm_vars
->thePlatform
->PMLog(who
,
4201 kPMLogClientAcknowledge
, theContext
->msgType
, * (UInt32
*) object
);
4203 UInt32 refcon
= ((theContext
->serialNumber
& 0xFFFF)<<16)
4204 + (theContext
->counter
& 0xFFFF);
4205 IOLockLock(theContext
->flags_lock
);
4206 aBool
= OSBoolean::withBoolean(false);
4207 theContext
->responseFlags
->setObject(theContext
->counter
,aBool
);
4209 IOLockUnlock(theContext
->flags_lock
);
4211 OUR_PMLog(kPMLogAppNotify
, theContext
->msgType
, refcon
);
4212 theContext
->us
->messageClient(theContext
->msgType
,object
,(void *)refcon
);
4213 if ( theContext
->maxTimeRequested
< k30seconds
)
4215 theContext
->maxTimeRequested
= k30seconds
;
4218 theContext
->counter
+= 1;
4221 //*********************************************************************************
4222 // tellClientWithResponse
4224 // We send a message to an in-kernel client, and we expect a response, so we compute a
4225 // cookie we can identify the response with.
4226 // If it doesn't understand the notification (it is not power-management savvy)
4227 // we won't wait for it to prepare for sleep. If it tells us via a return code
4228 // in the passed struct that it is currently ready, we won't wait for it to prepare.
4229 // If it tells us via the return code in the struct that it does need time, we will chill.
4230 //*********************************************************************************
4231 void tellClientWithResponse ( OSObject
* object
, void * context
)
4233 struct context
*theContext
= (struct context
*)context
;
4234 IOPowerStateChangeNotification notify
;
4240 refcon
= ((theContext
->serialNumber
& 0xFFFF)<<16) + (theContext
->counter
& 0xFFFF);
4241 IOLockLock(theContext
->flags_lock
);
4242 aBool
= OSBoolean::withBoolean(false);
4243 theContext
->responseFlags
->setObject(theContext
->counter
,aBool
);
4245 IOLockUnlock(theContext
->flags_lock
);
4247 IOPMprot
*pm_vars
= theContext
->us
->pm_vars
;
4248 if (gIOKitDebug
& kIOLogPower
) {
4249 OUR_PMLog(kPMLogClientNotify
, refcon
, (UInt32
) theContext
->msgType
);
4250 if (OSDynamicCast(IOService
, object
)) {
4251 const char *who
= ((IOService
*) object
)->getName();
4252 pm_vars
->thePlatform
->PMLog(who
,
4253 kPMLogClientNotify
, * (UInt32
*) object
, (UInt32
) object
);
4254 } else if (OSDynamicCast(_IOServiceInterestNotifier
, object
)) {
4255 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
4256 OUR_PMLog(kPMLogClientNotify
, (UInt32
) n
->handler
, 0);
4260 notify
.powerRef
= (void *)refcon
;
4261 notify
.returnValue
= 0;
4262 notify
.stateNumber
= theContext
->stateNumber
;
4263 notify
.stateFlags
= theContext
->stateFlags
;
4264 retCode
= theContext
->us
->messageClient(theContext
->msgType
,object
,(void *)¬ify
);
4265 if ( retCode
== kIOReturnSuccess
)
4267 if ( notify
.returnValue
== 0 )
4269 // client doesn't want time to respond
4270 IOLockLock(theContext
->flags_lock
);
4271 aBool
= OSBoolean::withBoolean(true);
4272 // so set its flag true
4273 theContext
->responseFlags
->replaceObject(theContext
->counter
,aBool
);
4275 IOLockUnlock(theContext
->flags_lock
);
4276 OUR_PMLog(kPMLogClientAcknowledge
, refcon
, (UInt32
) object
);
4278 IOLockLock(theContext
->flags_lock
);
4280 // it does want time, and it hasn't responded yet
4281 theFlag
= theContext
->responseFlags
->getObject(theContext
->counter
);
4284 if ( ((OSBoolean
*)theFlag
)->isFalse() )
4286 // so note its time requirement
4287 if ( theContext
->maxTimeRequested
< notify
.returnValue
)
4289 theContext
->maxTimeRequested
= notify
.returnValue
;
4293 IOLockUnlock(theContext
->flags_lock
);
4296 OUR_PMLog(kPMLogClientAcknowledge
, refcon
, 0);
4297 // not a client of ours
4298 IOLockLock(theContext
->flags_lock
);
4299 // so we won't be waiting for response
4300 aBool
= OSBoolean::withBoolean(true);
4301 theContext
->responseFlags
->replaceObject(theContext
->counter
,aBool
);
4303 IOLockUnlock(theContext
->flags_lock
);
4305 theContext
->counter
+= 1;
4309 //*********************************************************************************
4312 // Notify registered applications and kernel clients that we are not
4315 // Subclass can override this to send a different message type. Parameter is
4316 // the aborted destination state number.
4317 //*********************************************************************************
4319 void IOService::tellNoChangeDown ( unsigned long )
4321 return tellClients(kIOMessageDeviceWillNotPowerOff
);
4325 //*********************************************************************************
4328 // Notify registered applications and kernel clients that we are raising power.
4330 // Subclass can override this to send a different message type. Parameter is
4331 // the aborted destination state number.
4332 //*********************************************************************************
4334 void IOService::tellChangeUp ( unsigned long )
4336 return tellClients(kIOMessageDeviceHasPoweredOn
);
4340 //*********************************************************************************
4343 // Notify registered applications and kernel clients of something.
4344 //*********************************************************************************
4346 void IOService::tellClients ( int messageType
)
4348 struct context theContext
;
4350 theContext
.msgType
= messageType
;
4351 theContext
.us
= this;
4352 theContext
.stateNumber
= priv
->head_note_state
;
4353 theContext
.stateFlags
= priv
->head_note_capabilityFlags
;
4355 applyToInterested(gIOAppPowerStateInterest
,tellClient
,(void *)&theContext
);
4356 applyToInterested(gIOGeneralInterest
,tellClient
,(void *)&theContext
);
4360 //*********************************************************************************
4363 // Notify a registered application or kernel client of something.
4364 //*********************************************************************************
4365 void tellClient ( OSObject
* object
, void * context
)
4367 struct context
*theContext
= (struct context
*)context
;
4368 IOPowerStateChangeNotification notify
;
4370 notify
.powerRef
= (void *) 0;
4371 notify
.returnValue
= 0;
4372 notify
.stateNumber
= theContext
->stateNumber
;
4373 notify
.stateFlags
= theContext
->stateFlags
;
4375 theContext
->us
->messageClient(theContext
->msgType
,object
, ¬ify
);
4379 // **********************************************************************************
4382 // **********************************************************************************
4383 bool IOService::checkForDone ( void )
4388 IOLockLock(priv
->flags_lock
);
4389 if ( pm_vars
->responseFlags
== NULL
)
4391 IOLockUnlock(priv
->flags_lock
);
4395 for ( i
= 0; ; i
++ )
4397 theFlag
= pm_vars
->responseFlags
->getObject(i
);
4398 if ( theFlag
== NULL
)
4402 if ( ((OSBoolean
*)theFlag
)->isFalse() )
4404 IOLockUnlock(priv
->flags_lock
);
4408 IOLockUnlock(priv
->flags_lock
);
4413 // **********************************************************************************
4416 // **********************************************************************************
4417 bool IOService::responseValid ( unsigned long x
)
4419 UInt16 serialComponent
;
4420 UInt16 ordinalComponent
;
4422 unsigned long refcon
= (unsigned long)x
;
4425 serialComponent
= (refcon
>>16) & 0xFFFF;
4426 ordinalComponent
= refcon
& 0xFFFF;
4428 if ( serialComponent
!= pm_vars
->serialNumber
)
4433 IOLockLock(priv
->flags_lock
);
4434 if ( pm_vars
->responseFlags
== NULL
)
4436 IOLockUnlock(priv
->flags_lock
);
4440 theFlag
= pm_vars
->responseFlags
->getObject(ordinalComponent
);
4444 IOLockUnlock(priv
->flags_lock
);
4448 if ( ((OSBoolean
*)theFlag
)->isFalse() )
4450 aBool
= OSBoolean::withBoolean(true);
4451 pm_vars
->responseFlags
->replaceObject(ordinalComponent
,aBool
);
4455 IOLockUnlock(priv
->flags_lock
);
4460 // **********************************************************************************
4463 // Our power state is about to lower, and we have notified applications
4464 // and kernel clients, and one of them has acknowledged. If this is the last to do
4465 // so, and all acknowledgements are positive, we continue with the power change.
4467 // We serialize this processing with timer expiration with a command gate on the
4468 // power management workloop, which the timer expiration is command gated to as well.
4469 // **********************************************************************************
4470 IOReturn
IOService::allowPowerChange ( unsigned long refcon
)
4472 if ( ! initialized
)
4475 return kIOReturnSuccess
;
4478 return pm_vars
->PMcommandGate
->runAction(serializedAllowPowerChange
,(void *)refcon
);
4482 IOReturn
serializedAllowPowerChange ( OSObject
*owner
, void * refcon
, void *, void *, void *)
4484 return ((IOService
*)owner
)->serializedAllowPowerChange2((unsigned long)refcon
);
4487 IOReturn
IOService::serializedAllowPowerChange2 ( unsigned long refcon
)
4490 if ( ! responseValid(refcon
) )
4492 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr5
,refcon
,0);
4494 return kIOReturnSuccess
;
4496 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientAcknowledge
,refcon
,0);
4498 return allowCancelCommon();
4502 // **********************************************************************************
4503 // cancelPowerChange
4505 // Our power state is about to lower, and we have notified applications
4506 // and kernel clients, and one of them has vetoed the change. If this is the last
4507 // client to respond, we abandon the power change.
4509 // We serialize this processing with timer expiration with a command gate on the
4510 // power management workloop, which the timer expiration is command gated to as well.
4511 // **********************************************************************************
4512 IOReturn
IOService::cancelPowerChange ( unsigned long refcon
)
4514 if ( ! initialized
)
4517 return kIOReturnSuccess
;
4520 return pm_vars
->PMcommandGate
->runAction(serializedCancelPowerChange
,(void *)refcon
);
4524 IOReturn
serializedCancelPowerChange ( OSObject
*owner
, void * refcon
, void *, void *, void *)
4526 return ((IOService
*)owner
)->serializedCancelPowerChange2((unsigned long)refcon
);
4529 IOReturn
IOService::serializedCancelPowerChange2 ( unsigned long refcon
)
4532 if ( ! responseValid(refcon
) )
4534 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr5
,refcon
,0);
4536 return kIOReturnSuccess
;
4538 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientCancel
,refcon
,0);
4540 pm_vars
->doNotPowerDown
= true;
4542 return allowCancelCommon();
4546 // **********************************************************************************
4547 // allowCancelCommon
4549 // **********************************************************************************
4550 IOReturn
IOService::allowCancelCommon ( void )
4552 if (! acquire_lock() )
4554 return kIOReturnSuccess
;
4557 // is this the last response?
4558 if ( checkForDone() )
4560 // yes, stop the timer
4562 IOUnlock(priv
->our_lock
);
4563 IOLockLock(priv
->flags_lock
);
4564 if ( pm_vars
->responseFlags
)
4566 pm_vars
->responseFlags
->release();
4567 pm_vars
->responseFlags
= NULL
;
4569 IOLockUnlock(priv
->flags_lock
);
4570 switch (priv
->machine_state
) {
4571 case kIOPM_OurChangeTellClientsPowerDown
:
4572 // our change, was it vetoed?
4573 if ( ! pm_vars
->doNotPowerDown
)
4575 // no, we can continue
4576 OurChangeTellClientsPowerDown();
4578 // yes, rescind the warning
4579 tellNoChangeDown(priv
->head_note_state
);
4580 // mark the change note un-actioned
4581 priv
->head_note_flags
|= IOPMNotDone
;
4587 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
4588 OurChangeTellPriorityClientsPowerDown();
4590 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
4591 // our change, continue
4592 OurChangeNotifyInterestedDriversWillChange();
4594 case kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate
:
4595 // parent change, continue
4596 ParentDownTellPriorityClientsPowerDown_Delayed();
4598 case kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
:
4599 // parent change, continue
4600 ParentDownNotifyInterestedDriversWillChange_Delayed();
4605 IOUnlock(priv
->our_lock
);
4608 return kIOReturnSuccess
;
4613 //*********************************************************************************
4614 // c_PM_clamp_Timer_Expired (C Func)
4616 // Called when our clamp timer expires...we will call the object method.
4617 //*********************************************************************************
4619 static void c_PM_Clamp_Timer_Expired (OSObject
* client
, IOTimerEventSource
*)
4622 ((IOService
*)client
)->PM_Clamp_Timer_Expired ();
4627 //*********************************************************************************
4628 // PM_Clamp_Timer_Expired
4630 // called when clamp timer expires...set power state to 0.
4631 //*********************************************************************************
4633 void IOService::PM_Clamp_Timer_Expired (void)
4636 if ( ! initialized
)
4642 changePowerStateToPriv (0);
4646 //******************************************************************************
4649 // Set to highest available power state for a minimum of duration milliseconds
4650 //******************************************************************************
4652 #define kFiveMinutesInNanoSeconds (300 * NSEC_PER_SEC)
4654 void IOService::clampPowerOn (unsigned long duration
)
4657 changePowerStateToPriv (pm_vars
->theNumberOfPowerStates
-1);
4659 if ( priv
->clampTimerEventSrc
== NULL
) {
4660 priv
->clampTimerEventSrc
= IOTimerEventSource::timerEventSource(this,
4661 c_PM_Clamp_Timer_Expired
);
4663 IOWorkLoop
* workLoop
= getPMworkloop ();
4665 if ( !priv
->clampTimerEventSrc
|| !workLoop
||
4666 ( workLoop
->addEventSource( priv
->clampTimerEventSrc
) != kIOReturnSuccess
) ) {
4671 priv
->clampTimerEventSrc
->setTimeout(300*USEC_PER_SEC
, USEC_PER_SEC
);
4675 //*********************************************************************************
4678 // Does nothing here. This should be implemented in a subclass driver.
4679 //*********************************************************************************
4681 IOReturn
IOService::setPowerState ( unsigned long powerStateOrdinal
, IOService
* whatDevice
)
4687 //*********************************************************************************
4688 // maxCapabilityForDomainState
4690 // Finds the highest power state in the array whose input power
4691 // requirement is equal to the input parameter. Where a more intelligent
4692 // decision is possible, override this in the subclassed driver.
4693 //*********************************************************************************
4695 unsigned long IOService::maxCapabilityForDomainState ( IOPMPowerFlags domainState
)
4699 if (pm_vars
->theNumberOfPowerStates
== 0 )
4703 for ( i
= (pm_vars
->theNumberOfPowerStates
)-1; i
>= 0; i
-- )
4705 if ( (domainState
& pm_vars
->thePowerStates
[i
].inputPowerRequirement
) == pm_vars
->thePowerStates
[i
].inputPowerRequirement
)
4714 //*********************************************************************************
4715 // initialPowerStateForDomainState
4717 // Finds the highest power state in the array whose input power
4718 // requirement is equal to the input parameter. Where a more intelligent
4719 // decision is possible, override this in the subclassed driver.
4720 //*********************************************************************************
4722 unsigned long IOService::initialPowerStateForDomainState ( IOPMPowerFlags domainState
)
4726 if (pm_vars
->theNumberOfPowerStates
== 0 )
4730 for ( i
= (pm_vars
->theNumberOfPowerStates
)-1; i
>= 0; i
-- )
4732 if ( (domainState
& pm_vars
->thePowerStates
[i
].inputPowerRequirement
) == pm_vars
->thePowerStates
[i
].inputPowerRequirement
)
4741 //*********************************************************************************
4742 // powerStateForDomainState
4744 // Finds the highest power state in the array whose input power
4745 // requirement is equal to the input parameter. Where a more intelligent
4746 // decision is possible, override this in the subclassed driver.
4747 //*********************************************************************************
4749 unsigned long IOService::powerStateForDomainState ( IOPMPowerFlags domainState
)
4753 if (pm_vars
->theNumberOfPowerStates
== 0 )
4757 for ( i
= (pm_vars
->theNumberOfPowerStates
)-1; i
>= 0; i
-- )
4759 if ( (domainState
& pm_vars
->thePowerStates
[i
].inputPowerRequirement
) == pm_vars
->thePowerStates
[i
].inputPowerRequirement
)
4768 //*********************************************************************************
4771 // Does nothing here. This should be implemented in a subclass driver.
4772 //*********************************************************************************
4774 bool IOService::didYouWakeSystem ( void )
4780 //*********************************************************************************
4781 // powerStateWillChangeTo
4783 // Does nothing here. This should be implemented in a subclass driver.
4784 //*********************************************************************************
4786 IOReturn
IOService::powerStateWillChangeTo ( IOPMPowerFlags
, unsigned long, IOService
*)
4792 //*********************************************************************************
4793 // powerStateDidChangeTo
4795 // Does nothing here. This should be implemented in a subclass driver.
4796 //*********************************************************************************
4798 IOReturn
IOService::powerStateDidChangeTo ( IOPMPowerFlags
, unsigned long, IOService
*)
4804 //*********************************************************************************
4807 // Does nothing here. This should be implemented in a subclass policy-maker.
4808 //*********************************************************************************
4810 void IOService::powerChangeDone ( unsigned long )
4815 //*********************************************************************************
4818 // Does nothing here. This should be implemented in a subclass driver.
4819 //*********************************************************************************
4821 IOReturn
IOService::newTemperature ( long currentTemp
, IOService
* whichZone
)
4829 #define super OSObject
4831 OSDefineMetaClassAndStructors(IOPMprot
, OSObject
)
4832 //*********************************************************************************
4835 // Serialize protected instance variables for debug output.
4836 //*********************************************************************************
4837 bool IOPMprot::serialize(OSSerialize
*s
) const
4839 OSString
* theOSString
;
4846 // estimate how many bytes we need to present all power states
4847 buf_size
= 150 // beginning and end of string
4848 + (275 * (int)theNumberOfPowerStates
) // size per state
4849 + 100; // extra room just for kicks
4851 buffer
= ptr
= IONew(char, buf_size
);
4855 ptr
+= sprintf(ptr
,"{ theNumberOfPowerStates = %d, ",(unsigned int)theNumberOfPowerStates
);
4857 if ( theNumberOfPowerStates
!= 0 ) {
4858 ptr
+= sprintf(ptr
,"version %d, ",(unsigned int)thePowerStates
[0].version
);
4861 if ( theNumberOfPowerStates
!= 0 ) {
4862 for ( i
= 0; i
< (int)theNumberOfPowerStates
; i
++ ) {
4863 ptr
+= sprintf(ptr
, "power state %d = { ",i
);
4864 ptr
+= sprintf(ptr
,"capabilityFlags %08x, ",(unsigned int)thePowerStates
[i
].capabilityFlags
);
4865 ptr
+= sprintf(ptr
,"outputPowerCharacter %08x, ",(unsigned int)thePowerStates
[i
].outputPowerCharacter
);
4866 ptr
+= sprintf(ptr
,"inputPowerRequirement %08x, ",(unsigned int)thePowerStates
[i
].inputPowerRequirement
);
4867 ptr
+= sprintf(ptr
,"staticPower %d, ",(unsigned int)thePowerStates
[i
].staticPower
);
4868 ptr
+= sprintf(ptr
,"unbudgetedPower %d, ",(unsigned int)thePowerStates
[i
].unbudgetedPower
);
4869 ptr
+= sprintf(ptr
,"powerToAttain %d, ",(unsigned int)thePowerStates
[i
].powerToAttain
);
4870 ptr
+= sprintf(ptr
,"timeToAttain %d, ",(unsigned int)thePowerStates
[i
].timeToAttain
);
4871 ptr
+= sprintf(ptr
,"settleUpTime %d, ",(unsigned int)thePowerStates
[i
].settleUpTime
);
4872 ptr
+= sprintf(ptr
,"timeToLower %d, ",(unsigned int)thePowerStates
[i
].timeToLower
);
4873 ptr
+= sprintf(ptr
,"settleDownTime %d, ",(unsigned int)thePowerStates
[i
].settleDownTime
);
4874 ptr
+= sprintf(ptr
,"powerDomainBudget %d }, ",(unsigned int)thePowerStates
[i
].powerDomainBudget
);
4878 ptr
+= sprintf(ptr
,"aggressiveness = %d, ",(unsigned int)aggressiveness
);
4879 ptr
+= sprintf(ptr
,"myCurrentState = %d, ",(unsigned int)myCurrentState
);
4880 ptr
+= sprintf(ptr
,"parentsCurrentPowerFlags = %08x, ",(unsigned int)parentsCurrentPowerFlags
);
4881 ptr
+= sprintf(ptr
,"maxCapability = %d }",(unsigned int)maxCapability
);
4883 theOSString
= OSString::withCString(buffer
);
4884 rtn_code
= theOSString
->serialize(s
);
4885 theOSString
->release();
4886 IODelete(buffer
, char, buf_size
);
4893 #define super OSObject
4895 OSDefineMetaClassAndStructors(IOPMpriv
, OSObject
)
4896 //*********************************************************************************
4899 // Serialize private instance variables for debug output.
4900 //*********************************************************************************
4901 bool IOPMpriv::serialize(OSSerialize
*s
) const
4903 OSString
* theOSString
;
4907 IOPMinformee
* nextObject
;
4909 buffer
= ptr
= IONew(char, 2000);
4913 ptr
+= sprintf(ptr
,"{ this object = %08x",(unsigned int)owner
);
4914 if ( we_are_root
) {
4915 ptr
+= sprintf(ptr
," (root)");
4917 ptr
+= sprintf(ptr
,", ");
4919 nextObject
= interestedDrivers
->firstInList(); // display interested drivers
4920 while ( nextObject
!= NULL
) {
4921 ptr
+= sprintf(ptr
,"interested driver = %08x, ",(unsigned int)nextObject
->whatObject
);
4922 nextObject
= interestedDrivers
->nextInList(nextObject
);
4925 if ( machine_state
!= kIOPM_Finished
) {
4926 ptr
+= sprintf(ptr
,"machine_state = %d, ",(unsigned int)machine_state
);
4927 ptr
+= sprintf(ptr
,"driver_timer = %d, ",(unsigned int)driver_timer
);
4928 ptr
+= sprintf(ptr
,"settle_time = %d, ",(unsigned int)settle_time
);
4929 ptr
+= sprintf(ptr
,"head_note_flags = %08x, ",(unsigned int)head_note_flags
);
4930 ptr
+= sprintf(ptr
,"head_note_state = %d, ",(unsigned int)head_note_state
);
4931 ptr
+= sprintf(ptr
,"head_note_outputFlags = %08x, ",(unsigned int)head_note_outputFlags
);
4932 ptr
+= sprintf(ptr
,"head_note_domainState = %08x, ",(unsigned int)head_note_domainState
);
4933 ptr
+= sprintf(ptr
,"head_note_capabilityFlags = %08x, ",(unsigned int)head_note_capabilityFlags
);
4934 ptr
+= sprintf(ptr
,"head_note_pendingAcks = %d, ",(unsigned int)head_note_pendingAcks
);
4937 if ( device_overrides
) {
4938 ptr
+= sprintf(ptr
,"device overrides, ");
4940 ptr
+= sprintf(ptr
,"driverDesire = %d, ",(unsigned int)driverDesire
);
4941 ptr
+= sprintf(ptr
,"deviceDesire = %d, ",(unsigned int)deviceDesire
);
4942 ptr
+= sprintf(ptr
,"ourDesiredPowerState = %d, ",(unsigned int)ourDesiredPowerState
);
4943 ptr
+= sprintf(ptr
,"previousRequest = %d }",(unsigned int)previousRequest
);
4945 theOSString
= OSString::withCString(buffer
);
4946 rtn_code
= theOSString
->serialize(s
);
4947 theOSString
->release();
4948 IODelete(buffer
, char, 2000);