2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <IOKit/assert.h>
31 #include <IOKit/IOCommandGate.h>
32 #include <IOKit/IOKitDebug.h>
33 #include <IOKit/IOLib.h>
34 #include <IOKit/IOMessage.h>
35 #include <IOKit/IOPlatformExpert.h>
36 #include <IOKit/IOService.h>
37 #include <IOKit/IOTimerEventSource.h>
38 #include <IOKit/IOWorkLoop.h>
40 #include <IOKit/pwr_mgt/IOPMchangeNoteList.h>
41 #include <IOKit/pwr_mgt/IOPMinformee.h>
42 #include <IOKit/pwr_mgt/IOPMinformeeList.h>
43 #include <IOKit/pwr_mgt/IOPMlog.h>
44 #include <IOKit/pwr_mgt/IOPowerConnection.h>
45 #include <IOKit/pwr_mgt/RootDomain.h>
47 // Required for notification instrumentation
48 #include "IOServicePrivate.h"
50 #define super IORegistryEntry
52 #define OUR_PMLog(t, a, b) \
53 do { pm_vars->thePlatform->PMLog(pm_vars->ourName, t, a, b); } while(0)
55 static void ack_timer_expired(thread_call_param_t
);
56 static void settle_timer_expired(thread_call_param_t
);
57 static void PM_idle_timer_expired(OSObject
*, IOTimerEventSource
*);
58 void tellAppWithResponse ( OSObject
* object
, void * context
);
59 void tellClientWithResponse ( OSObject
* object
, void * context
);
60 void tellClient ( OSObject
* object
, void * context
);
61 IOReturn
serializedAllowPowerChange ( OSObject
*, void *, void *, void *, void *);
62 IOReturn
serializedCancelPowerChange ( OSObject
*, void *, void *, void *, void *);
64 extern const IORegistryPlane
* gIOPowerPlane
;
67 // and there's 1000 nanoseconds in a microsecond:
68 #define ns_per_us 1000
71 // The current change note is processed by a state machine.
72 // Inputs are acks from interested parties, ack from the controlling driver,
73 // ack timeouts, settle timeout, and powerStateDidChange from the parent.
74 // These are the states:
76 kIOPM_OurChangeTellClientsPowerDown
= 1,
77 kIOPM_OurChangeTellPriorityClientsPowerDown
,
78 kIOPM_OurChangeNotifyInterestedDriversWillChange
,
79 kIOPM_OurChangeSetPowerState
,
80 kIOPM_OurChangeWaitForPowerSettle
,
81 kIOPM_OurChangeNotifyInterestedDriversDidChange
,
82 kIOPM_OurChangeFinish
,
83 kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate
,
84 kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
,
85 kIOPM_ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate
,
86 kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
,
87 kIOPM_ParentDownSetPowerState_Delayed
,
88 kIOPM_ParentDownWaitForPowerSettle_Delayed
,
89 kIOPM_ParentDownAcknowledgeChange_Delayed
,
90 kIOPM_ParentUpSetPowerState_Delayed
,
91 kIOPM_ParentUpSetPowerState_Immediate
,
92 kIOPM_ParentUpWaitForSettleTime_Delayed
,
93 kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed
,
94 kIOPM_ParentUpAcknowledgePowerChange_Delayed
,
98 // values of outofbandparameter
105 // used for applyToInterested
107 OSArray
* responseFlags
;
110 UInt32 maxTimeRequested
;
114 unsigned long stateNumber
;
115 IOPMPowerFlags stateFlags
;
118 // five minutes in microseconds
119 #define FIVE_MINUTES 5*60*1000000
120 #define k30seconds 30*1000000
123 There are two different kinds of power state changes. One is initiated by a subclassed device object which has either
124 decided to change power state, or its controlling driver has suggested it, or some other driver wants to use the
125 idle device and has asked it to become usable. The second kind of power state change is initiated by the power
126 domain parent. The two are handled slightly differently.
128 There is a queue of so-called change notifications, or change notes for short. Usually the queue is empty, and when
129 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
130 at one time, a queue is implemented. Example: the subclass device decides it's idle and initiates a change to a lower
131 power state. This causes interested parties to be notified, but they don't all acknowledge right away. This causes the
132 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
133 wants to raise power back up again. This change can't be started, however, because the previous one isn't complete yet,
134 so the second one waits in the queue. During this time, the parent decides to lower or raise the power state of the entire
135 power domain and notifies the device, and that notification goes into the queue, too, and can't be actioned until the
138 This is how a power change initiated by the subclass device is handled:
139 First, all interested parties are notified of the change via their powerStateWillChangeTo method. If they all don't
140 acknowledge via return code, then we have to wait. If they do, or when they finally all acknowledge via our
141 acknowledgePowerChange method, then we can continue. We call the controlling driver, instructing it to change to
142 the new state. Then we wait for power to settle. If there is no settling-time, or after it has passed, we notify
143 interested parties again, this time via their powerStateDidChangeTo methods. When they have all acked, we're done.
144 If we lowered power and don't need the power domain to be in its current power state, we suggest to the parent that
145 it lower the power domain state.
147 This is how a change to a lower power domain state initiated by the parent is handled:
148 First, we figure out what power state we will be in when the new domain state is reached. Then all interested parties are
149 notified that we are moving to that new state. When they have acknowledged, we call the controlling driver to assume
150 that state and we wait for power to settle. Then we acknowledge our preparedness to our parent. When all its interested
151 parties have acknowledged, it lowers power and then notifies its interested parties again. When we get this call, we notify
152 our interested parties that the power state has changed, and when they have all acknowledged, we're done.
154 This is how a change to a higher power domain state initiated by the parent is handled:
155 We figure out what power state we will be in when the new domain state is reached. If it is different from our current
156 state we acknowledge the parent. When all the parent's interested parties have acknowledged, it raises power in the
157 domain and waits for power to settle. Then it notifies everyone that the new state has been reached. When we get this call,
158 we call the controlling driver, instructing it to assume the new state, and wait for power to settle. Then we notify our interested
159 parties. When they all acknowledge we are done.
161 In either of the two cases above, it is possible that we will not be changing state even though the domain is. Examples:
162 A change to a lower domain state may not affect us because we are already in a low enough state, and
163 We will not take advantage of a change to a higher domain state, because we have no need of the higher power.
164 In such a case, there is nothing to do but acknowledge the parent. So when the parent calls our powerDomainWillChange
165 method, and we decide that we will not be changing state, we merely acknowledge the parent, via return code, and wait.
166 When the parent subsequently calls powerStateDidChange, we acknowledge again via return code, and the change is complete.
168 Power state changes are processed in a state machine, and since there are four varieties of power state changes, there are
169 four major paths through the state machine:
171 The fourth is nearly trivial. In this path, the parent is changing the domain state, but we are not changing the device state.
172 The change starts when the parent calls powerDomainWillChange. All we do is acknowledge the parent.
173 When the parent calls powerStateDidChange, we acknowledge the parent again, and we're done.
175 The first is fairly simple. It starts when a power domain child calls requestPowerDomainState and we decide to change power states
176 to accomodate the child, or if our power-controlling driver calls changePowerStateTo, or if some other driver which is using our
177 device calls makeUsable, or if a subclassed object calls changePowerStateToPriv. These are all power changes initiated by us, not
178 forced upon us by the parent. We start by notifying interested parties. If they all acknowledge via return code, we can go
179 on to state "OurChangeSetPowerState". Otherwise, we start the ack timer and wait for the stragglers to acknowlege by calling
180 acknowledgePowerChange. We move on to state "OurChangeSetPowerState" when all the stragglers have acknowledged,
181 or when the ack timer expires on all those which didn't acknowledge. In "OurChangeSetPowerState" we call the power-controlling
182 driver to change the power state of the hardware. If it returns saying it has done so, we go on to state "OurChangeWaitForPowerSettle".
183 Otherwise, we have to wait for it, so we set the ack timer and wait. When it calls acknowledgeSetPowerState, or when the
184 ack timer expires, we go on. In "OurChangeWaitForPowerSettle", we look in the power state array to see if there is any settle time required
185 when changing from our current state to the new state. If not, we go right away to "OurChangeNotifyInterestedDriversDidChange". Otherwise, we
186 set the settle timer and wait. When it expires, we move on. In "OurChangeNotifyInterestedDriversDidChange" state, we notify all our interested parties
187 via their powerStateDidChange methods that we have finished changing power state. If they all acknowledge via return
188 code, we move on to "OurChangeFinish". Otherwise we set the ack timer and wait. When they have all acknowledged, or
189 when the ack timer has expired for those that didn't, we move on to "OurChangeFinish", where we remove the used
190 change note from the head of the queue and start the next one if one exists.
192 Parent-initiated changes are more complex in the state machine. First, power going up and power going down are handled
193 differently, so they have different paths throught the state machine. Second, we can acknowledge the parent's notification
194 in two different ways, so each of the parent paths is really two.
196 When the parent calls our powerDomainWillChange method, notifying us that it will lower power in the domain, we decide
197 what state that will put our device in. Then we embark on the state machine path "IOPMParentDownSetPowerState_Immediate"
198 and "kIOPM_ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate", in which we notify interested parties of the upcoming change, instruct our driver to make
199 the change, check for settle time, and notify interested parties of the completed change. If we get to the end of this path without
200 stalling due to an interested party which didn't acknowledge via return code, due to the controlling driver not able to change
201 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.
202 If we do stall in any of those states, we return IOPMWillAckLater to the parent and enter the parallel path "kIOPM_ParentDownSetPowerState_Delayed"
203 "kIOPM_ParentDownWaitForPowerSettle_Delayed", and "kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed", where we continue with the same processing, except that at the end we
204 acknowledge the parent explicitly via acknowledgePowerChange, and we're done with the change.
205 Then when the parent calls us at powerStateDidChange we acknowledging via return code, because we have already made
206 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.
208 The case of the parent raising power in the domain is handled similarly in that there are parallel paths, one for no-stall
209 that ends in implicit acknowleging the parent, and one that has stalled at least once that ends in explicit acknowledging
210 the parent. This case is different, though in that our device changes state in the second half, after the parent calls
211 powerStateDidChange rather than before, as in the power-lowering case.
213 When the parent calls our powerDomainWillChange method, notifying us that it will raise power in the domain, we acknowledge
214 via return code, because there's really nothing we can do until the power is actually raised in the domain.
215 When the parent calls us at powerStateDidChange, we start by notifying our interested parties. If they all acknowledge via return code,
216 we go on to" kIOPM_ParentUpSetPowerState_Immediate" to instruct the driver to raise its power level. After that, we check for any
217 necessary settling time in "IOPMParentUpWaitForSettleTime_Immediate", and we notify all interested parties that power has changed
218 in "IOPMParentUpNotifyInterestedDriversDidChange_Immediate". If none of these operations stall, we acknowledge the parent via return code, release
219 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",
220 "kIOPM_ParentUpWaitForSettleTime_Delayed", "kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed", and "kIOPM_ParentUpAcknowledgePowerChange_Delayed", which ends with
221 our explicit acknowledgement to the parent.
226 const char priv_key
[ ] = "Power Management private data";
227 const char prot_key
[ ] = "Power Management protected data";
230 void IOService::PMinit ( void )
232 if ( ! initialized
) {
234 // make space for our variables
235 pm_vars
= new IOPMprot
;
241 // add pm_vars & priv to the properties
242 setProperty(prot_key
, (OSObject
*) pm_vars
);
243 setProperty(priv_key
, (OSObject
*) priv
);
245 // then initialize them
247 pm_vars
->theNumberOfPowerStates
= 0;
248 priv
->we_are_root
= false;
249 pm_vars
->theControllingDriver
= NULL
;
250 priv
->our_lock
= IOLockAlloc();
251 priv
->flags_lock
= IOLockAlloc();
252 priv
->queue_lock
= IOLockAlloc();
253 pm_vars
->childLock
= IOLockAlloc();
254 pm_vars
->parentLock
= IOLockAlloc();
255 priv
->interestedDrivers
= new IOPMinformeeList
;
256 priv
->interestedDrivers
->initialize();
257 priv
->changeList
= new IOPMchangeNoteList
;
258 priv
->changeList
->initialize();
259 pm_vars
->aggressiveness
= 0;
260 for (unsigned int i
= 0; i
<= kMaxType
; i
++)
262 pm_vars
->current_aggressiveness_values
[i
] = 0;
263 pm_vars
->current_aggressiveness_valid
[i
] = false;
265 pm_vars
->myCurrentState
= 0;
266 priv
->imminentState
= 0;
267 priv
->ourDesiredPowerState
= 0;
268 pm_vars
->parentsCurrentPowerFlags
= 0;
269 pm_vars
->maxCapability
= 0;
270 priv
->driverDesire
= 0;
271 priv
->deviceDesire
= 0;
272 priv
->initial_change
= true;
273 priv
->need_to_become_usable
= false;
274 priv
->previousRequest
= 0;
275 priv
->device_overrides
= false;
276 priv
->machine_state
= kIOPM_Finished
;
277 priv
->timerEventSrc
= NULL
;
278 priv
->clampTimerEventSrc
= NULL
;
279 pm_vars
->PMworkloop
= NULL
;
280 priv
->activityLock
= NULL
;
281 pm_vars
->ourName
= getName();
282 pm_vars
->thePlatform
= getPlatform();
283 pm_vars
->parentsKnowState
= false;
284 assert( pm_vars
->thePlatform
!= 0 );
285 priv
->clampOn
= false;
286 pm_vars
->serialNumber
= 0;
287 pm_vars
->responseFlags
= NULL
;
288 pm_vars
->doNotPowerDown
= true;
289 pm_vars
->PMcommandGate
= NULL
;
290 priv
->ackTimer
= thread_call_allocate((thread_call_func_t
)ack_timer_expired
, (thread_call_param_t
)this);
291 priv
->settleTimer
= thread_call_allocate((thread_call_func_t
)settle_timer_expired
, (thread_call_param_t
)this);
297 //*********************************************************************************
300 // Free up the data created in PMinit, if it exists.
301 //*********************************************************************************
302 void IOService::PMfree ( void )
305 if ( priv
->clampTimerEventSrc
!= NULL
) {
306 getPMworkloop()->removeEventSource(priv
->clampTimerEventSrc
);
307 priv
->clampTimerEventSrc
->release();
308 priv
->clampTimerEventSrc
= NULL
;
310 if ( priv
->timerEventSrc
!= NULL
) {
311 pm_vars
->PMworkloop
->removeEventSource(priv
->timerEventSrc
);
312 priv
->timerEventSrc
->release();
313 priv
->timerEventSrc
= NULL
;
315 if ( priv
->settleTimer
) {
316 thread_call_cancel(priv
->settleTimer
);
317 thread_call_free(priv
->settleTimer
);
318 priv
->settleTimer
= NULL
;
320 if ( priv
->ackTimer
) {
321 thread_call_cancel(priv
->ackTimer
);
322 thread_call_free(priv
->ackTimer
);
323 priv
->ackTimer
= NULL
;
325 if ( priv
->our_lock
) {
326 IOLockFree(priv
->our_lock
);
327 priv
->our_lock
= NULL
;
329 if ( priv
->flags_lock
) {
330 IOLockFree(priv
->flags_lock
);
331 priv
->flags_lock
= NULL
;
333 if ( priv
->activityLock
) {
334 IOLockFree(priv
->activityLock
);
335 priv
->activityLock
= NULL
;
337 priv
->interestedDrivers
->release();
338 priv
->changeList
->release();
339 // remove instance variables
344 if ( pm_vars
->PMcommandGate
) {
345 if(pm_vars
->PMworkloop
)
346 pm_vars
->PMworkloop
->removeEventSource(pm_vars
->PMcommandGate
);
347 pm_vars
->PMcommandGate
->release();
348 pm_vars
->PMcommandGate
= NULL
;
350 if ( pm_vars
->PMworkloop
) {
351 // The work loop object returned from getPMworkLoop() is
352 // never retained, therefore it should not be released.
353 // pm_vars->PMworkloop->release();
354 pm_vars
->PMworkloop
= NULL
;
356 if ( pm_vars
->responseFlags
) {
357 pm_vars
->responseFlags
->release();
358 pm_vars
->responseFlags
= NULL
;
360 // remove instance variables
366 //*********************************************************************************
369 // Disconnect the node from its parents and children in the Power Plane.
370 //*********************************************************************************
371 void IOService::PMstop ( void )
375 IOPowerConnection
* connection
;
376 IOService
* theChild
;
377 IOService
* theParent
;
379 // remove the properties
380 removeProperty(prot_key
);
381 removeProperty(priv_key
);
384 iter
= getParentIterator(gIOPowerPlane
);
388 while ( (next
= iter
->getNextObject()) )
390 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
392 theParent
= (IOService
*)connection
->copyParentEntry(gIOPowerPlane
);
395 theParent
->removePowerChild(connection
);
396 theParent
->release();
403 // detach IOConnections
404 detachAbove( gIOPowerPlane
);
408 // no more power state changes
409 pm_vars
->parentsKnowState
= false;
413 iter
= getChildIterator(gIOPowerPlane
);
417 while ( (next
= iter
->getNextObject()) )
419 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
421 theChild
= ((IOService
*)(connection
->copyChildEntry(gIOPowerPlane
)));
424 // detach nub from child
425 connection
->detachFromChild(theChild
,gIOPowerPlane
);
428 // detach us from nub
429 detachFromChild(connection
,gIOPowerPlane
);
435 // Remove all interested drivers from the list, including the power
436 // controlling driver.
438 // Usually, the controlling driver and the policy-maker functionality
439 // are implemented by the same object, and without the deregistration,
440 // the object will be holding an extra retain on itself, and cannot
443 if ( priv
&& priv
->interestedDrivers
)
445 IOPMinformee
* informee
;
447 while (( informee
= priv
->interestedDrivers
->firstInList() ))
448 deRegisterInterestedDriver( informee
->whatObject
);
453 //*********************************************************************************
456 // A policy-maker calls its nub here when initializing, to be attached into
457 // the power management hierarchy. The default function is to call the
458 // platform expert, which knows how to do it. This method is overridden
459 // by a nub subclass which may either know how to do it, or may need
460 // to take other action.
462 // This may be the only "power management" method used in a nub,
463 // meaning it may not be initialized for power management.
464 //*********************************************************************************
465 void IOService::joinPMtree ( IOService
* driver
)
467 IOPlatformExpert
* thePlatform
;
469 thePlatform
= getPlatform();
470 assert(thePlatform
!= 0 );
471 thePlatform
->PMRegisterDevice(this,driver
);
475 //*********************************************************************************
478 // Power Managment is informing us that we are the root power domain.
479 // The only difference between us and any other power domain is that
480 // we have no parent and therefore never call it.
481 //*********************************************************************************
482 IOReturn
IOService::youAreRoot ( void )
484 priv
-> we_are_root
= true;
485 pm_vars
->parentsKnowState
= true;
486 attachToParent( getRegistryRoot(),gIOPowerPlane
);
492 //*********************************************************************************
495 // Power Management is informing us who our parent is.
496 // If we have a controlling driver, find out, given our newly-informed
497 // power domain state, what state it would be in, and then tell it
498 // to assume that state.
499 //*********************************************************************************
500 IOReturn
IOService::setPowerParent ( IOPowerConnection
* theParent
, bool stateKnown
, IOPMPowerFlags currentState
)
504 IOPowerConnection
* connection
;
505 unsigned long tempDesire
;
507 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogSetParent
,stateKnown
,currentState
);
509 IOLockLock(pm_vars
->parentLock
);
511 if ( stateKnown
&& ((pm_vars
->PMworkloop
== NULL
) || (pm_vars
->PMcommandGate
== NULL
)) )
513 // we have a path to the root
514 // find out the workloop
516 if ( pm_vars
->PMworkloop
!= NULL
)
518 if ( pm_vars
->PMcommandGate
== NULL
)
520 // and make our command gate
521 pm_vars
->PMcommandGate
= IOCommandGate::commandGate((OSObject
*)this);
522 if ( pm_vars
->PMcommandGate
!= NULL
)
524 pm_vars
->PMworkloop
->addEventSource(pm_vars
->PMcommandGate
);
530 IOLockUnlock(pm_vars
->parentLock
);
532 // set our connection data
533 theParent
->setParentCurrentPowerFlags(currentState
);
534 theParent
->setParentKnowsState(stateKnown
);
536 // combine parent knowledge
537 pm_vars
->parentsKnowState
= true;
538 pm_vars
->parentsCurrentPowerFlags
= 0;
540 iter
= getParentIterator(gIOPowerPlane
);
544 while ( (next
= iter
->getNextObject()) )
546 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
548 pm_vars
->parentsKnowState
&= connection
->parentKnowsState();
549 pm_vars
->parentsCurrentPowerFlags
|= connection
->parentCurrentPowerFlags();
555 if ( (pm_vars
->theControllingDriver
!= NULL
) &&
556 (pm_vars
->parentsKnowState
) )
558 pm_vars
->maxCapability
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(pm_vars
->parentsCurrentPowerFlags
);
559 // initially change into the state we are already in
560 tempDesire
= priv
->deviceDesire
;
561 priv
->deviceDesire
= pm_vars
->theControllingDriver
->initialPowerStateForDomainState(pm_vars
->parentsCurrentPowerFlags
);
562 computeDesiredState();
563 priv
->previousRequest
= 0xffffffff;
565 // put this back like before
566 priv
->deviceDesire
= tempDesire
;
573 //*********************************************************************************
576 // Power Management is informing us who our children are.
577 //*********************************************************************************
578 IOReturn
IOService::addPowerChild ( IOService
* theChild
)
580 IOPowerConnection
*connection
;
585 // we're not a power-managed IOService
586 return IOPMNotYetInitialized
;
589 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAddChild
,0,0);
591 // Put ourselves into a usable power state.
592 // We must be in an "on" power state, as our children must be able to access
593 // our hardware after joining the power plane.
597 connection
= new IOPowerConnection
;
600 connection
->start(this);
601 connection
->setAwaitingAck(false);
604 attachToChild( connection
,gIOPowerPlane
);
605 connection
->attachToChild( theChild
,gIOPowerPlane
);
606 connection
->release();
608 // tell it the current state of the power domain
609 if ( (pm_vars
->theControllingDriver
== NULL
) ||
610 ! (inPlane(gIOPowerPlane
)) ||
611 ! (pm_vars
->parentsKnowState
) )
613 theChild
->setPowerParent(connection
,false,0);
614 if ( inPlane(gIOPowerPlane
) )
616 for (i
= 0; i
<= kMaxType
; i
++) {
617 if ( pm_vars
->current_aggressiveness_valid
[i
] )
619 theChild
->setAggressiveness (i
, pm_vars
->current_aggressiveness_values
[i
]);
624 theChild
->setPowerParent(connection
,true,pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].outputPowerCharacter
);
625 for (i
= 0; i
<= kMaxType
; i
++)
627 if ( pm_vars
->current_aggressiveness_valid
[i
] )
629 theChild
->setAggressiveness (i
, pm_vars
->current_aggressiveness_values
[i
]);
632 // catch it up if change is in progress
633 add_child_to_active_change(connection
);
640 //*********************************************************************************
643 //*********************************************************************************
644 IOReturn
IOService::removePowerChild ( IOPowerConnection
* theNub
)
646 IORegistryEntry
*theChild
;
649 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRemoveChild
,0,0);
653 // detach nub from child
654 theChild
= theNub
->copyChildEntry(gIOPowerPlane
);
657 theNub
->detachFromChild(theChild
, gIOPowerPlane
);
660 // detach from the nub
661 detachFromChild(theNub
,gIOPowerPlane
);
663 // are we awaiting an ack from this child?
664 if ( theNub
->getAwaitingAck() )
666 // yes, pretend we got one
667 theNub
->setAwaitingAck(false);
668 if ( acquire_lock() )
670 if (priv
->head_note_pendingAcks
!= 0 )
672 // that's one fewer ack to worry about
673 priv
->head_note_pendingAcks
-= 1;
675 if ( priv
->head_note_pendingAcks
== 0 )
677 // yes, stop the timer
679 IOUnlock(priv
->our_lock
);
680 // and now we can continue our power change
683 IOUnlock(priv
->our_lock
);
686 IOUnlock(priv
->our_lock
);
693 // if not fully initialized
694 if ( (pm_vars
->theControllingDriver
== NULL
) ||
695 !(inPlane(gIOPowerPlane
)) ||
696 !(pm_vars
->parentsKnowState
) )
702 // Perhaps the departing child was holding up idle or system sleep - we need to re-evaluate our
703 // childrens' requests. Clear and re-calculate our kIOPMChildClamp and kIOPMChildClamp2 bits.
704 rebuildChildClampBits();
709 iter
= getChildIterator(gIOPowerPlane
);
710 if ( !iter
|| !iter
->getNextObject() )
712 // paired to match the makeUsable() call in addPowerChild()
713 changePowerStateToPriv(0);
715 if(iter
) iter
->release();
718 // this may be different now
719 computeDesiredState();
720 // change state if we can now tolerate lower power
727 //*********************************************************************************
728 // registerPowerDriver
730 // A driver has called us volunteering to control power to our device.
731 // If the power state array it provides is richer than the one we already
732 // know about (supplied by an earlier volunteer), then accept the offer.
733 // Notify all interested parties of our power state, which we now know.
734 //*********************************************************************************
736 IOReturn
IOService::registerPowerDriver ( IOService
* controllingDriver
, IOPMPowerState
* powerStates
, unsigned long numberOfStates
)
739 unsigned long tempDesire
;
741 if ( (numberOfStates
> pm_vars
->theNumberOfPowerStates
)
742 && (numberOfStates
> 1) )
744 if ( priv
->changeList
->currentChange() == -1 )
746 if ( controllingDriver
!= NULL
)
748 if ( numberOfStates
<= IOPMMaxPowerStates
)
750 switch ( powerStates
[0].version
)
753 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriver
,
754 (unsigned long)numberOfStates
, (unsigned long)powerStates
[0].version
);
755 for ( i
= 0; i
< numberOfStates
; i
++ )
757 pm_vars
->thePowerStates
[i
] = powerStates
[i
];
761 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriver
,
762 (unsigned long) numberOfStates
,(unsigned long) powerStates
[0].version
);
763 for ( i
= 0; i
< numberOfStates
; i
++ )
765 pm_vars
->thePowerStates
[i
].version
= powerStates
[i
].version
;
766 pm_vars
->thePowerStates
[i
].capabilityFlags
= powerStates
[i
].capabilityFlags
;
767 pm_vars
->thePowerStates
[i
].outputPowerCharacter
= powerStates
[i
].outputPowerCharacter
;
768 pm_vars
->thePowerStates
[i
].inputPowerRequirement
= powerStates
[i
].inputPowerRequirement
;
769 pm_vars
->thePowerStates
[i
].staticPower
= powerStates
[i
].staticPower
;
770 pm_vars
->thePowerStates
[i
].unbudgetedPower
= powerStates
[i
].unbudgetedPower
;
771 pm_vars
->thePowerStates
[i
].powerToAttain
= powerStates
[i
].powerToAttain
;
772 pm_vars
->thePowerStates
[i
].timeToAttain
= powerStates
[i
].timeToAttain
;
773 pm_vars
->thePowerStates
[i
].settleUpTime
= powerStates
[i
].settleUpTime
;
774 pm_vars
->thePowerStates
[i
].timeToLower
= powerStates
[i
].timeToLower
;
775 pm_vars
->thePowerStates
[i
].settleDownTime
= powerStates
[i
].settleDownTime
;
776 pm_vars
->thePowerStates
[i
].powerDomainBudget
= powerStates
[i
].powerDomainBudget
;
780 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr1
,
781 (unsigned long)powerStates
[0].version
,0);
785 // make a mask of all the character bits we know about
786 pm_vars
->myCharacterFlags
= 0;
787 for ( i
= 0; i
< numberOfStates
; i
++ ) {
788 pm_vars
->myCharacterFlags
|= pm_vars
->thePowerStates
[i
].outputPowerCharacter
;
791 pm_vars
->theNumberOfPowerStates
= numberOfStates
;
792 pm_vars
->theControllingDriver
= controllingDriver
;
793 if ( priv
->interestedDrivers
->findItem(controllingDriver
) == NULL
)
795 // register it as interested, unless already done
796 registerInterestedDriver (controllingDriver
);
798 if ( priv
->need_to_become_usable
) {
799 priv
->need_to_become_usable
= false;
800 priv
->deviceDesire
= pm_vars
->theNumberOfPowerStates
- 1;
803 if ( inPlane(gIOPowerPlane
) &&
804 (pm_vars
->parentsKnowState
) ) {
805 pm_vars
->maxCapability
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(pm_vars
->parentsCurrentPowerFlags
);
806 // initially change into the state we are already in
807 tempDesire
= priv
->deviceDesire
;
808 priv
->deviceDesire
= pm_vars
->theControllingDriver
->initialPowerStateForDomainState(pm_vars
->parentsCurrentPowerFlags
);
809 computeDesiredState();
811 // put this back like before
812 priv
->deviceDesire
= tempDesire
;
815 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr2
,(unsigned long)numberOfStates
,0);
818 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr4
,0,0);
823 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr5
,(unsigned long)numberOfStates
,0);
828 //*********************************************************************************
829 // registerInterestedDriver
831 // Add the caller to our list of interested drivers and return our current
832 // power state. If we don't have a power-controlling driver yet, we will
833 // call this interested driver again later when we do get a driver and find
834 // out what the current power state of the device is.
835 //*********************************************************************************
837 IOPMPowerFlags
IOService::registerInterestedDriver ( IOService
* theDriver
)
839 IOPMinformee
*newInformee
;
840 IOPMPowerFlags futureCapability
;
842 if (theDriver
== NULL
) {
846 // make new driver node
847 newInformee
= new IOPMinformee
;
848 newInformee
->initialize(theDriver
);
849 // add it to list of drivers
850 priv
->interestedDrivers
->addToList(newInformee
);
852 if ( (pm_vars
->theControllingDriver
== NULL
) ||
853 !(inPlane(gIOPowerPlane
)) ||
854 !(pm_vars
->parentsKnowState
) )
856 // can't tell it a state yet
857 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInterestedDriver
,IOPMNotPowerManaged
,0);
858 return IOPMNotPowerManaged
;
861 // can we notify new driver of a change in progress?
862 switch (priv
->machine_state
) {
863 case kIOPM_OurChangeSetPowerState
:
864 case kIOPM_OurChangeFinish
:
865 case kIOPM_ParentDownSetPowerState_Delayed
:
866 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
867 case kIOPM_ParentUpSetPowerState_Delayed
:
868 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
869 // yes, remember what we tell it
870 futureCapability
= priv
->head_note_capabilityFlags
;
871 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInterestedDriver
,(unsigned long)futureCapability
,1);
873 add_driver_to_active_change(newInformee
);
874 // and return the same thing
875 return futureCapability
;
878 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInterestedDriver
,
879 (unsigned long) pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
,2);
881 // no, return current capability
882 return pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
;
886 //*********************************************************************************
887 // deRegisterInterestedDriver
889 //*********************************************************************************
890 IOReturn
IOService::deRegisterInterestedDriver ( IOService
* theDriver
)
892 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRemoveDriver
,0,0);
894 // remove the departing driver
895 priv
->interestedDrivers
->removeFromList(theDriver
);
901 //*********************************************************************************
902 // acknowledgePowerChange
904 // After we notified one of the interested drivers or a power-domain child
905 // of an impending change in power, it has called to say it is now
906 // prepared for the change. If this object is the last to
907 // acknowledge this change, we take whatever action we have been waiting
909 // That may include acknowledging to our parent. In this case, we do it
910 // last of all to insure that this doesn't cause the parent to call us some-
911 // where else and alter data we are relying on here (like the very existance
912 // of a "current change note".)
913 //*********************************************************************************
915 IOReturn
IOService::acknowledgePowerChange ( IOService
* whichObject
)
917 IOPMinformee
*ackingObject
;
918 unsigned long childPower
= kIOPMUnknown
;
921 // one of our interested drivers?
922 ackingObject
= priv
->interestedDrivers
->findItem(whichObject
);
923 if ( ackingObject
== NULL
)
925 if ( ! isChild(whichObject
,gIOPowerPlane
) )
927 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr1
,0,0);
928 //kprintf("errant driver: %s\n",whichObject->getName());
932 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChildAcknowledge
,priv
->head_note_pendingAcks
,0);
935 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogDriverAcknowledge
,priv
->head_note_pendingAcks
,0);
938 if (! acquire_lock() )
943 if (priv
->head_note_pendingAcks
!= 0 )
945 // yes, make sure we're expecting acks
946 if ( ackingObject
!= NULL
)
948 // it's an interested driver
949 // make sure we're expecting this ack
950 if ( ackingObject
->timer
!= 0 )
953 ackingObject
->timer
= 0;
954 // that's one fewer to worry about
955 priv
->head_note_pendingAcks
-= 1;
957 if ( priv
->head_note_pendingAcks
== 0 )
959 // yes, stop the timer
961 IOUnlock(priv
->our_lock
);
962 // and now we can continue
967 // this driver has already acked
968 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr2
,0,0);
969 //kprintf("errant driver: %s\n",whichObject->getName());
973 // make sure we're expecting this ack
974 if ( ((IOPowerConnection
*)whichObject
)->getAwaitingAck() )
976 // that's one fewer to worry about
977 priv
->head_note_pendingAcks
-= 1;
978 ((IOPowerConnection
*)whichObject
)->setAwaitingAck(false);
979 theChild
= (IOService
*)whichObject
->copyChildEntry(gIOPowerPlane
);
982 childPower
= theChild
->currentPowerConsumption();
985 if ( childPower
== kIOPMUnknown
)
987 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
= kIOPMUnknown
;
989 if ( pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
!= kIOPMUnknown
)
991 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
+= childPower
;
995 if ( priv
->head_note_pendingAcks
== 0 ) {
996 // yes, stop the timer
998 IOUnlock(priv
->our_lock
);
999 // and now we can continue
1006 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr3
,0,0); // not expecting anybody to ack
1007 //kprintf("errant driver: %s\n",whichObject->getName());
1009 IOUnlock(priv
->our_lock
);
1013 //*********************************************************************************
1014 // acknowledgeSetPowerState
1016 // After we instructed our controlling driver to change power states,
1017 // it has called to say it has finished doing so.
1018 // We continue to process the power state change.
1019 //*********************************************************************************
1021 IOReturn
IOService::acknowledgeSetPowerState ( void )
1023 if (!acquire_lock())
1026 IOReturn timer
= priv
->driver_timer
;
1027 if ( timer
== -1 ) {
1028 // driver is acking instead of using return code
1029 OUR_PMLog(kPMLogDriverAcknowledgeSet
, (UInt32
) this, timer
);
1030 priv
->driver_timer
= 0;
1032 else if ( timer
> 0 ) { // are we expecting this?
1033 // yes, stop the timer
1035 priv
->driver_timer
= 0;
1036 OUR_PMLog(kPMLogDriverAcknowledgeSet
, (UInt32
) this, timer
);
1037 IOUnlock(priv
->our_lock
);
1041 // not expecting this
1042 OUR_PMLog(kPMLogAcknowledgeErr4
, (UInt32
) this, 0);
1045 IOUnlock(priv
->our_lock
);
1050 //*********************************************************************************
1053 // Either the controlling driver has called acknowledgeSetPowerState
1054 // or the acknowledgement timer has expired while waiting for that.
1055 // We carry on processing the current change note.
1056 //*********************************************************************************
1058 void IOService::driver_acked ( void )
1060 switch (priv
->machine_state
) {
1061 case kIOPM_OurChangeWaitForPowerSettle
:
1062 OurChangeWaitForPowerSettle();
1064 case kIOPM_ParentDownWaitForPowerSettle_Delayed
:
1065 ParentDownWaitForPowerSettle_Delayed();
1067 case kIOPM_ParentUpWaitForSettleTime_Delayed
:
1068 ParentUpWaitForSettleTime_Delayed();
1074 //*********************************************************************************
1075 // powerDomainWillChangeTo
1077 // Called by the power-hierarchy parent notifying of a new power state
1078 // in the power domain.
1079 // We enqueue a parent power-change to our queue of power changes.
1080 // This may or may not cause us to change power, depending on what
1081 // kind of change is occuring in the domain.
1082 //*********************************************************************************
1084 IOReturn
IOService::powerDomainWillChangeTo ( IOPMPowerFlags newPowerStateFlags
, IOPowerConnection
* whichParent
)
1088 IOPowerConnection
*connection
;
1089 unsigned long newStateNumber
;
1090 IOPMPowerFlags combinedPowerFlags
;
1092 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogWillChange
,(unsigned long)newPowerStateFlags
,0);
1094 if ( ! inPlane(gIOPowerPlane
) )
1097 return IOPMAckImplied
;
1100 IOLockLock(pm_vars
->parentLock
);
1102 if ( (pm_vars
->PMworkloop
== NULL
) || (pm_vars
->PMcommandGate
== NULL
) )
1104 // we have a path to the root
1106 // so find out the workloop
1107 if ( pm_vars
->PMworkloop
!= NULL
)
1109 // and make our command gate
1110 if ( pm_vars
->PMcommandGate
== NULL
)
1112 pm_vars
->PMcommandGate
= IOCommandGate::commandGate((OSObject
*)this);
1113 if ( pm_vars
->PMcommandGate
!= NULL
)
1115 pm_vars
->PMworkloop
->addEventSource(pm_vars
->PMcommandGate
);
1121 IOLockUnlock(pm_vars
->parentLock
);
1123 // combine parents' power states
1124 // to determine our maximum state within the new power domain
1125 combinedPowerFlags
= 0;
1127 iter
= getParentIterator(gIOPowerPlane
);
1131 while ( (next
= iter
->getNextObject()) )
1133 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1135 if ( connection
== whichParent
){
1136 combinedPowerFlags
|= newPowerStateFlags
;
1138 combinedPowerFlags
|= connection
->parentCurrentPowerFlags();
1145 if ( pm_vars
->theControllingDriver
== NULL
)
1147 // we can't take any more action
1148 return IOPMAckImplied
;
1150 newStateNumber
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(combinedPowerFlags
);
1152 return enqueuePowerChange(IOPMParentInitiated
| IOPMDomainWillChange
,
1153 newStateNumber
,combinedPowerFlags
,whichParent
,newPowerStateFlags
);
1157 //*********************************************************************************
1158 // powerDomainDidChangeTo
1160 // Called by the power-hierarchy parent after the power state of the power domain
1161 // has settled at a new level.
1162 // We enqueue a parent power-change to our queue of power changes.
1163 // This may or may not cause us to change power, depending on what
1164 // kind of change is occuring in the domain.
1165 //*********************************************************************************
1167 IOReturn
IOService::powerDomainDidChangeTo ( IOPMPowerFlags newPowerStateFlags
, IOPowerConnection
* whichParent
)
1169 unsigned long newStateNumber
;
1171 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogDidChange
,newPowerStateFlags
,0);
1173 setParentInfo(newPowerStateFlags
,whichParent
);
1175 if ( pm_vars
->theControllingDriver
== NULL
) {
1176 return IOPMAckImplied
;
1179 newStateNumber
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(pm_vars
->parentsCurrentPowerFlags
);
1180 // tell interested parties about it
1181 return enqueuePowerChange(IOPMParentInitiated
| IOPMDomainDidChange
,
1182 newStateNumber
,pm_vars
->parentsCurrentPowerFlags
,whichParent
,0);
1186 //*********************************************************************************
1189 // Set our connection data for one specific parent, and then combine all the parent
1191 //*********************************************************************************
1193 void IOService::setParentInfo ( IOPMPowerFlags newPowerStateFlags
, IOPowerConnection
* whichParent
)
1197 IOPowerConnection
*connection
;
1199 // set our connection data
1200 whichParent
->setParentCurrentPowerFlags(newPowerStateFlags
);
1201 whichParent
->setParentKnowsState(true);
1203 IOLockLock(pm_vars
->parentLock
);
1205 // recompute our parent info
1206 pm_vars
->parentsCurrentPowerFlags
= 0;
1207 pm_vars
->parentsKnowState
= true;
1209 iter
= getParentIterator(gIOPowerPlane
);
1213 while ( (next
= iter
->getNextObject()) )
1215 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1217 pm_vars
->parentsKnowState
&= connection
->parentKnowsState();
1218 pm_vars
->parentsCurrentPowerFlags
|= connection
->parentCurrentPowerFlags();
1223 IOLockUnlock(pm_vars
->parentLock
);
1226 //*********************************************************************************
1227 // rebuildChildClampBits
1229 // The ChildClamp bits (kIOPMChildClamp & kIOPMChildClamp2) in our capabilityFlags
1230 // indicate that one of our children (or grandchildren or great-grandchildren or ...)
1231 // doesn't support idle or system sleep in its current state. Since we don't track the
1232 // origin of each bit, every time any child changes state we have to clear these bits
1233 // and rebuild them.
1234 //*********************************************************************************
1236 void IOService::rebuildChildClampBits(void)
1241 IOPowerConnection
*connection
;
1244 // A child's desires has changed. We need to rebuild the child-clamp bits in our
1245 // power state array. Start by clearing the bits in each power state.
1247 for ( i
= 0; i
< pm_vars
->theNumberOfPowerStates
; i
++ )
1249 pm_vars
->thePowerStates
[i
].capabilityFlags
&= ~(kIOPMChildClamp
| kIOPMChildClamp2
);
1252 // Now loop through the children. When we encounter the calling child, save
1253 // the computed state as this child's desire. And while we're at it, set the ChildClamp bits
1254 // in any of our states that some child has requested with clamp on.
1256 iter
= getChildIterator(gIOPowerPlane
);
1260 while ( (next
= iter
->getNextObject()) )
1262 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1264 if ( connection
->getPreventIdleSleepFlag() )
1265 pm_vars
->thePowerStates
[connection
->getDesiredDomainState()].capabilityFlags
|= kIOPMChildClamp
;
1266 if ( connection
->getPreventSystemSleepFlag() )
1267 pm_vars
->thePowerStates
[connection
->getDesiredDomainState()].capabilityFlags
|= kIOPMChildClamp2
;
1276 //*********************************************************************************
1277 // requestPowerDomainState
1279 // The kIOPMPreventIdleSleep and/or kIOPMPreventIdleSleep bits may be be set in the parameter.
1280 // It is not considered part of the state specification.
1281 //*********************************************************************************
1282 IOReturn
IOService::requestPowerDomainState ( IOPMPowerFlags desiredState
, IOPowerConnection
* whichChild
, unsigned long specification
)
1285 unsigned long computedState
;
1286 unsigned long theDesiredState
= desiredState
& ~(kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
1289 IOPowerConnection
*connection
;
1291 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRequestDomain
,
1292 (unsigned long)desiredState
,(unsigned long)specification
);
1294 if ( pm_vars
->theControllingDriver
== NULL
)
1296 return IOPMNotYetInitialized
;
1299 switch (specification
) {
1300 case IOPMLowestState
:
1302 while ( i
< pm_vars
->theNumberOfPowerStates
)
1304 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1310 if ( i
>= pm_vars
->theNumberOfPowerStates
)
1312 return IOPMNoSuchState
;
1316 case IOPMNextLowerState
:
1317 i
= pm_vars
->myCurrentState
- 1;
1318 while ( (int) i
>= 0 )
1320 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1328 return IOPMNoSuchState
;
1332 case IOPMHighestState
:
1333 i
= pm_vars
->theNumberOfPowerStates
;
1334 while ( (int) i
>= 0 )
1337 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1344 return IOPMNoSuchState
;
1348 case IOPMNextHigherState
:
1349 i
= pm_vars
->myCurrentState
+ 1;
1350 while ( i
< pm_vars
->theNumberOfPowerStates
)
1352 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1358 if ( i
== pm_vars
->theNumberOfPowerStates
)
1360 return IOPMNoSuchState
;
1365 return IOPMBadSpecification
;
1370 IOLockLock(pm_vars
->childLock
);
1372 // Now loop through the children. When we encounter the calling child, save
1373 // the computed state as this child's desire.
1374 iter
= getChildIterator(gIOPowerPlane
);
1378 while ( (next
= iter
->getNextObject()) )
1380 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1382 if ( connection
== whichChild
)
1384 connection
->setDesiredDomainState(computedState
);
1385 connection
->setPreventIdleSleepFlag(desiredState
& kIOPMPreventIdleSleep
);
1386 connection
->setPreventSystemSleepFlag(desiredState
& kIOPMPreventSystemSleep
);
1387 connection
->setChildHasRequestedPower();
1394 // Since a child's power requirements may have changed, clear and rebuild
1395 // kIOPMChildClamp and kIOPMChildClamp2 (idle and system sleep clamps)
1396 rebuildChildClampBits();
1398 IOLockUnlock(pm_vars
->childLock
);
1400 // this may be different now
1401 computeDesiredState();
1403 if ( inPlane(gIOPowerPlane
) &&
1404 (pm_vars
->parentsKnowState
) ) {
1405 // change state if all children can now tolerate lower power
1409 // are we clamped on, waiting for this child?
1410 if ( priv
->clampOn
) {
1411 // yes, remove the clamp
1412 priv
->clampOn
= false;
1413 changePowerStateToPriv(0);
1420 //*********************************************************************************
1421 // temporaryPowerClampOn
1423 // A power domain wants to clamp its power on till it has children which
1424 // will thendetermine the power domain state.
1426 // We enter the highest state until addPowerChild is called.
1427 //*********************************************************************************
1429 IOReturn
IOService::temporaryPowerClampOn ( void )
1431 priv
->clampOn
= true;
1437 //*********************************************************************************
1440 // Some client of our device is asking that we become usable. Although
1441 // this has not come from a subclassed device object, treat it exactly
1442 // as if it had. In this way, subsequent requests for lower power from
1443 // a subclassed device object will pre-empt this request.
1445 // We treat this as a subclass object request to switch to the
1446 // highest power state.
1447 //*********************************************************************************
1449 IOReturn
IOService::makeUsable ( void )
1451 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogMakeUsable
,0,0);
1453 if ( pm_vars
->theControllingDriver
== NULL
)
1455 priv
->need_to_become_usable
= true;
1458 priv
->deviceDesire
= pm_vars
->theNumberOfPowerStates
- 1;
1459 computeDesiredState();
1460 if ( inPlane(gIOPowerPlane
) && (pm_vars
->parentsKnowState
) )
1462 return changeState();
1468 //*********************************************************************************
1469 // currentCapability
1471 //*********************************************************************************
1473 IOPMPowerFlags
IOService::currentCapability ( void )
1475 if ( pm_vars
->theControllingDriver
== NULL
)
1479 return pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
;
1484 //*********************************************************************************
1485 // changePowerStateTo
1487 // For some reason, our power-controlling driver has decided it needs to change
1488 // power state. We enqueue the power change so that appropriate parties
1489 // will be notified, and then we will instruct the driver to make the change.
1490 //*********************************************************************************
1492 IOReturn
IOService::changePowerStateTo ( unsigned long ordinal
)
1494 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeStateTo
,ordinal
,0);
1496 if ( ordinal
>= pm_vars
->theNumberOfPowerStates
)
1498 return IOPMParameterError
;
1500 priv
->driverDesire
= ordinal
;
1501 computeDesiredState();
1502 if ( inPlane(gIOPowerPlane
) && (pm_vars
->parentsKnowState
) )
1504 return changeState();
1510 //*********************************************************************************
1511 // changePowerStateToPriv
1513 // For some reason, a subclassed device object has decided it needs to change
1514 // power state. We enqueue the power change so that appropriate parties
1515 // will be notified, and then we will instruct the driver to make the change.
1516 //*********************************************************************************
1518 IOReturn
IOService::changePowerStateToPriv ( unsigned long ordinal
)
1520 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeStateToPriv
,ordinal
,0);
1522 if ( pm_vars
->theControllingDriver
== NULL
)
1524 return IOPMNotYetInitialized
;
1526 if ( ordinal
>= pm_vars
->theNumberOfPowerStates
)
1528 return IOPMParameterError
;
1530 priv
->deviceDesire
= ordinal
;
1531 computeDesiredState();
1532 if ( inPlane(gIOPowerPlane
) && (pm_vars
->parentsKnowState
) )
1534 return changeState();
1541 //*********************************************************************************
1542 // computeDesiredState
1544 //*********************************************************************************
1546 void IOService::computeDesiredState ( void )
1550 IOPowerConnection
*connection
;
1551 unsigned long newDesiredState
= 0;
1553 // Compute the maximum of our children's desires, our controlling driver's desire, and the subclass device's desire.
1554 if ( ! priv
->device_overrides
)
1556 iter
= getChildIterator(gIOPowerPlane
);
1560 while ( (next
= iter
->getNextObject()) )
1562 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1564 if ( connection
->getDesiredDomainState() > newDesiredState
)
1566 newDesiredState
= connection
->getDesiredDomainState();
1573 if ( priv
->driverDesire
> newDesiredState
)
1575 newDesiredState
= priv
->driverDesire
;
1579 if ( priv
->deviceDesire
> newDesiredState
)
1581 newDesiredState
= priv
->deviceDesire
;
1584 priv
->ourDesiredPowerState
= newDesiredState
;
1588 //*********************************************************************************
1591 // A subclass object, our controlling driver, or a power domain child
1592 // has asked for a different power state. Here we compute what new
1593 // state we should enter and enqueue the change (or start it).
1594 //*********************************************************************************
1596 IOReturn
IOService::changeState ( void )
1598 // if not fully initialized
1599 if ( (pm_vars
->theControllingDriver
== NULL
) ||
1600 !(inPlane(gIOPowerPlane
)) ||
1601 !(pm_vars
->parentsKnowState
) )
1603 // we can do no more
1607 return enqueuePowerChange(IOPMWeInitiated
,priv
->ourDesiredPowerState
,0,0,0);
1611 //*********************************************************************************
1612 // currentPowerConsumption
1614 //*********************************************************************************
1616 unsigned long IOService::currentPowerConsumption ( void )
1618 if ( pm_vars
->theControllingDriver
== NULL
)
1620 return kIOPMUnknown
;
1622 if ( pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
& kIOPMStaticPowerValid
)
1624 return pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].staticPower
;
1626 return kIOPMUnknown
;
1629 //*********************************************************************************
1632 // The activity tickle with parameter kIOPMSubclassPolicyis not handled
1633 // here and should have been intercepted by the subclass.
1634 // The tickle with parameter kIOPMSuperclassPolicy1 causes the activity
1635 // flag to be set, and the device state checked. If the device has been
1636 // powered down, it is powered up again.
1637 //*********************************************************************************
1639 bool IOService::activityTickle ( unsigned long type
, unsigned long stateNumber
)
1641 IOPMrootDomain
*pmRootDomain
;
1642 AbsoluteTime uptime
;
1644 if ( type
== kIOPMSuperclassPolicy1
)
1646 if ( pm_vars
->theControllingDriver
== NULL
)
1651 if( priv
->activityLock
== NULL
)
1653 priv
->activityLock
= IOLockAlloc();
1656 IOTakeLock(priv
->activityLock
);
1657 priv
->device_active
= true;
1659 clock_get_uptime(&uptime
);
1660 priv
->device_active_timestamp
= uptime
;
1662 if ( pm_vars
->myCurrentState
>= stateNumber
)
1664 IOUnlock(priv
->activityLock
);
1667 IOUnlock(priv
->activityLock
);
1669 // Transfer execution to the PM workloop
1670 if( (pmRootDomain
= getPMRootDomain()) )
1671 pmRootDomain
->unIdleDevice(this, stateNumber
);
1678 //*********************************************************************************
1681 // A child is calling to get a pointer to the Power Management workloop.
1682 // We got it or get it from one of our parents.
1683 //*********************************************************************************
1685 IOWorkLoop
* IOService::getPMworkloop ( void )
1690 if ( ! inPlane(gIOPowerPlane
) )
1694 // we have no workloop yet
1695 if ( pm_vars
->PMworkloop
== NULL
)
1697 nub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
1700 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
1702 // ask one of our parents for the workloop
1705 pm_vars
->PMworkloop
= parent
->getPMworkloop();
1710 return pm_vars
->PMworkloop
;
1714 //*********************************************************************************
1715 // setIdleTimerPeriod
1717 // A subclass policy-maker is going to use our standard idleness
1718 // detection service. Make a command queue and an idle timer and
1719 // connect them to the power management workloop. Finally,
1721 //*********************************************************************************
1723 IOReturn
IOService::setIdleTimerPeriod ( unsigned long period
)
1725 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMsetIdleTimerPeriod
,period
, 0);
1727 priv
->idle_timer_period
= period
;
1731 if ( getPMworkloop() == NULL
)
1733 return kIOReturnError
;
1736 // make the timer event
1737 if ( priv
->timerEventSrc
== NULL
)
1739 priv
->timerEventSrc
= IOTimerEventSource::timerEventSource(this,
1740 PM_idle_timer_expired
);
1741 if ((!priv
->timerEventSrc
) ||
1742 (pm_vars
->PMworkloop
->addEventSource(priv
->timerEventSrc
) != kIOReturnSuccess
) )
1744 return kIOReturnError
;
1748 if ( priv
->activityLock
== NULL
)
1750 priv
->activityLock
= IOLockAlloc();
1753 start_PM_idle_timer();
1758 //******************************************************************************
1761 // Returns how many "seconds from now" the device should idle into its
1762 // next lowest power state.
1763 //******************************************************************************
1764 SInt32
IOService::nextIdleTimeout(
1765 AbsoluteTime currentTime
,
1766 AbsoluteTime lastActivity
,
1767 unsigned int powerState
)
1774 // Calculate time difference using funky macro from clock.h.
1775 delta
= currentTime
;
1776 SUB_ABSOLUTETIME(&delta
, &lastActivity
);
1778 // Figure it in seconds.
1779 absolutetime_to_nanoseconds(delta
, &delta_ns
);
1780 delta_secs
= (SInt32
)(delta_ns
/ NSEC_PER_SEC
);
1782 // Be paranoid about delta somehow exceeding timer period.
1783 if (delta_secs
< (int) priv
->idle_timer_period
)
1784 delay_secs
= (int) priv
->idle_timer_period
- delta_secs
;
1786 delay_secs
= (int) priv
->idle_timer_period
;
1788 return (SInt32
)delay_secs
;
1791 //******************************************************************************
1792 // start_PM_idle_timer
1794 // The parameter is a pointer to us. Use it to call our timeout method.
1795 //******************************************************************************
1796 void IOService::start_PM_idle_timer ( void )
1798 static const int maxTimeout
= 100000;
1799 static const int minTimeout
= 1;
1800 AbsoluteTime uptime
;
1803 IOLockLock(priv
->activityLock
);
1805 clock_get_uptime(&uptime
);
1807 // Subclasses may modify idle sleep algorithm
1808 idle_in
= nextIdleTimeout(uptime
,
1809 priv
->device_active_timestamp
,
1810 pm_vars
->myCurrentState
);
1812 // Check for out-of range responses
1813 if(idle_in
> maxTimeout
)
1815 // use standard implementation
1816 idle_in
= IOService::nextIdleTimeout(uptime
,
1817 priv
->device_active_timestamp
,
1818 pm_vars
->myCurrentState
);
1819 } else if(idle_in
< minTimeout
) {
1824 priv
->timerEventSrc
->setTimeout(idle_in
, NSEC_PER_SEC
);
1826 IOLockUnlock(priv
->activityLock
);
1831 //*********************************************************************************
1832 // PM_idle_timer_expired
1834 // The parameter is a pointer to us. Use it to call our timeout method.
1835 //*********************************************************************************
1837 void PM_idle_timer_expired(OSObject
* ourSelves
, IOTimerEventSource
*)
1839 ((IOService
*)ourSelves
)->PM_idle_timer_expiration();
1843 //*********************************************************************************
1844 // PM_idle_timer_expiration
1846 // The idle timer has expired. If there has been activity since the last
1847 // expiration, just restart the timer and return. If there has not been
1848 // activity, switch to the next lower power state and restart the timer.
1849 //*********************************************************************************
1851 void IOService::PM_idle_timer_expiration ( void )
1853 if ( ! initialized
)
1859 if ( priv
->idle_timer_period
> 0 )
1861 IOTakeLock(priv
->activityLock
);
1862 if ( priv
->device_active
)
1864 priv
->device_active
= false;
1865 IOUnlock(priv
->activityLock
);
1866 start_PM_idle_timer();
1869 if ( pm_vars
->myCurrentState
> 0 )
1871 IOUnlock(priv
->activityLock
);
1872 changePowerStateToPriv(pm_vars
->myCurrentState
- 1);
1873 start_PM_idle_timer();
1876 IOUnlock(priv
->activityLock
);
1877 start_PM_idle_timer();
1882 // **********************************************************************************
1885 // We are un-idling a device due to its activity tickle. This routine runs on the
1886 // PM workloop, and is initiated by IOService::activityTickle.
1887 // We process all activityTickle state requests on the list.
1888 // **********************************************************************************
1889 void IOService::command_received ( void *statePtr
, void *, void * , void * )
1891 unsigned long stateNumber
;
1893 stateNumber
= (unsigned long)statePtr
;
1895 // If not initialized, we're unloading
1896 if ( ! initialized
) return;
1898 if ( (pm_vars
->myCurrentState
< stateNumber
) &&
1899 (priv
->imminentState
< stateNumber
) )
1901 changePowerStateToPriv(stateNumber
);
1903 // After we raise our state, re-schedule the idle timer.
1904 if(priv
->timerEventSrc
)
1905 start_PM_idle_timer();
1910 //*********************************************************************************
1911 // setAggressiveness
1913 // Pass on the input parameters to all power domain children. All those which are
1914 // power domains will pass it on to their children, etc.
1915 //*********************************************************************************
1917 IOReturn
IOService::setAggressiveness ( unsigned long type
, unsigned long newLevel
)
1921 IOPowerConnection
*connection
;
1924 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogSetAggressiveness
,type
, newLevel
);
1926 if ( type
<= kMaxType
)
1928 pm_vars
->current_aggressiveness_values
[type
] = newLevel
;
1929 pm_vars
->current_aggressiveness_valid
[type
] = true;
1932 iter
= getChildIterator(gIOPowerPlane
);
1936 while ( (next
= iter
->getNextObject()) )
1938 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1940 child
= ((IOService
*)(connection
->copyChildEntry(gIOPowerPlane
)));
1943 child
->setAggressiveness(type
, newLevel
);
1954 //*********************************************************************************
1955 // getAggressiveness
1957 // Called by the user client.
1958 //*********************************************************************************
1960 IOReturn
IOService::getAggressiveness ( unsigned long type
, unsigned long * currentLevel
)
1962 if ( type
> kMaxType
)
1963 return kIOReturnBadArgument
;
1965 if ( !pm_vars
->current_aggressiveness_valid
[type
] )
1966 return kIOReturnInvalid
;
1968 *currentLevel
= pm_vars
->current_aggressiveness_values
[type
];
1970 return kIOReturnSuccess
;
1973 //*********************************************************************************
1976 // Pass this to all power domain children. All those which are
1977 // power domains will pass it on to their children, etc.
1978 //*********************************************************************************
1980 IOReturn
IOService::systemWake ( void )
1984 IOPowerConnection
*connection
;
1985 IOService
*theChild
;
1987 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogSystemWake
,0, 0);
1989 iter
= getChildIterator(gIOPowerPlane
);
1993 while ( (next
= iter
->getNextObject()) )
1995 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1997 theChild
= (IOService
*)connection
->copyChildEntry(gIOPowerPlane
);
2000 theChild
->systemWake();
2001 theChild
->release();
2008 if ( pm_vars
->theControllingDriver
!= NULL
)
2010 if ( pm_vars
->theControllingDriver
->didYouWakeSystem() )
2020 //*********************************************************************************
2021 // temperatureCriticalForZone
2023 //*********************************************************************************
2025 IOReturn
IOService::temperatureCriticalForZone ( IOService
* whichZone
)
2027 IOService
*theParent
;
2030 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogCriticalTemp
,0,0);
2032 if ( inPlane(gIOPowerPlane
) && !(priv
->we_are_root
) )
2034 theNub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
2037 theParent
= (IOService
*)theNub
->copyParentEntry(gIOPowerPlane
);
2041 theParent
->temperatureCriticalForZone(whichZone
);
2042 theParent
->release();
2050 //*********************************************************************************
2051 // powerOverrideOnPriv
2053 //*********************************************************************************
2056 IOReturn
IOService::powerOverrideOnPriv ( void )
2058 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogOverrideOn
,0,0);
2060 // turn on the override
2061 priv
->device_overrides
= true;
2062 computeDesiredState();
2064 // change state if that changed something
2065 return changeState();
2069 //*********************************************************************************
2070 // powerOverrideOffPriv
2072 //*********************************************************************************
2073 IOReturn
IOService::powerOverrideOffPriv ( void )
2075 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogOverrideOff
,0,0);
2077 // turn off the override
2078 priv
->device_overrides
= false;
2079 computeDesiredState();
2082 return makeUsable();
2084 // change state if that changed something
2085 return changeState();
2090 //*********************************************************************************
2091 // enqueuePowerChange
2093 // Allocate a new state change notification, initialize it with fields from the
2094 // caller, and add it to the tail of the list of pending power changes.
2096 // If it is early enough in the list, and almost all the time it is the only one in
2097 // the list, start the power change.
2099 // In rare instances, this change will preempt the previous change in the list.
2100 // If the previous change is un-actioned in any way (because we are still
2101 // processing an even earlier power change), and if both the previous change
2102 // in the list and this change are initiated by us (not the parent), then we
2103 // needn't perform the previous change, so we collapse the list a little.
2104 //*********************************************************************************
2106 IOReturn
IOService::enqueuePowerChange ( unsigned long flags
, unsigned long whatStateOrdinal
, unsigned long domainState
, IOPowerConnection
* whichParent
, unsigned long singleParentState
)
2111 // Create and initialize the new change note
2113 IOLockLock(priv
->queue_lock
);
2114 newNote
= priv
->changeList
->createChangeNote();
2115 if ( newNote
== -1 ) {
2116 // uh-oh, our list is full
2117 IOLockUnlock(priv
->queue_lock
);
2118 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogEnqueueErr
,0,0);
2119 return IOPMAckImplied
;
2122 priv
->changeList
->changeNote
[newNote
].newStateNumber
= whatStateOrdinal
;
2123 priv
->changeList
->changeNote
[newNote
].outputPowerCharacter
= pm_vars
->thePowerStates
[whatStateOrdinal
].outputPowerCharacter
;
2124 priv
->changeList
->changeNote
[newNote
].inputPowerRequirement
= pm_vars
->thePowerStates
[whatStateOrdinal
].inputPowerRequirement
;
2125 priv
->changeList
->changeNote
[newNote
].capabilityFlags
= pm_vars
->thePowerStates
[whatStateOrdinal
].capabilityFlags
;
2126 priv
->changeList
->changeNote
[newNote
].flags
= flags
;
2127 priv
->changeList
->changeNote
[newNote
].parent
= NULL
;
2128 if (flags
& IOPMParentInitiated
)
2130 priv
->changeList
->changeNote
[newNote
].domainState
= domainState
;
2131 priv
->changeList
->changeNote
[newNote
].parent
= whichParent
;
2132 whichParent
->retain();
2133 priv
->changeList
->changeNote
[newNote
].singleParentState
= singleParentState
;
2136 previousNote
= priv
->changeList
->previousChangeNote(newNote
);
2138 if ( previousNote
== -1 )
2141 // Queue is empty, we can start this change.
2143 if (flags
& IOPMWeInitiated
)
2145 IOLockUnlock(priv
->queue_lock
);
2146 start_our_change(newNote
);
2149 IOLockUnlock(priv
->queue_lock
);
2150 return start_parent_change(newNote
);
2154 // The queue is not empty. Try to collapse this new change and the previous one in queue into one change.
2155 // This is possible only if both changes are initiated by us, and neither has been started yet.
2156 // Do this more than once if possible.
2158 // (A change is started iff it is at the head of the queue)
2160 while ( (previousNote
!= priv
->head_note
) && (previousNote
!= -1) &&
2161 (priv
->changeList
->changeNote
[newNote
].flags
& priv
->changeList
->changeNote
[previousNote
].flags
& IOPMWeInitiated
) )
2163 priv
->changeList
->changeNote
[previousNote
].outputPowerCharacter
= priv
->changeList
->changeNote
[newNote
].outputPowerCharacter
;
2164 priv
->changeList
->changeNote
[previousNote
].inputPowerRequirement
= priv
->changeList
->changeNote
[newNote
].inputPowerRequirement
;
2165 priv
->changeList
->changeNote
[previousNote
].capabilityFlags
=priv
-> changeList
->changeNote
[newNote
].capabilityFlags
;
2166 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogCollapseQueue
,priv
->changeList
->changeNote
[newNote
].newStateNumber
,
2167 priv
->changeList
->changeNote
[previousNote
].newStateNumber
);
2168 priv
->changeList
->changeNote
[previousNote
].newStateNumber
= priv
->changeList
->changeNote
[newNote
].newStateNumber
;
2169 priv
->changeList
->releaseTailChangeNote();
2170 newNote
= previousNote
;
2171 previousNote
= priv
->changeList
->previousChangeNote(newNote
);
2173 IOLockUnlock(priv
->queue_lock
);
2174 // in any case, we can't start yet
2175 return IOPMWillAckLater
;
2178 //*********************************************************************************
2181 // Notify all interested parties either that a change is impending or that the
2182 // previously-notified change is done and power has settled.
2183 // The parameter identifies whether this is the
2184 // pre-change notification or the post-change notification.
2186 //*********************************************************************************
2188 IOReturn
IOService::notifyAll ( bool is_prechange
)
2190 IOPMinformee
* nextObject
;
2193 IOPowerConnection
* connection
;
2195 // To prevent acknowledgePowerChange from finishing the change note and removing it from the queue if
2196 // some driver calls it, we inflate the number of pending acks so it cannot become zero. We'll fix it later.
2198 priv
->head_note_pendingAcks
=1;
2200 // OK, we will go through the lists of interested drivers and power domain children
2201 // and notify each one of this change.
2203 nextObject
= priv
->interestedDrivers
->firstInList();
2204 while ( nextObject
!= NULL
) {
2205 priv
->head_note_pendingAcks
+=1;
2206 if (! inform(nextObject
, is_prechange
) )
2209 nextObject
= priv
->interestedDrivers
->nextInList(nextObject
);
2212 if (! acquire_lock() ) {
2215 // did they all ack?
2216 if ( priv
->head_note_pendingAcks
> 1 ) {
2218 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2222 IOUnlock(priv
->our_lock
);
2225 iter
= getChildIterator(gIOPowerPlane
);
2226 // summing their power consumption
2227 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
= 0;
2231 while ( (next
= iter
->getNextObject()) )
2233 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
2235 priv
->head_note_pendingAcks
+=1;
2236 notifyChild(connection
, is_prechange
);
2242 if (! acquire_lock() ) {
2245 // now make this real
2246 priv
->head_note_pendingAcks
-= 1;
2248 if (priv
->head_note_pendingAcks
== 0 ) {
2250 IOUnlock(priv
->our_lock
);
2251 // return ack to parent
2252 return IOPMAckImplied
;
2256 IOUnlock(priv
->our_lock
);
2257 return IOPMWillAckLater
;
2261 //*********************************************************************************
2264 // Notify a power domain child of an upcoming power change.
2266 // If the object acknowledges the current change, we return TRUE.
2267 //*********************************************************************************
2269 bool IOService::notifyChild ( IOPowerConnection
* theNub
, bool is_prechange
)
2271 IOReturn k
= IOPMAckImplied
;
2272 unsigned long childPower
;
2273 IOService
*theChild
;
2275 theChild
= (IOService
*)(theNub
->copyChildEntry(gIOPowerPlane
));
2278 // The child has been detached since we grabbed the child iterator.
2279 // Decrement pending_acks, already incremented in notifyAll,
2280 // to account for this unexpected departure.
2281 priv
->head_note_pendingAcks
--;
2285 // Unless the child handles the notification immediately and returns
2286 // kIOPMAckImplied, we'll be awaiting their acknowledgement later.
2287 theNub
->setAwaitingAck(true);
2291 k
= theChild
->powerDomainWillChangeTo(priv
->head_note_outputFlags
,theNub
);
2293 k
= theChild
->powerDomainDidChangeTo(priv
->head_note_outputFlags
,theNub
);
2296 // did the return code ack?
2297 if ( k
== IOPMAckImplied
)
2300 priv
->head_note_pendingAcks
--;
2301 theNub
->setAwaitingAck(false);
2302 childPower
= theChild
->currentPowerConsumption();
2303 if ( childPower
== kIOPMUnknown
)
2305 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
= kIOPMUnknown
;
2307 if ( pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
!= kIOPMUnknown
)
2309 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
+= childPower
;
2312 theChild
->release();
2315 theChild
->release();
2320 //*********************************************************************************
2323 // Notify an interested driver of an upcoming power change.
2325 // If the object acknowledges the current change, we return TRUE.
2326 //*********************************************************************************
2328 bool IOService::inform ( IOPMinformee
* nextObject
, bool is_prechange
)
2330 IOReturn k
= IOPMAckImplied
;
2333 nextObject
->timer
= -1;
2337 pm_vars
->thePlatform
->PMLog (pm_vars
->ourName
,PMlogInformDriverPreChange
,
2338 (unsigned long)priv
->head_note_capabilityFlags
,(unsigned long)priv
->head_note_state
);
2339 k
= nextObject
->whatObject
->powerStateWillChangeTo( priv
->head_note_capabilityFlags
,priv
->head_note_state
,this);
2341 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInformDriverPostChange
,
2342 (unsigned long)priv
->head_note_capabilityFlags
,(unsigned long)priv
->head_note_state
);
2343 k
= nextObject
->whatObject
->powerStateDidChangeTo(priv
->head_note_capabilityFlags
,priv
->head_note_state
,this);
2346 // did it ack behind our back?
2347 if ( nextObject
->timer
== 0 )
2353 // no, did the return code ack?
2354 if ( k
==IOPMAckImplied
)
2357 nextObject
->timer
= 0;
2358 priv
->head_note_pendingAcks
-= 1;
2364 nextObject
->timer
= 0;
2365 priv
-> head_note_pendingAcks
-= 1;
2370 nextObject
->timer
= (k
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
2376 //*********************************************************************************
2377 // OurChangeTellClientsPowerDown
2379 // All registered applications and kernel clients have positively acknowledged our
2380 // intention of lowering power. Here we notify them all that we will definitely
2381 // lower the power. If we don't have to wait for any of them to acknowledge, we
2382 // carry on by notifying interested drivers. Otherwise, we do wait.
2383 //*********************************************************************************
2385 void IOService::OurChangeTellClientsPowerDown ( void )
2388 priv
->machine_state
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
2390 // are we waiting for responses?
2391 if ( tellChangeDown1(priv
->head_note_state
) )
2393 // no, notify priority clients
2394 OurChangeTellPriorityClientsPowerDown();
2396 // If we are waiting for responses, execution will resume via
2397 // allowCancelCommon() or ack timeout
2401 //*********************************************************************************
2402 // OurChangeTellPriorityClientsPowerDown
2404 // All registered applications and kernel clients have positively acknowledged our
2405 // intention of lowering power. Here we notify "priority" clients that we are
2406 // lowering power. If we don't have to wait for any of them to acknowledge, we
2407 // carry on by notifying interested drivers. Otherwise, we do wait.
2408 //*********************************************************************************
2410 void IOService::OurChangeTellPriorityClientsPowerDown ( void )
2413 priv
->machine_state
= kIOPM_OurChangeNotifyInterestedDriversWillChange
;
2414 // are we waiting for responses?
2415 if ( tellChangeDown2(priv
->head_note_state
) )
2417 // no, notify interested drivers
2418 return OurChangeNotifyInterestedDriversWillChange();
2420 // If we are waiting for responses, execution will resume via
2421 // allowCancelCommon() or ack timeout
2425 //*********************************************************************************
2426 // OurChangeNotifyInterestedDriversWillChange
2428 // All registered applications and kernel clients have acknowledged our notification
2429 // that we are lowering power. Here we notify interested drivers. If we don't have
2430 // to wait for any of them to acknowledge, we instruct our power driver to make the change.
2431 // Otherwise, we do wait.
2432 //*********************************************************************************
2434 void IOService::OurChangeNotifyInterestedDriversWillChange ( void )
2436 // no, in case they don't all ack
2437 priv
->machine_state
= kIOPM_OurChangeSetPowerState
;
2438 if ( notifyAll(true) == IOPMAckImplied
)
2440 // not waiting for responses
2441 OurChangeSetPowerState();
2443 // If we are waiting for responses, execution will resume via
2444 // all_acked() or ack timeout
2448 //*********************************************************************************
2449 // OurChangeSetPowerState
2451 // All interested drivers have acknowledged our pre-change notification of a power
2452 // change we initiated. Here we instruct our controlling driver to make
2453 // the change to the hardware. If it does so, we continue processing
2454 // (waiting for settle and notifying interested parties post-change.)
2455 // If it doesn't, we have to wait for it to acknowledge and then continue.
2456 //*********************************************************************************
2458 void IOService::OurChangeSetPowerState ( void )
2460 priv
->machine_state
= kIOPM_OurChangeWaitForPowerSettle
;
2462 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2464 // it's done, carry on
2465 OurChangeWaitForPowerSettle();
2467 // it's not, wait for it
2468 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2470 // execution will resume via ack_timer_ticked()
2475 //*********************************************************************************
2476 // OurChangeWaitForPowerSettle
2478 // Our controlling driver has changed power state on the hardware
2479 // during a power change we initiated. Here we see if we need to wait
2480 // for power to settle before continuing. If not, we continue processing
2481 // (notifying interested parties post-change). If so, we wait and
2483 //*********************************************************************************
2485 void IOService::OurChangeWaitForPowerSettle ( void )
2487 priv
->settle_time
= compute_settle_time();
2488 if ( priv
->settle_time
== 0 )
2490 OurChangeNotifyInterestedDriversDidChange();
2492 priv
->machine_state
= kIOPM_OurChangeNotifyInterestedDriversDidChange
;
2493 startSettleTimer(priv
->settle_time
);
2498 //*********************************************************************************
2499 // OurChangeNotifyInterestedDriversDidChange
2501 // Power has settled on a power change we initiated. Here we notify
2502 // all our interested parties post-change. If they all acknowledge, we're
2503 // done with this change note, and we can start on the next one.
2504 // Otherwise we have to wait for acknowledgements and finish up later.
2505 //*********************************************************************************
2507 void IOService::OurChangeNotifyInterestedDriversDidChange ( void )
2509 // in case they don't all ack
2510 priv
->machine_state
= kIOPM_OurChangeFinish
;
2511 if ( notifyAll(false) == IOPMAckImplied
)
2513 // not waiting for responses
2516 // If we are waiting for responses, execution will resume via
2517 // all_acked() or ack timeout
2521 //*********************************************************************************
2524 // Power has settled on a power change we initiated, and
2525 // all our interested parties have acknowledged. We're
2526 // done with this change note, and we can start on the next one.
2527 //*********************************************************************************
2529 void IOService::OurChangeFinish ( void )
2535 //*********************************************************************************
2536 // ParentDownTellPriorityClientsPowerDown_Immediate
2538 // All applications and kernel clients have been notified of a power lowering
2539 // initiated by the parent and we didn't have to wait for any responses. Here
2540 // we notify any priority clients. If they all ack, we continue with the power change.
2541 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2542 //*********************************************************************************
2544 IOReturn
IOService::ParentDownTellPriorityClientsPowerDown_Immediate ( void )
2546 // in case they don't all ack
2547 priv
->machine_state
= kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
;
2548 // are we waiting for responses?
2549 if ( tellChangeDown2(priv
->head_note_state
) )
2551 // no, notify interested drivers
2552 return ParentDownNotifyInterestedDriversWillChange_Immediate();
2554 // If we are waiting for responses, execution will resume via
2555 // allowCancelCommon() or ack timeout
2556 return IOPMWillAckLater
;
2560 //*********************************************************************************
2561 // ParentDownTellPriorityClientsPowerDown_Immediate2
2563 // All priority kernel clients have been notified of a power lowering
2564 // initiated by the parent and we didn't have to wait for any responses. Here
2565 // we notify any interested drivers and power domain children. If they all ack,
2566 // we continue with the power change.
2567 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2568 //*********************************************************************************
2570 IOReturn
IOService::ParentDownNotifyInterestedDriversWillChange_Immediate ( void )
2572 // in case they don't all ack
2573 priv
->machine_state
= kIOPM_ParentDownSetPowerState_Delayed
;
2574 if ( notifyAll(true) == IOPMAckImplied
)
2577 return ParentDownSetPowerState_Immediate();
2579 // If we are waiting for responses, execution will resume via
2580 // all_acked() or ack timeout
2581 return IOPMWillAckLater
;
2585 //*********************************************************************************
2586 // ParentDownTellPriorityClientsPowerDown_Immediate4
2588 // All applications and kernel clients have been notified of a power lowering
2589 // initiated by the parent and we had to wait for responses. Here
2590 // we notify any priority clients. If they all ack, we continue with the power change.
2591 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2592 //*********************************************************************************
2594 void IOService::ParentDownTellPriorityClientsPowerDown_Delayed ( void )
2596 // in case they don't all ack
2597 priv
->machine_state
= kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
;
2599 // are we waiting for responses?
2600 if ( tellChangeDown2(priv
->head_note_state
) )
2602 // no, notify interested drivers
2603 ParentDownNotifyInterestedDriversWillChange_Delayed();
2605 // If we are waiting for responses, execution will resume via
2606 // allowCancelCommon() or ack timeout
2610 //*********************************************************************************
2611 // ParentDownTellPriorityClientsPowerDown_Immediate5
2613 // All applications and kernel clients have been notified of a power lowering
2614 // initiated by the parent and we had to wait for their responses. Here we notify
2615 // any interested drivers and power domain children. If they all ack, we continue
2616 // with the power change.
2617 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2618 //*********************************************************************************
2620 void IOService::ParentDownNotifyInterestedDriversWillChange_Delayed ( void )
2622 // in case they don't all ack
2623 priv
->machine_state
= kIOPM_ParentDownSetPowerState_Delayed
;
2624 if ( notifyAll(true) == IOPMAckImplied
)
2627 ParentDownSetPowerState_Delayed();
2629 // If we are waiting for responses, execution will resume via
2630 // all_acked() or ack timeout
2634 //*********************************************************************************
2635 // ParentDownSetPowerState_Immediate
2637 // All parties have acknowledged our pre-change notification of a power
2638 // lowering initiated by the parent. Here we instruct our controlling driver
2639 // to put the hardware in the state it needs to be in when the domain is
2640 // lowered. If it does so, we continue processing
2641 // (waiting for settle and acknowledging the parent.)
2642 // If it doesn't, we have to wait for it to acknowledge and then continue.
2643 //*********************************************************************************
2645 IOReturn
IOService::ParentDownSetPowerState_Immediate ( void )
2647 priv
->machine_state
= kIOPM_ParentDownWaitForPowerSettle_Delayed
;
2649 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2651 // it's done, carry on
2652 return ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate();
2654 // it's not, wait for it
2655 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2657 return IOPMWillAckLater
;
2661 //*********************************************************************************
2662 // ParentDownSetPowerState_Delayed
2664 // We had to wait for it, but all parties have acknowledged our pre-change
2665 // notification of a power lowering initiated by the parent.
2666 // Here we instruct our controlling driver
2667 // to put the hardware in the state it needs to be in when the domain is
2668 // lowered. If it does so, we continue processing
2669 // (waiting for settle and acknowledging the parent.)
2670 // If it doesn't, we have to wait for it to acknowledge and then continue.
2671 //*********************************************************************************
2673 void IOService::ParentDownSetPowerState_Delayed ( void )
2675 priv
-> machine_state
= kIOPM_ParentDownWaitForPowerSettle_Delayed
;
2677 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2679 // it's done, carry on
2680 ParentDownWaitForPowerSettle_Delayed();
2682 // it's not, wait for it
2683 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2689 //*********************************************************************************
2690 // ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate
2692 // Our controlling driver has changed power state on the hardware
2693 // during a power change initiated by our parent. Here we see if we need
2694 // to wait for power to settle before continuing. If not, we continue
2695 // processing (acknowledging our preparedness to the parent).
2696 // If so, we wait and continue later.
2697 //*********************************************************************************
2699 IOReturn
IOService::ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate ( void )
2703 priv
->settle_time
= compute_settle_time();
2704 if ( priv
->settle_time
== 0 )
2706 // store current state in case they don't all ack
2707 priv
->machine_state
= kIOPM_ParentDownAcknowledgeChange_Delayed
;
2708 if ( notifyAll(false) == IOPMAckImplied
)
2710 // not waiting for responses
2711 nub
= priv
->head_note_parent
;
2715 return IOPMAckImplied
;
2717 // If we are waiting for responses, execution will resume via
2718 // all_acked() or ack timeout
2719 return IOPMWillAckLater
;
2721 // let settle time elapse, then notify interest drivers of our power state change in ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
2722 priv
->machine_state
= kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
;
2723 startSettleTimer(priv
->settle_time
);
2724 return IOPMWillAckLater
;
2729 //*********************************************************************************
2730 // ParentDownWaitForPowerSettle_Delayed
2732 // Our controlling driver has changed power state on the hardware
2733 // during a power change initiated by our parent. We have had to wait
2734 // for acknowledgement from interested parties, or we have had to wait
2735 // for the controlling driver to change the state. Here we see if we need
2736 // to wait for power to settle before continuing. If not, we continue
2737 // processing (acknowledging our preparedness to the parent).
2738 // If so, we wait and continue later.
2739 //*********************************************************************************
2741 void IOService::ParentDownWaitForPowerSettle_Delayed ( void )
2743 priv
->settle_time
= compute_settle_time();
2744 if ( priv
->settle_time
== 0 )
2746 ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed();
2748 priv
->machine_state
= kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
;
2749 startSettleTimer(priv
->settle_time
);
2754 //*********************************************************************************
2755 // ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
2757 // Power has settled on a power change initiated by our parent. Here we
2758 // notify interested parties.
2759 //*********************************************************************************
2761 void IOService::ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed ( void )
2763 IORegistryEntry
*nub
;
2766 // in case they don't all ack
2767 priv
->machine_state
= kIOPM_ParentDownAcknowledgeChange_Delayed
;
2768 if ( notifyAll(false) == IOPMAckImplied
) {
2769 nub
= priv
->head_note_parent
;
2772 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
2774 parent
->acknowledgePowerChange((IOService
*)nub
);
2779 // If we are waiting for responses, execution will resume via
2780 // all_acked() or ack timeout in ParentDownAcknowledgeChange_Delayed.
2781 // Notice the duplication of code just above and in ParentDownAcknowledgeChange_Delayed.
2785 //*********************************************************************************
2786 // ParentDownAcknowledgeChange_Delayed
2788 // We had to wait for it, but all parties have acknowledged our post-change
2789 // notification of a power lowering initiated by the parent.
2790 // Here we acknowledge the parent.
2791 // We are done with this change note, and we can start on the next one.
2792 //*********************************************************************************
2794 void IOService::ParentDownAcknowledgeChange_Delayed ( void )
2796 IORegistryEntry
*nub
;
2799 nub
= priv
->head_note_parent
;
2802 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
2805 parent
->acknowledgePowerChange((IOService
*)nub
);
2812 //*********************************************************************************
2813 // ParentUpSetPowerState_Delayed
2815 // Our parent has informed us via powerStateDidChange that it has
2816 // raised the power in our power domain, and we have had to wait
2817 // for some interested party to acknowledge our notification.
2818 // Here we instruct our controlling
2819 // driver to program the hardware to take advantage of the higher domain
2820 // power. If it does so, we continue processing
2821 // (waiting for settle and notifying interested parties post-change.)
2822 // If it doesn't, we have to wait for it to acknowledge and then continue.
2823 //*********************************************************************************
2825 void IOService::ParentUpSetPowerState_Delayed ( void )
2827 priv
->machine_state
= kIOPM_ParentUpWaitForSettleTime_Delayed
;
2829 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2831 // it did it, carry on
2832 ParentUpWaitForSettleTime_Delayed();
2834 // it didn't, wait for it
2835 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2841 //*********************************************************************************
2842 // ParentUpSetPowerState_Immediate
2844 // Our parent has informed us via powerStateDidChange that it has
2845 // raised the power in our power domain. Here we instruct our controlling
2846 // driver to program the hardware to take advantage of the higher domain
2847 // power. If it does so, we continue processing
2848 // (waiting for settle and notifying interested parties post-change.)
2849 // If it doesn't, we have to wait for it to acknowledge and then continue.
2850 //*********************************************************************************
2852 IOReturn
IOService::ParentUpSetPowerState_Immediate ( void )
2854 priv
->machine_state
= kIOPM_ParentUpWaitForSettleTime_Delayed
;
2856 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2858 // it did it, carry on
2859 return ParentUpWaitForSettleTime_Immediate();
2862 // it didn't, wait for it
2863 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2865 return IOPMWillAckLater
;
2870 //*********************************************************************************
2871 // ParentUpWaitForSettleTime_Immediate
2873 // Our controlling driver has changed power state on the hardware
2874 // during a power raise initiated by the parent. Here we see if we need to wait
2875 // for power to settle before continuing. If not, we continue processing
2876 // (notifying interested parties post-change). If so, we wait and
2878 //*********************************************************************************
2880 IOReturn
IOService::ParentUpWaitForSettleTime_Immediate ( void )
2882 priv
->settle_time
= compute_settle_time();
2883 if ( priv
->settle_time
== 0 )
2885 return ParentUpNotifyInterestedDriversDidChange_Immediate();
2887 priv
->machine_state
= kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed
;
2888 startSettleTimer(priv
->settle_time
);
2889 return IOPMWillAckLater
;
2894 //*********************************************************************************
2895 // ParentUpWaitForSettleTime_Delayed
2897 // Our controlling driver has changed power state on the hardware
2898 // during a power raise initiated by the parent, but we had to wait for it.
2899 // Here we see if we need to wait for power to settle before continuing.
2900 // If not, we continue processing (notifying interested parties post-change).
2901 // If so, we wait and continue later.
2902 //*********************************************************************************
2904 void IOService::ParentUpWaitForSettleTime_Delayed ( void )
2906 priv
->settle_time
= compute_settle_time();
2907 if ( priv
->settle_time
== 0 )
2909 ParentUpNotifyInterestedDriversDidChange_Delayed();
2911 priv
->machine_state
= kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed
;
2912 startSettleTimer(priv
->settle_time
);
2917 //*********************************************************************************
2918 // ParentUpNotifyInterestedDriversDidChange_Immediate
2920 // No power settling was required on a power raise initiated by the parent.
2921 // Here we notify all our interested parties post-change. If they all acknowledge,
2922 // we're done with this change note, and we can start on the next one.
2923 // Otherwise we have to wait for acknowledgements and finish up later.
2924 //*********************************************************************************
2926 IOReturn
IOService::ParentUpNotifyInterestedDriversDidChange_Immediate ( void )
2930 // in case they don't all ack
2931 priv
->machine_state
= kIOPM_ParentUpAcknowledgePowerChange_Delayed
;
2932 if ( notifyAll(false) == IOPMAckImplied
)
2934 nub
= priv
->head_note_parent
;
2938 return IOPMAckImplied
;
2940 // If we are waiting for responses, execution will resume via
2941 // all_acked() or ack timeout in ParentUpAcknowledgePowerChange_Delayed.
2942 return IOPMWillAckLater
;
2946 //*********************************************************************************
2947 // ParentUpNotifyInterestedDriversDidChange_Delayed
2949 // Power has settled on a power raise initiated by the parent.
2950 // Here we notify all our interested parties post-change. If they all acknowledge,
2951 // we're done with this change note, and we can start on the next one.
2952 // Otherwise we have to wait for acknowledgements and finish up later.
2953 //*********************************************************************************
2955 void IOService::ParentUpNotifyInterestedDriversDidChange_Delayed ( void )
2957 // in case they don't all ack
2958 priv
->machine_state
= kIOPM_ParentUpAcknowledgePowerChange_Delayed
;
2959 if ( notifyAll(false) == IOPMAckImplied
)
2961 ParentUpAcknowledgePowerChange_Delayed();
2963 // If we are waiting for responses, execution will resume via
2964 // all_acked() or ack timeout in ParentUpAcknowledgePowerChange_Delayed.
2968 //*********************************************************************************
2969 // ParentUpAcknowledgePowerChange_Delayed
2971 // All parties have acknowledged our post-change notification of a power
2972 // raising initiated by the parent. Here we acknowledge the parent.
2973 // We are done with this change note, and we can start on the next one.
2974 //*********************************************************************************
2976 void IOService::ParentUpAcknowledgePowerChange_Delayed ( void )
2978 IORegistryEntry
*nub
;
2981 nub
= priv
->head_note_parent
;
2984 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
2987 parent
->acknowledgePowerChange((IOService
*)nub
);
2994 //*********************************************************************************
2997 // A power change is complete, and the used post-change note is at
2998 // the head of the queue. Remove it and set myCurrentState to the result
2999 // of the change. Start up the next change in queue.
3000 //*********************************************************************************
3002 void IOService::all_done ( void )
3004 unsigned long previous_state
;
3005 IORegistryEntry
*nub
;
3008 priv
->machine_state
= kIOPM_Finished
;
3011 if ( priv
->head_note_flags
& IOPMWeInitiated
)
3013 // could our driver switch to the new state?
3014 if ( !( priv
->head_note_flags
& IOPMNotDone
) )
3016 // yes, did power raise?
3017 if ( pm_vars
->myCurrentState
< priv
->head_note_state
)
3019 // yes, inform clients and apps
3020 tellChangeUp (priv
->head_note_state
);
3022 // no, if this lowers our
3023 if ( ! priv
->we_are_root
)
3025 // power requirements, tell the parent
3026 ask_parent(priv
->head_note_state
);
3029 previous_state
= pm_vars
->myCurrentState
;
3031 pm_vars
->myCurrentState
= priv
->head_note_state
;
3032 priv
->imminentState
= pm_vars
->myCurrentState
;
3033 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeDone
,(unsigned long)pm_vars
->myCurrentState
,0);
3034 // inform subclass policy-maker
3035 powerChangeDone(previous_state
);
3039 // parent's power change
3040 if ( priv
->head_note_flags
& IOPMParentInitiated
)
3042 if ( ((priv
->head_note_flags
& IOPMDomainWillChange
) && (pm_vars
->myCurrentState
>= priv
->head_note_state
)) ||
3043 ((priv
->head_note_flags
& IOPMDomainDidChange
) && (pm_vars
->myCurrentState
< priv
->head_note_state
)) )
3046 if ( pm_vars
->myCurrentState
< priv
->head_note_state
)
3048 // yes, inform clients and apps
3049 tellChangeUp (priv
->head_note_state
);
3052 previous_state
= pm_vars
->myCurrentState
;
3053 pm_vars
->myCurrentState
= priv
->head_note_state
;
3054 priv
->imminentState
= pm_vars
->myCurrentState
;
3055 pm_vars
->maxCapability
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(priv
->head_note_domainState
);
3057 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeDone
,(unsigned long)pm_vars
->myCurrentState
,0);
3058 // inform subclass policy-maker
3059 powerChangeDone(previous_state
);
3063 IOLockLock(priv
->queue_lock
);
3064 // we're done with this
3065 priv
->changeList
->releaseHeadChangeNote();
3067 // start next one in queue
3068 priv
->head_note
= priv
->changeList
->currentChange();
3069 if ( priv
->head_note
!= -1 )
3072 IOLockUnlock(priv
->queue_lock
);
3073 if (priv
->changeList
->changeNote
[priv
->head_note
].flags
& IOPMWeInitiated
)
3075 start_our_change(priv
->head_note
);
3077 nub
= priv
->changeList
->changeNote
[priv
->head_note
].parent
;
3078 if ( start_parent_change(priv
->head_note
) == IOPMAckImplied
)
3080 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
3083 parent
->acknowledgePowerChange((IOService
*)nub
);
3089 IOLockUnlock(priv
->queue_lock
);
3095 //*********************************************************************************
3098 // A driver or child has acknowledged our notification of an upcoming power
3099 // change, and this acknowledgement is the last one pending
3100 // before we change power or after changing power.
3102 //*********************************************************************************
3104 void IOService::all_acked ( void )
3106 switch (priv
->machine_state
) {
3107 case kIOPM_OurChangeSetPowerState
:
3108 OurChangeSetPowerState();
3110 case kIOPM_OurChangeFinish
:
3113 case kIOPM_ParentDownSetPowerState_Delayed
:
3114 ParentDownSetPowerState_Delayed();
3116 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3117 ParentDownAcknowledgeChange_Delayed();
3119 case kIOPM_ParentUpSetPowerState_Delayed
:
3120 ParentUpSetPowerState_Delayed();
3122 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3123 ParentUpAcknowledgePowerChange_Delayed();
3128 //*********************************************************************************
3129 // settleTimerExpired
3131 // Power has settled after our last change. Notify interested parties that
3132 // there is a new power state.
3133 //*********************************************************************************
3135 void IOService::settleTimerExpired ( void )
3137 if ( ! initialized
)
3143 switch (priv
->machine_state
) {
3144 case kIOPM_OurChangeNotifyInterestedDriversDidChange
:
3145 OurChangeNotifyInterestedDriversDidChange();
3147 case kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
:
3148 ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed();
3150 case kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed
:
3151 ParentUpNotifyInterestedDriversDidChange_Delayed();
3157 //*********************************************************************************
3158 // compute_settle_time
3160 // Compute the power-settling delay in microseconds for the
3161 // change from myCurrentState to head_note_state.
3162 //*********************************************************************************
3164 unsigned long IOService::compute_settle_time ( void )
3166 unsigned long totalTime
;
3169 // compute total time to attain the new state
3171 i
= pm_vars
->myCurrentState
;
3173 // we're lowering power
3174 if ( priv
->head_note_state
< pm_vars
->myCurrentState
)
3176 while ( i
> priv
->head_note_state
)
3178 totalTime
+= pm_vars
->thePowerStates
[i
].settleDownTime
;
3183 // we're raising power
3184 if ( priv
->head_note_state
> pm_vars
->myCurrentState
)
3186 while ( i
< priv
->head_note_state
)
3188 totalTime
+= pm_vars
->thePowerStates
[i
+1].settleUpTime
;
3197 //*********************************************************************************
3200 // Enter with a power-settling delay in microseconds and start a nano-second
3201 // timer for that delay.
3202 //*********************************************************************************
3204 IOReturn
IOService::startSettleTimer ( unsigned long delay
)
3206 AbsoluteTime deadline
;
3208 clock_interval_to_deadline(delay
, kMicrosecondScale
, &deadline
);
3210 thread_call_enter_delayed(priv
->settleTimer
, deadline
);
3215 //*********************************************************************************
3218 // The acknowledgement timeout periodic timer has ticked.
3219 // If we are awaiting acks for a power change notification,
3220 // we decrement the timer word of each interested driver which hasn't acked.
3221 // If a timer word becomes zero, we pretend the driver aknowledged.
3222 // If we are waiting for the controlling driver to change the power
3223 // state of the hardware, we decrement its timer word, and if it becomes
3224 // zero, we pretend the driver acknowledged.
3225 //*********************************************************************************
3227 void IOService::ack_timer_ticked ( void )
3229 IOPMinformee
* nextObject
;
3231 if ( ! initialized
)
3237 if (! acquire_lock() )
3242 switch (priv
->machine_state
) {
3243 case kIOPM_OurChangeWaitForPowerSettle
:
3244 case kIOPM_ParentDownWaitForPowerSettle_Delayed
:
3245 case kIOPM_ParentUpWaitForSettleTime_Delayed
:
3246 // are we waiting for our driver to make its change?
3247 if ( priv
->driver_timer
!= 0 ) {
3249 priv
->driver_timer
-= 1;
3250 // it's tardy, we'll go on without it
3251 if ( priv
->driver_timer
== 0 )
3253 IOUnlock(priv
->our_lock
);
3254 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogCtrlDriverTardy
,0,0);
3257 // still waiting, set timer again
3259 IOUnlock(priv
->our_lock
);
3263 IOUnlock(priv
->our_lock
);
3267 case kIOPM_OurChangeSetPowerState
:
3268 case kIOPM_OurChangeFinish
:
3269 case kIOPM_ParentDownSetPowerState_Delayed
:
3270 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3271 case kIOPM_ParentUpSetPowerState_Delayed
:
3272 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3273 // are we waiting for interested parties to acknowledge?
3274 if (priv
->head_note_pendingAcks
!= 0 )
3276 // yes, go through the list of interested drivers
3277 nextObject
= priv
->interestedDrivers
->firstInList();
3278 // and check each one
3279 while ( nextObject
!= NULL
)
3281 if ( nextObject
->timer
> 0 )
3283 nextObject
->timer
-= 1;
3284 // this one should have acked by now
3285 if ( nextObject
->timer
== 0 )
3287 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogIntDriverTardy
,0,0);
3288 //kprintf("interested driver tardy: %s\n",nextObject->whatObject->getName());
3289 priv
->head_note_pendingAcks
-= 1;
3292 nextObject
= priv
->interestedDrivers
->nextInList(nextObject
);
3295 // is that the last?
3296 if ( priv
->head_note_pendingAcks
== 0 )
3298 IOUnlock(priv
->our_lock
);
3299 // yes, we can continue
3302 // no, set timer again
3304 IOUnlock(priv
->our_lock
);
3307 IOUnlock(priv
->our_lock
);
3311 // apps didn't respond to parent-down notification
3312 case kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate
:
3313 IOUnlock(priv
->our_lock
);
3314 IOLockLock(priv
->flags_lock
);
3315 if (pm_vars
->responseFlags
)
3317 // get rid of this stuff
3318 pm_vars
->responseFlags
->release();
3319 pm_vars
->responseFlags
= NULL
;
3321 IOLockUnlock(priv
->flags_lock
);
3322 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,5);
3323 // carry on with the change
3324 ParentDownTellPriorityClientsPowerDown_Delayed();
3327 case kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
:
3328 IOUnlock(priv
->our_lock
);
3329 IOLockLock(priv
->flags_lock
);
3330 if (pm_vars
->responseFlags
)
3332 // get rid of this stuff
3333 pm_vars
->responseFlags
->release();
3334 pm_vars
->responseFlags
= NULL
;
3336 IOLockUnlock(priv
->flags_lock
);
3337 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,1);
3338 // carry on with the change
3339 ParentDownNotifyInterestedDriversWillChange_Delayed();
3342 case kIOPM_OurChangeTellClientsPowerDown
:
3343 // apps didn't respond to our power-down request
3344 IOUnlock(priv
->our_lock
);
3345 IOLockLock(priv
->flags_lock
);
3346 if (pm_vars
->responseFlags
)
3348 // get rid of this stuff
3349 pm_vars
->responseFlags
->release();
3350 pm_vars
->responseFlags
= NULL
;
3352 IOLockUnlock(priv
->flags_lock
);
3353 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,2);
3354 // rescind the request
3355 tellNoChangeDown(priv
->head_note_state
);
3356 // mark the change note un-actioned
3357 priv
->head_note_flags
|= IOPMNotDone
;
3362 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
3363 // clients didn't respond to our power-down note
3364 IOUnlock(priv
->our_lock
);
3365 IOLockLock(priv
->flags_lock
);
3366 if (pm_vars
->responseFlags
)
3368 // get rid of this stuff
3369 pm_vars
->responseFlags
->release();
3370 pm_vars
->responseFlags
= NULL
;
3372 IOLockUnlock(priv
->flags_lock
);
3373 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,4);
3374 // carry on with the change
3375 OurChangeTellPriorityClientsPowerDown();
3378 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
3379 // apps didn't respond to our power-down notification
3380 IOUnlock(priv
->our_lock
);
3381 IOLockLock(priv
->flags_lock
);
3382 if (pm_vars
->responseFlags
)
3384 // get rid of this stuff
3385 pm_vars
->responseFlags
->release();
3386 pm_vars
->responseFlags
= NULL
;
3388 IOLockUnlock(priv
->flags_lock
);
3389 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,3);
3390 // carry on with the change
3391 OurChangeNotifyInterestedDriversWillChange();
3395 // not waiting for acks
3396 IOUnlock(priv
->our_lock
);
3402 //*********************************************************************************
3405 //*********************************************************************************
3407 void IOService::start_ack_timer ( void )
3409 AbsoluteTime deadline
;
3411 clock_interval_to_deadline(ACK_TIMER_PERIOD
, kNanosecondScale
, &deadline
);
3413 thread_call_enter_delayed(priv
->ackTimer
, deadline
);
3417 //*********************************************************************************
3420 //*********************************************************************************
3422 void IOService::stop_ack_timer ( void )
3424 thread_call_cancel(priv
->ackTimer
);
3428 //*********************************************************************************
3429 // c-language timer expiration functions
3431 //*********************************************************************************
3433 static void ack_timer_expired ( thread_call_param_t us
)
3435 ((IOService
*)us
)->ack_timer_ticked();
3439 static void settle_timer_expired ( thread_call_param_t us
)
3441 ((IOService
*)us
)->settleTimerExpired();
3445 //*********************************************************************************
3446 // add_child_to_active_change
3448 // A child has just registered with us. If there is
3449 // currently a change in progress, get the new party involved: if we
3450 // have notified all parties and are waiting for acks, notify the new
3452 //*********************************************************************************
3454 IOReturn
IOService::add_child_to_active_change ( IOPowerConnection
* newObject
)
3456 if (! acquire_lock() )
3461 switch (priv
->machine_state
)
3463 case kIOPM_OurChangeSetPowerState
:
3464 case kIOPM_ParentDownSetPowerState_Delayed
:
3465 case kIOPM_ParentUpSetPowerState_Delayed
:
3466 // one for this child and one to prevent
3467 priv
->head_note_pendingAcks
+= 2;
3468 // incoming acks from changing our state
3469 IOUnlock(priv
->our_lock
);
3470 notifyChild(newObject
, true);
3471 if (! acquire_lock() )
3474 --priv
->head_note_pendingAcks
;
3477 // are we still waiting for acks?
3478 if ( --priv
->head_note_pendingAcks
== 0 )
3480 // no, stop the timer
3482 IOUnlock(priv
->our_lock
);
3484 // and now we can continue
3489 case kIOPM_OurChangeFinish
:
3490 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3491 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3492 // one for this child and one to prevent
3493 priv
->head_note_pendingAcks
+= 2;
3494 // incoming acks from changing our state
3495 IOUnlock(priv
->our_lock
);
3496 notifyChild(newObject
, false);
3497 if (! acquire_lock() )
3500 --priv
->head_note_pendingAcks
;
3503 // are we still waiting for acks?
3504 if ( --priv
->head_note_pendingAcks
== 0 )
3506 // no, stop the timer
3508 IOUnlock(priv
->our_lock
);
3510 // and now we can continue
3516 IOUnlock(priv
->our_lock
);
3521 //*********************************************************************************
3522 // add_driver_to_active_change
3524 // An interested driver has just registered with us. If there is
3525 // currently a change in progress, get the new party involved: if we
3526 // have notified all parties and are waiting for acks, notify the new
3528 //*********************************************************************************
3530 IOReturn
IOService::add_driver_to_active_change ( IOPMinformee
* newObject
)
3532 if (! acquire_lock() )
3537 switch (priv
->machine_state
) {
3538 case kIOPM_OurChangeSetPowerState
:
3539 case kIOPM_ParentDownSetPowerState_Delayed
:
3540 case kIOPM_ParentUpSetPowerState_Delayed
:
3541 // one for this driver and one to prevent
3542 priv
->head_note_pendingAcks
+= 2;
3543 // incoming acks from changing our state
3544 IOUnlock(priv
->our_lock
);
3545 // inform the driver
3546 inform(newObject
, true);
3547 if (! acquire_lock() )
3550 --priv
->head_note_pendingAcks
;
3553 // are we still waiting for acks?
3554 if ( --priv
->head_note_pendingAcks
== 0 )
3556 // no, stop the timer
3558 IOUnlock(priv
->our_lock
);
3560 // and now we can continue
3565 case kIOPM_OurChangeFinish
:
3566 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3567 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3568 // one for this driver and one to prevent
3569 priv
->head_note_pendingAcks
+= 2;
3570 // incoming acks from changing our state
3571 IOUnlock(priv
->our_lock
);
3572 // inform the driver
3573 inform(newObject
, false);
3574 if (! acquire_lock() ) {
3576 --priv
->head_note_pendingAcks
;
3579 // are we still waiting for acks?
3580 if ( --priv
->head_note_pendingAcks
== 0 ) {
3581 // no, stop the timer
3583 IOUnlock(priv
->our_lock
);
3585 // and now we can continue
3591 IOUnlock(priv
->our_lock
);
3596 //*********************************************************************************
3597 // start_parent_change
3599 // Here we begin the processing of a change note initiated by our parent
3600 // which is at the head of the queue.
3602 // It is possible for the change to be processed to completion and removed from the queue.
3603 // There are several possible interruptions to the processing, though, and they are:
3604 // we may have to wait for interested parties to acknowledge our pre-change notification,
3605 // we may have to wait for our controlling driver to change the hardware power state,
3606 // there may be a settling time after changing the hardware power state,
3607 // we may have to wait for interested parties to acknowledge our post-change notification,
3608 // we may have to wait for the acknowledgement timer expiration to substitute for the
3609 // acknowledgement from a failing driver.
3610 //*********************************************************************************
3612 IOReturn
IOService::start_parent_change ( unsigned long queue_head
)
3614 priv
->head_note
= queue_head
;
3615 priv
->head_note_flags
= priv
-> changeList
->changeNote
[priv
->head_note
].flags
;
3616 priv
->head_note_state
= priv
->changeList
->changeNote
[priv
->head_note
].newStateNumber
;
3617 priv
->imminentState
= priv
->head_note_state
;
3618 priv
->head_note_outputFlags
= priv
->changeList
->changeNote
[priv
->head_note
].outputPowerCharacter
;
3619 priv
->head_note_domainState
= priv
->changeList
->changeNote
[priv
->head_note
].domainState
;
3620 priv
->head_note_parent
= priv
->changeList
->changeNote
[priv
->head_note
].parent
;
3621 priv
->head_note_capabilityFlags
= priv
->changeList
->changeNote
[priv
->head_note
].capabilityFlags
;
3623 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartParentChange
,
3624 (unsigned long)priv
->head_note_state
,(unsigned long)pm_vars
->myCurrentState
);
3626 // if we need something and haven't told the parent, do so
3627 ask_parent( priv
->ourDesiredPowerState
);
3629 // power domain is lowering
3630 if ( priv
->head_note_state
< pm_vars
->myCurrentState
)
3632 setParentInfo(priv
->changeList
->changeNote
[priv
->head_note
].singleParentState
,priv
->head_note_parent
);
3633 priv
->initial_change
= false;
3634 // tell apps and kernel clients
3635 priv
->machine_state
= kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate
;
3637 // are we waiting for responses?
3638 if ( tellChangeDown1(priv
->head_note_state
) )
3640 // no, notify priority clients
3641 return ParentDownTellPriorityClientsPowerDown_Immediate();
3644 return IOPMWillAckLater
;
3647 // parent is raising power, we may or may not
3648 if ( priv
->head_note_state
> pm_vars
->myCurrentState
)
3650 if ( priv
->ourDesiredPowerState
> pm_vars
->myCurrentState
)
3652 if ( priv
->ourDesiredPowerState
< priv
->head_note_state
)
3654 // we do, but not all the way
3655 priv
->head_note_state
= priv
->ourDesiredPowerState
;
3656 priv
->imminentState
= priv
->head_note_state
;
3657 priv
->head_note_outputFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].outputPowerCharacter
;
3658 priv
->head_note_capabilityFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].capabilityFlags
;
3659 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAmendParentChange
,(unsigned long)priv
->head_note_state
,0);
3663 priv
->head_note_state
= pm_vars
->myCurrentState
;
3664 priv
->imminentState
= priv
->head_note_state
;
3665 priv
->head_note_outputFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].outputPowerCharacter
;
3666 priv
->head_note_capabilityFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].capabilityFlags
;
3667 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAmendParentChange
,(unsigned long)priv
->head_note_state
,0);
3671 if ( (priv
->head_note_state
> pm_vars
->myCurrentState
) &&
3672 (priv
->head_note_flags
& IOPMDomainDidChange
) )
3675 priv
->initial_change
= false;
3676 priv
->machine_state
= kIOPM_ParentUpSetPowerState_Delayed
;
3677 if ( notifyAll(true) == IOPMAckImplied
) {
3678 return ParentUpSetPowerState_Immediate();
3680 // they didn't all ack
3681 return IOPMWillAckLater
;
3685 // a null change or power will go up
3686 return IOPMAckImplied
;
3690 //*********************************************************************************
3693 // Here we begin the processing of a change note initiated by us
3694 // which is at the head of the queue.
3696 // It is possible for the change to be processed to completion and removed from the queue.
3697 // There are several possible interruptions to the processing, though, and they are:
3698 // we may have to wait for interested parties to acknowledge our pre-change notification,
3699 // changes initiated by the parent will wait in the middle for powerStateDidChange,
3700 // we may have to wait for our controlling driver to change the hardware power state,
3701 // there may be a settling time after changing the hardware power state,
3702 // we may have to wait for interested parties to acknowledge our post-change notification,
3703 // we may have to wait for the acknowledgement timer expiration to substitute for the
3704 // acknowledgement from a failing driver.
3705 //*********************************************************************************
3707 void IOService::start_our_change ( unsigned long queue_head
)
3709 priv
->head_note
= queue_head
;
3710 priv
->head_note_flags
= priv
->changeList
->changeNote
[priv
->head_note
].flags
;
3711 priv
->head_note_state
= priv
->changeList
->changeNote
[priv
->head_note
].newStateNumber
;
3712 priv
->imminentState
= priv
->head_note_state
;
3713 priv
->head_note_outputFlags
= priv
->changeList
->changeNote
[priv
->head_note
].outputPowerCharacter
;
3714 priv
->head_note_capabilityFlags
= priv
->changeList
->changeNote
[priv
->head_note
].capabilityFlags
;
3716 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartDeviceChange
,
3717 (unsigned long)priv
->head_note_state
,(unsigned long)pm_vars
->myCurrentState
);
3719 // can our driver switch to the new state?
3720 if ( priv
->head_note_capabilityFlags
& IOPMNotAttainable
)
3722 // no, ask the parent to do it then
3723 if ( ! priv
->we_are_root
)
3725 ask_parent(priv
->head_note_state
);
3727 // mark the change note un-actioned
3728 priv
-> head_note_flags
|= IOPMNotDone
;
3734 // is there enough power in the domain?
3735 if ( (pm_vars
->maxCapability
< priv
->head_note_state
) && (! priv
->we_are_root
) )
3737 // no, ask the parent to raise it
3738 if ( ! priv
->we_are_root
)
3740 ask_parent(priv
->head_note_state
);
3742 // no, mark the change note un-actioned
3743 priv
->head_note_flags
|= IOPMNotDone
;
3745 // till the parent raises power
3750 if ( ! priv
->initial_change
)
3752 if ( priv
->head_note_state
== pm_vars
->myCurrentState
)
3754 // we initiated a null change; forget it
3759 priv
->initial_change
= false;
3762 if ( priv
->head_note_state
< pm_vars
->myCurrentState
)
3764 // yes, in case we have to wait for acks
3765 priv
->machine_state
= kIOPM_OurChangeTellClientsPowerDown
;
3766 pm_vars
->doNotPowerDown
= false;
3768 // ask apps and kernel clients if we can drop power
3769 pm_vars
->outofbandparameter
= kNotifyApps
;
3770 if ( askChangeDown(priv
->head_note_state
) )
3772 // don't have to wait, did any clients veto?
3773 if ( pm_vars
->doNotPowerDown
)
3775 // yes, rescind the warning
3776 tellNoChangeDown(priv
->head_note_state
);
3777 // mark the change note un-actioned
3778 priv
-> head_note_flags
|= IOPMNotDone
;
3782 // no, tell'em we're dropping power
3783 OurChangeTellClientsPowerDown();
3787 // we are raising power
3788 if ( ! priv
->we_are_root
)
3790 // if this changes our power requirement, tell the parent
3791 ask_parent(priv
->head_note_state
);
3793 // in case they don't all ack
3794 priv
->machine_state
= kIOPM_OurChangeSetPowerState
;
3796 // notify interested drivers and children
3797 if ( notifyAll(true) == IOPMAckImplied
)
3799 OurChangeSetPowerState();
3805 //*********************************************************************************
3808 // Call the power domain parent to ask for a higher power state in the domain
3809 // or to suggest a lower power state.
3810 //*********************************************************************************
3812 IOReturn
IOService::ask_parent ( unsigned long requestedState
)
3816 IOPowerConnection
*connection
;
3818 unsigned long ourRequest
= pm_vars
->thePowerStates
[requestedState
].inputPowerRequirement
;
3820 if ( pm_vars
->thePowerStates
[requestedState
].capabilityFlags
& (kIOPMChildClamp
| kIOPMPreventIdleSleep
) )
3822 ourRequest
|= kIOPMPreventIdleSleep
;
3824 if ( pm_vars
->thePowerStates
[requestedState
].capabilityFlags
& (kIOPMChildClamp2
| kIOPMPreventSystemSleep
) )
3826 ourRequest
|= kIOPMPreventSystemSleep
;
3829 // is this a new desire?
3830 if ( priv
->previousRequest
== ourRequest
)
3832 // no, the parent knows already, just return
3836 if ( priv
->we_are_root
)
3840 priv
->previousRequest
= ourRequest
;
3842 iter
= getParentIterator(gIOPowerPlane
);
3846 while ( (next
= iter
->getNextObject()) )
3848 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
3850 parent
= (IOService
*)connection
->copyParentEntry(gIOPowerPlane
);
3852 if ( parent
->requestPowerDomainState(ourRequest
,connection
,IOPMLowestState
)!= IOPMNoErr
)
3854 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRequestDenied
,
3855 (unsigned long)priv
->previousRequest
,0);
3868 //*********************************************************************************
3871 // Call the controlling driver and have it change the power state of the
3872 // hardware. If it returns IOPMAckImplied, the change is complete, and
3873 // we return IOPMAckImplied. Otherwise, it will ack when the change
3874 // is done; we return IOPMWillAckLater.
3875 //*********************************************************************************
3876 IOReturn
IOService::instruct_driver ( unsigned long newState
)
3880 // can our driver switch to the desired state?
3881 if ( pm_vars
->thePowerStates
[newState
].capabilityFlags
& IOPMNotAttainable
)
3884 return IOPMAckImplied
;
3887 priv
->driver_timer
= -1;
3890 OUR_PMLog( kPMLogProgramHardware
, (UInt32
) this, newState
);
3891 delay
= pm_vars
->theControllingDriver
->setPowerState( newState
,this );
3892 OUR_PMLog((UInt32
) -kPMLogProgramHardware
, (UInt32
) this, (UInt32
) delay
);
3895 if ( delay
== IOPMAckImplied
)
3897 priv
->driver_timer
= 0;
3898 return IOPMAckImplied
;
3901 // it acked behind our back
3902 if ( priv
->driver_timer
== 0 )
3904 return IOPMAckImplied
;
3910 return IOPMAckImplied
;
3914 priv
->driver_timer
= (delay
/ ( ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
3915 return IOPMWillAckLater
;
3919 //*********************************************************************************
3922 // We are acquiring the lock we use to protect our queue head from
3923 // simutaneous access by a thread which calls acknowledgePowerStateChange
3924 // or acknowledgeSetPowerState and the ack timer expiration thread.
3925 // Return TRUE if we acquire the lock, and the queue head didn't change
3926 // while we were acquiring the lock (and maybe blocked).
3927 // If there is no queue head, or it changes while we are blocked,
3928 // return FALSE with the lock unlocked.
3929 //*********************************************************************************
3931 bool IOService::acquire_lock ( void )
3933 long current_change_note
;
3935 current_change_note
= priv
->head_note
;
3936 if ( current_change_note
== -1 ) {
3940 IOTakeLock(priv
->our_lock
);
3941 if ( current_change_note
== priv
->head_note
)
3945 // we blocked and something changed radically
3946 // so there's nothing to do any more
3947 IOUnlock(priv
->our_lock
);
3953 //*********************************************************************************
3956 // Ask registered applications and kernel clients if we can change to a lower
3959 // Subclass can override this to send a different message type. Parameter is
3960 // the destination state number.
3962 // Return true if we don't have to wait for acknowledgements
3963 //*********************************************************************************
3965 bool IOService::askChangeDown ( unsigned long stateNum
)
3967 return tellClientsWithResponse(kIOMessageCanDevicePowerOff
);
3971 //*********************************************************************************
3974 // Notify registered applications and kernel clients that we are definitely
3977 // Return true if we don't have to wait for acknowledgements
3978 //*********************************************************************************
3980 bool IOService::tellChangeDown1 ( unsigned long stateNum
)
3982 pm_vars
->outofbandparameter
= kNotifyApps
;
3983 return tellChangeDown(stateNum
);
3987 //*********************************************************************************
3990 // Notify priority clients that we are definitely dropping power.
3992 // Return true if we don't have to wait for acknowledgements
3993 //*********************************************************************************
3995 bool IOService::tellChangeDown2 ( unsigned long stateNum
)
3997 pm_vars
->outofbandparameter
= kNotifyPriority
;
3998 return tellChangeDown(stateNum
);
4002 //*********************************************************************************
4005 // Notify registered applications and kernel clients that we are definitely
4008 // Subclass can override this to send a different message type. Parameter is
4009 // the destination state number.
4011 // Return true if we don't have to wait for acknowledgements
4012 //*********************************************************************************
4014 bool IOService::tellChangeDown ( unsigned long stateNum
)
4016 return tellClientsWithResponse(kIOMessageDeviceWillPowerOff
);
4020 //*********************************************************************************
4021 // tellClientsWithResponse
4023 // Notify registered applications and kernel clients that we are definitely
4026 // Return true if we don't have to wait for acknowledgements
4027 //*********************************************************************************
4029 bool IOService::tellClientsWithResponse ( int messageType
)
4031 struct context theContext
;
4032 AbsoluteTime deadline
;
4035 pm_vars
->responseFlags
= OSArray::withCapacity( 1 );
4036 pm_vars
->serialNumber
+= 1;
4038 theContext
.responseFlags
= pm_vars
->responseFlags
;
4039 theContext
.serialNumber
= pm_vars
->serialNumber
;
4040 theContext
.flags_lock
= priv
->flags_lock
;
4041 theContext
.counter
= 1;
4042 theContext
.msgType
= messageType
;
4043 theContext
.us
= this;
4044 theContext
.maxTimeRequested
= 0;
4045 theContext
.stateNumber
= priv
->head_note_state
;
4046 theContext
.stateFlags
= priv
->head_note_capabilityFlags
;
4048 IOLockLock(priv
->flags_lock
);
4050 // position zero is false to
4051 // prevent allowCancelCommon from succeeding
4052 aBool
= OSBoolean::withBoolean(false);
4053 theContext
.responseFlags
->setObject(0,aBool
);
4055 IOLockUnlock(priv
->flags_lock
);
4057 switch ( pm_vars
->outofbandparameter
) {
4059 applyToInterested(gIOAppPowerStateInterest
,tellAppWithResponse
,(void *)&theContext
);
4060 applyToInterested(gIOGeneralInterest
,tellClientWithResponse
,(void *)&theContext
);
4062 case kNotifyPriority
:
4063 applyToInterested(gIOPriorityPowerStateInterest
,tellClientWithResponse
,(void *)&theContext
);
4067 if (! acquire_lock() )
4071 IOLockLock(priv
->flags_lock
);
4072 // now fix position zero
4073 aBool
= OSBoolean::withBoolean(true);
4074 theContext
.responseFlags
->replaceObject(0,aBool
);
4076 IOLockUnlock(priv
->flags_lock
);
4078 // do we have to wait for somebody?
4079 if ( ! checkForDone() )
4081 // yes, start the ackTimer
4082 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,theContext
.maxTimeRequested
,0);
4083 clock_interval_to_deadline(theContext
.maxTimeRequested
/ 1000, kMillisecondScale
, &deadline
);
4085 thread_call_enter_delayed(priv
->ackTimer
, deadline
);
4087 IOUnlock(priv
->our_lock
);
4091 IOUnlock(priv
->our_lock
);
4092 IOLockLock(priv
->flags_lock
);
4094 // everybody responded
4095 pm_vars
->responseFlags
->release();
4096 pm_vars
->responseFlags
= NULL
;
4097 IOLockUnlock(priv
->flags_lock
);
4103 //*********************************************************************************
4104 // tellAppWithResponse
4106 // We send a message to an application, and we expect a response, so we compute a
4107 // cookie we can identify the response with.
4108 //*********************************************************************************
4109 void tellAppWithResponse ( OSObject
* object
, void * context
)
4111 struct context
*theContext
= (struct context
*)context
;
4113 IOPMprot
*pm_vars
= theContext
->us
->pm_vars
;
4115 if( OSDynamicCast( IOService
, object
) )
4117 // Automatically 'ack' in kernel clients
4118 IOLockLock(theContext
->flags_lock
);
4119 aBool
= OSBoolean::withBoolean(true);
4120 theContext
->responseFlags
->setObject(theContext
->counter
,aBool
);
4122 IOLockUnlock(theContext
->flags_lock
);
4124 const char *who
= ((IOService
*) object
)->getName();
4125 pm_vars
->thePlatform
->PMLog(who
,
4126 kPMLogClientAcknowledge
, theContext
->msgType
, * (UInt32
*) object
);
4128 UInt32 refcon
= ((theContext
->serialNumber
& 0xFFFF)<<16)
4129 + (theContext
->counter
& 0xFFFF);
4130 IOLockLock(theContext
->flags_lock
);
4131 aBool
= OSBoolean::withBoolean(false);
4132 theContext
->responseFlags
->setObject(theContext
->counter
,aBool
);
4134 IOLockUnlock(theContext
->flags_lock
);
4136 OUR_PMLog(kPMLogAppNotify
, theContext
->msgType
, refcon
);
4137 theContext
->us
->messageClient(theContext
->msgType
,object
,(void *)refcon
);
4138 if ( theContext
->maxTimeRequested
< k30seconds
)
4140 theContext
->maxTimeRequested
= k30seconds
;
4143 theContext
->counter
+= 1;
4146 //*********************************************************************************
4147 // tellClientWithResponse
4149 // We send a message to an in-kernel client, and we expect a response, so we compute a
4150 // cookie we can identify the response with.
4151 // If it doesn't understand the notification (it is not power-management savvy)
4152 // we won't wait for it to prepare for sleep. If it tells us via a return code
4153 // in the passed struct that it is currently ready, we won't wait for it to prepare.
4154 // If it tells us via the return code in the struct that it does need time, we will chill.
4155 //*********************************************************************************
4156 void tellClientWithResponse ( OSObject
* object
, void * context
)
4158 struct context
*theContext
= (struct context
*)context
;
4159 IOPowerStateChangeNotification notify
;
4165 refcon
= ((theContext
->serialNumber
& 0xFFFF)<<16) + (theContext
->counter
& 0xFFFF);
4166 IOLockLock(theContext
->flags_lock
);
4167 aBool
= OSBoolean::withBoolean(false);
4168 theContext
->responseFlags
->setObject(theContext
->counter
,aBool
);
4170 IOLockUnlock(theContext
->flags_lock
);
4172 IOPMprot
*pm_vars
= theContext
->us
->pm_vars
;
4173 if (gIOKitDebug
& kIOLogPower
) {
4174 OUR_PMLog(kPMLogClientNotify
, refcon
, (UInt32
) theContext
->msgType
);
4175 if (OSDynamicCast(IOService
, object
)) {
4176 const char *who
= ((IOService
*) object
)->getName();
4177 pm_vars
->thePlatform
->PMLog(who
,
4178 kPMLogClientNotify
, * (UInt32
*) object
, (UInt32
) object
);
4179 } else if (OSDynamicCast(_IOServiceInterestNotifier
, object
)) {
4180 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
4181 OUR_PMLog(kPMLogClientNotify
, (UInt32
) n
->handler
, 0);
4185 notify
.powerRef
= (void *)refcon
;
4186 notify
.returnValue
= 0;
4187 notify
.stateNumber
= theContext
->stateNumber
;
4188 notify
.stateFlags
= theContext
->stateFlags
;
4189 retCode
= theContext
->us
->messageClient(theContext
->msgType
,object
,(void *)¬ify
);
4190 if ( retCode
== kIOReturnSuccess
)
4192 if ( notify
.returnValue
== 0 )
4194 // client doesn't want time to respond
4195 IOLockLock(theContext
->flags_lock
);
4196 aBool
= OSBoolean::withBoolean(true);
4197 // so set its flag true
4198 theContext
->responseFlags
->replaceObject(theContext
->counter
,aBool
);
4200 IOLockUnlock(theContext
->flags_lock
);
4201 OUR_PMLog(kPMLogClientAcknowledge
, refcon
, (UInt32
) object
);
4203 IOLockLock(theContext
->flags_lock
);
4205 // it does want time, and it hasn't responded yet
4206 theFlag
= theContext
->responseFlags
->getObject(theContext
->counter
);
4209 if ( ((OSBoolean
*)theFlag
)->isFalse() )
4211 // so note its time requirement
4212 if ( theContext
->maxTimeRequested
< notify
.returnValue
)
4214 theContext
->maxTimeRequested
= notify
.returnValue
;
4218 IOLockUnlock(theContext
->flags_lock
);
4221 OUR_PMLog(kPMLogClientAcknowledge
, refcon
, 0);
4222 // not a client of ours
4223 IOLockLock(theContext
->flags_lock
);
4224 // so we won't be waiting for response
4225 aBool
= OSBoolean::withBoolean(true);
4226 theContext
->responseFlags
->replaceObject(theContext
->counter
,aBool
);
4228 IOLockUnlock(theContext
->flags_lock
);
4230 theContext
->counter
+= 1;
4234 //*********************************************************************************
4237 // Notify registered applications and kernel clients that we are not
4240 // Subclass can override this to send a different message type. Parameter is
4241 // the aborted destination state number.
4242 //*********************************************************************************
4244 void IOService::tellNoChangeDown ( unsigned long )
4246 return tellClients(kIOMessageDeviceWillNotPowerOff
);
4250 //*********************************************************************************
4253 // Notify registered applications and kernel clients that we are raising power.
4255 // Subclass can override this to send a different message type. Parameter is
4256 // the aborted destination state number.
4257 //*********************************************************************************
4259 void IOService::tellChangeUp ( unsigned long )
4261 return tellClients(kIOMessageDeviceHasPoweredOn
);
4265 //*********************************************************************************
4268 // Notify registered applications and kernel clients of something.
4269 //*********************************************************************************
4271 void IOService::tellClients ( int messageType
)
4273 struct context theContext
;
4275 theContext
.msgType
= messageType
;
4276 theContext
.us
= this;
4277 theContext
.stateNumber
= priv
->head_note_state
;
4278 theContext
.stateFlags
= priv
->head_note_capabilityFlags
;
4280 applyToInterested(gIOAppPowerStateInterest
,tellClient
,(void *)&theContext
);
4281 applyToInterested(gIOGeneralInterest
,tellClient
,(void *)&theContext
);
4285 //*********************************************************************************
4288 // Notify a registered application or kernel client of something.
4289 //*********************************************************************************
4290 void tellClient ( OSObject
* object
, void * context
)
4292 struct context
*theContext
= (struct context
*)context
;
4293 IOPowerStateChangeNotification notify
;
4295 notify
.powerRef
= (void *) 0;
4296 notify
.returnValue
= 0;
4297 notify
.stateNumber
= theContext
->stateNumber
;
4298 notify
.stateFlags
= theContext
->stateFlags
;
4300 theContext
->us
->messageClient(theContext
->msgType
,object
, ¬ify
);
4304 // **********************************************************************************
4307 // **********************************************************************************
4308 bool IOService::checkForDone ( void )
4313 IOLockLock(priv
->flags_lock
);
4314 if ( pm_vars
->responseFlags
== NULL
)
4316 IOLockUnlock(priv
->flags_lock
);
4320 for ( i
= 0; ; i
++ )
4322 theFlag
= pm_vars
->responseFlags
->getObject(i
);
4323 if ( theFlag
== NULL
)
4327 if ( ((OSBoolean
*)theFlag
)->isFalse() )
4329 IOLockUnlock(priv
->flags_lock
);
4333 IOLockUnlock(priv
->flags_lock
);
4338 // **********************************************************************************
4341 // **********************************************************************************
4342 bool IOService::responseValid ( unsigned long x
)
4344 UInt16 serialComponent
;
4345 UInt16 ordinalComponent
;
4347 unsigned long refcon
= (unsigned long)x
;
4350 serialComponent
= (refcon
>>16) & 0xFFFF;
4351 ordinalComponent
= refcon
& 0xFFFF;
4353 if ( serialComponent
!= pm_vars
->serialNumber
)
4358 IOLockLock(priv
->flags_lock
);
4359 if ( pm_vars
->responseFlags
== NULL
)
4361 IOLockUnlock(priv
->flags_lock
);
4365 theFlag
= pm_vars
->responseFlags
->getObject(ordinalComponent
);
4369 IOLockUnlock(priv
->flags_lock
);
4373 if ( ((OSBoolean
*)theFlag
)->isFalse() )
4375 aBool
= OSBoolean::withBoolean(true);
4376 pm_vars
->responseFlags
->replaceObject(ordinalComponent
,aBool
);
4380 IOLockUnlock(priv
->flags_lock
);
4385 // **********************************************************************************
4388 // Our power state is about to lower, and we have notified applications
4389 // and kernel clients, and one of them has acknowledged. If this is the last to do
4390 // so, and all acknowledgements are positive, we continue with the power change.
4392 // We serialize this processing with timer expiration with a command gate on the
4393 // power management workloop, which the timer expiration is command gated to as well.
4394 // **********************************************************************************
4395 IOReturn
IOService::allowPowerChange ( unsigned long refcon
)
4397 if ( ! initialized
)
4400 return kIOReturnSuccess
;
4403 return pm_vars
->PMcommandGate
->runAction(serializedAllowPowerChange
,(void *)refcon
);
4407 IOReturn
serializedAllowPowerChange ( OSObject
*owner
, void * refcon
, void *, void *, void *)
4409 return ((IOService
*)owner
)->serializedAllowPowerChange2((unsigned long)refcon
);
4412 IOReturn
IOService::serializedAllowPowerChange2 ( unsigned long refcon
)
4415 if ( ! responseValid(refcon
) )
4417 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr5
,refcon
,0);
4419 return kIOReturnSuccess
;
4421 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientAcknowledge
,refcon
,0);
4423 return allowCancelCommon();
4427 // **********************************************************************************
4428 // cancelPowerChange
4430 // Our power state is about to lower, and we have notified applications
4431 // and kernel clients, and one of them has vetoed the change. If this is the last
4432 // client to respond, we abandon the power change.
4434 // We serialize this processing with timer expiration with a command gate on the
4435 // power management workloop, which the timer expiration is command gated to as well.
4436 // **********************************************************************************
4437 IOReturn
IOService::cancelPowerChange ( unsigned long refcon
)
4439 if ( ! initialized
)
4442 return kIOReturnSuccess
;
4445 return pm_vars
->PMcommandGate
->runAction(serializedCancelPowerChange
,(void *)refcon
);
4449 IOReturn
serializedCancelPowerChange ( OSObject
*owner
, void * refcon
, void *, void *, void *)
4451 return ((IOService
*)owner
)->serializedCancelPowerChange2((unsigned long)refcon
);
4454 IOReturn
IOService::serializedCancelPowerChange2 ( unsigned long refcon
)
4457 if ( ! responseValid(refcon
) )
4459 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr5
,refcon
,0);
4461 return kIOReturnSuccess
;
4463 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientCancel
,refcon
,0);
4465 pm_vars
->doNotPowerDown
= true;
4467 return allowCancelCommon();
4471 // **********************************************************************************
4472 // allowCancelCommon
4474 // **********************************************************************************
4475 IOReturn
IOService::allowCancelCommon ( void )
4477 if (! acquire_lock() )
4479 return kIOReturnSuccess
;
4482 // is this the last response?
4483 if ( checkForDone() )
4485 // yes, stop the timer
4487 IOUnlock(priv
->our_lock
);
4488 IOLockLock(priv
->flags_lock
);
4489 if ( pm_vars
->responseFlags
)
4491 pm_vars
->responseFlags
->release();
4492 pm_vars
->responseFlags
= NULL
;
4494 IOLockUnlock(priv
->flags_lock
);
4495 switch (priv
->machine_state
) {
4496 case kIOPM_OurChangeTellClientsPowerDown
:
4497 // our change, was it vetoed?
4498 if ( ! pm_vars
->doNotPowerDown
)
4500 // no, we can continue
4501 OurChangeTellClientsPowerDown();
4503 // yes, rescind the warning
4504 tellNoChangeDown(priv
->head_note_state
);
4505 // mark the change note un-actioned
4506 priv
->head_note_flags
|= IOPMNotDone
;
4512 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
4513 OurChangeTellPriorityClientsPowerDown();
4515 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
4516 // our change, continue
4517 OurChangeNotifyInterestedDriversWillChange();
4519 case kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate
:
4520 // parent change, continue
4521 ParentDownTellPriorityClientsPowerDown_Delayed();
4523 case kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
:
4524 // parent change, continue
4525 ParentDownNotifyInterestedDriversWillChange_Delayed();
4530 IOUnlock(priv
->our_lock
);
4533 return kIOReturnSuccess
;
4538 //*********************************************************************************
4539 // c_PM_clamp_Timer_Expired (C Func)
4541 // Called when our clamp timer expires...we will call the object method.
4542 //*********************************************************************************
4544 static void c_PM_Clamp_Timer_Expired (OSObject
* client
, IOTimerEventSource
*)
4547 ((IOService
*)client
)->PM_Clamp_Timer_Expired ();
4552 //*********************************************************************************
4553 // PM_Clamp_Timer_Expired
4555 // called when clamp timer expires...set power state to 0.
4556 //*********************************************************************************
4558 void IOService::PM_Clamp_Timer_Expired (void)
4561 if ( ! initialized
)
4567 changePowerStateToPriv (0);
4571 //******************************************************************************
4574 // Set to highest available power state for a minimum of duration milliseconds
4575 //******************************************************************************
4577 #define kFiveMinutesInNanoSeconds (300 * NSEC_PER_SEC)
4579 void IOService::clampPowerOn (unsigned long duration
)
4582 changePowerStateToPriv (pm_vars
->theNumberOfPowerStates
-1);
4584 if ( priv
->clampTimerEventSrc
== NULL
) {
4585 priv
->clampTimerEventSrc
= IOTimerEventSource::timerEventSource(this,
4586 c_PM_Clamp_Timer_Expired
);
4588 IOWorkLoop
* workLoop
= getPMworkloop ();
4590 if ( !priv
->clampTimerEventSrc
|| !workLoop
||
4591 ( workLoop
->addEventSource( priv
->clampTimerEventSrc
) != kIOReturnSuccess
) ) {
4596 priv
->clampTimerEventSrc
->setTimeout(300*USEC_PER_SEC
, USEC_PER_SEC
);
4600 //*********************************************************************************
4603 // Does nothing here. This should be implemented in a subclass driver.
4604 //*********************************************************************************
4606 IOReturn
IOService::setPowerState ( unsigned long powerStateOrdinal
, IOService
* whatDevice
)
4612 //*********************************************************************************
4613 // maxCapabilityForDomainState
4615 // Finds the highest power state in the array whose input power
4616 // requirement is equal to the input parameter. Where a more intelligent
4617 // decision is possible, override this in the subclassed driver.
4618 //*********************************************************************************
4620 unsigned long IOService::maxCapabilityForDomainState ( IOPMPowerFlags domainState
)
4624 if (pm_vars
->theNumberOfPowerStates
== 0 )
4628 for ( i
= (pm_vars
->theNumberOfPowerStates
)-1; i
>= 0; i
-- )
4630 if ( (domainState
& pm_vars
->thePowerStates
[i
].inputPowerRequirement
) == pm_vars
->thePowerStates
[i
].inputPowerRequirement
)
4639 //*********************************************************************************
4640 // initialPowerStateForDomainState
4642 // Finds the highest power state in the array whose input power
4643 // requirement is equal to the input parameter. Where a more intelligent
4644 // decision is possible, override this in the subclassed driver.
4645 //*********************************************************************************
4647 unsigned long IOService::initialPowerStateForDomainState ( IOPMPowerFlags domainState
)
4651 if (pm_vars
->theNumberOfPowerStates
== 0 )
4655 for ( i
= (pm_vars
->theNumberOfPowerStates
)-1; i
>= 0; i
-- )
4657 if ( (domainState
& pm_vars
->thePowerStates
[i
].inputPowerRequirement
) == pm_vars
->thePowerStates
[i
].inputPowerRequirement
)
4666 //*********************************************************************************
4667 // powerStateForDomainState
4669 // Finds the highest power state in the array whose input power
4670 // requirement is equal to the input parameter. Where a more intelligent
4671 // decision is possible, override this in the subclassed driver.
4672 //*********************************************************************************
4674 unsigned long IOService::powerStateForDomainState ( IOPMPowerFlags domainState
)
4678 if (pm_vars
->theNumberOfPowerStates
== 0 )
4682 for ( i
= (pm_vars
->theNumberOfPowerStates
)-1; i
>= 0; i
-- )
4684 if ( (domainState
& pm_vars
->thePowerStates
[i
].inputPowerRequirement
) == pm_vars
->thePowerStates
[i
].inputPowerRequirement
)
4693 //*********************************************************************************
4696 // Does nothing here. This should be implemented in a subclass driver.
4697 //*********************************************************************************
4699 bool IOService::didYouWakeSystem ( void )
4705 //*********************************************************************************
4706 // powerStateWillChangeTo
4708 // Does nothing here. This should be implemented in a subclass driver.
4709 //*********************************************************************************
4711 IOReturn
IOService::powerStateWillChangeTo ( IOPMPowerFlags
, unsigned long, IOService
*)
4717 //*********************************************************************************
4718 // powerStateDidChangeTo
4720 // Does nothing here. This should be implemented in a subclass driver.
4721 //*********************************************************************************
4723 IOReturn
IOService::powerStateDidChangeTo ( IOPMPowerFlags
, unsigned long, IOService
*)
4729 //*********************************************************************************
4732 // Does nothing here. This should be implemented in a subclass policy-maker.
4733 //*********************************************************************************
4735 void IOService::powerChangeDone ( unsigned long )
4740 //*********************************************************************************
4743 // Does nothing here. This should be implemented in a subclass driver.
4744 //*********************************************************************************
4746 IOReturn
IOService::newTemperature ( long currentTemp
, IOService
* whichZone
)
4754 #define super OSObject
4756 OSDefineMetaClassAndStructors(IOPMprot
, OSObject
)
4757 //*********************************************************************************
4760 // Serialize protected instance variables for debug output.
4761 //*********************************************************************************
4762 bool IOPMprot::serialize(OSSerialize
*s
) const
4764 OSString
* theOSString
;
4771 // estimate how many bytes we need to present all power states
4772 buf_size
= 150 // beginning and end of string
4773 + (275 * (int)theNumberOfPowerStates
) // size per state
4774 + 100; // extra room just for kicks
4776 buffer
= ptr
= IONew(char, buf_size
);
4780 ptr
+= sprintf(ptr
,"{ theNumberOfPowerStates = %d, ",(unsigned int)theNumberOfPowerStates
);
4782 if ( theNumberOfPowerStates
!= 0 ) {
4783 ptr
+= sprintf(ptr
,"version %d, ",(unsigned int)thePowerStates
[0].version
);
4786 if ( theNumberOfPowerStates
!= 0 ) {
4787 for ( i
= 0; i
< (int)theNumberOfPowerStates
; i
++ ) {
4788 ptr
+= sprintf(ptr
, "power state %d = { ",i
);
4789 ptr
+= sprintf(ptr
,"capabilityFlags %08x, ",(unsigned int)thePowerStates
[i
].capabilityFlags
);
4790 ptr
+= sprintf(ptr
,"outputPowerCharacter %08x, ",(unsigned int)thePowerStates
[i
].outputPowerCharacter
);
4791 ptr
+= sprintf(ptr
,"inputPowerRequirement %08x, ",(unsigned int)thePowerStates
[i
].inputPowerRequirement
);
4792 ptr
+= sprintf(ptr
,"staticPower %d, ",(unsigned int)thePowerStates
[i
].staticPower
);
4793 ptr
+= sprintf(ptr
,"unbudgetedPower %d, ",(unsigned int)thePowerStates
[i
].unbudgetedPower
);
4794 ptr
+= sprintf(ptr
,"powerToAttain %d, ",(unsigned int)thePowerStates
[i
].powerToAttain
);
4795 ptr
+= sprintf(ptr
,"timeToAttain %d, ",(unsigned int)thePowerStates
[i
].timeToAttain
);
4796 ptr
+= sprintf(ptr
,"settleUpTime %d, ",(unsigned int)thePowerStates
[i
].settleUpTime
);
4797 ptr
+= sprintf(ptr
,"timeToLower %d, ",(unsigned int)thePowerStates
[i
].timeToLower
);
4798 ptr
+= sprintf(ptr
,"settleDownTime %d, ",(unsigned int)thePowerStates
[i
].settleDownTime
);
4799 ptr
+= sprintf(ptr
,"powerDomainBudget %d }, ",(unsigned int)thePowerStates
[i
].powerDomainBudget
);
4803 ptr
+= sprintf(ptr
,"aggressiveness = %d, ",(unsigned int)aggressiveness
);
4804 ptr
+= sprintf(ptr
,"myCurrentState = %d, ",(unsigned int)myCurrentState
);
4805 ptr
+= sprintf(ptr
,"parentsCurrentPowerFlags = %08x, ",(unsigned int)parentsCurrentPowerFlags
);
4806 ptr
+= sprintf(ptr
,"maxCapability = %d }",(unsigned int)maxCapability
);
4808 theOSString
= OSString::withCString(buffer
);
4809 rtn_code
= theOSString
->serialize(s
);
4810 theOSString
->release();
4811 IODelete(buffer
, char, buf_size
);
4818 #define super OSObject
4820 OSDefineMetaClassAndStructors(IOPMpriv
, OSObject
)
4821 //*********************************************************************************
4824 // Serialize private instance variables for debug output.
4825 //*********************************************************************************
4826 bool IOPMpriv::serialize(OSSerialize
*s
) const
4828 OSString
* theOSString
;
4832 IOPMinformee
* nextObject
;
4834 buffer
= ptr
= IONew(char, 2000);
4838 ptr
+= sprintf(ptr
,"{ this object = %08x",(unsigned int)owner
);
4839 if ( we_are_root
) {
4840 ptr
+= sprintf(ptr
," (root)");
4842 ptr
+= sprintf(ptr
,", ");
4844 nextObject
= interestedDrivers
->firstInList(); // display interested drivers
4845 while ( nextObject
!= NULL
) {
4846 ptr
+= sprintf(ptr
,"interested driver = %08x, ",(unsigned int)nextObject
->whatObject
);
4847 nextObject
= interestedDrivers
->nextInList(nextObject
);
4850 if ( machine_state
!= kIOPM_Finished
) {
4851 ptr
+= sprintf(ptr
,"machine_state = %d, ",(unsigned int)machine_state
);
4852 ptr
+= sprintf(ptr
,"driver_timer = %d, ",(unsigned int)driver_timer
);
4853 ptr
+= sprintf(ptr
,"settle_time = %d, ",(unsigned int)settle_time
);
4854 ptr
+= sprintf(ptr
,"head_note_flags = %08x, ",(unsigned int)head_note_flags
);
4855 ptr
+= sprintf(ptr
,"head_note_state = %d, ",(unsigned int)head_note_state
);
4856 ptr
+= sprintf(ptr
,"head_note_outputFlags = %08x, ",(unsigned int)head_note_outputFlags
);
4857 ptr
+= sprintf(ptr
,"head_note_domainState = %08x, ",(unsigned int)head_note_domainState
);
4858 ptr
+= sprintf(ptr
,"head_note_capabilityFlags = %08x, ",(unsigned int)head_note_capabilityFlags
);
4859 ptr
+= sprintf(ptr
,"head_note_pendingAcks = %d, ",(unsigned int)head_note_pendingAcks
);
4862 if ( device_overrides
) {
4863 ptr
+= sprintf(ptr
,"device overrides, ");
4865 ptr
+= sprintf(ptr
,"driverDesire = %d, ",(unsigned int)driverDesire
);
4866 ptr
+= sprintf(ptr
,"deviceDesire = %d, ",(unsigned int)deviceDesire
);
4867 ptr
+= sprintf(ptr
,"ourDesiredPowerState = %d, ",(unsigned int)ourDesiredPowerState
);
4868 ptr
+= sprintf(ptr
,"previousRequest = %d }",(unsigned int)previousRequest
);
4870 theOSString
= OSString::withCString(buffer
);
4871 rtn_code
= theOSString
->serialize(s
);
4872 theOSString
->release();
4873 IODelete(buffer
, char, 2000);