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>
48 // Required for notification instrumentation
49 #include "IOServicePrivate.h"
51 #define super IORegistryEntry
53 #define OUR_PMLog(t, a, b) \
54 do { pm_vars->thePlatform->PMLog(pm_vars->ourName, t, a, b); } while(0)
56 static void ack_timer_expired(thread_call_param_t
);
57 static void settle_timer_expired(thread_call_param_t
);
58 static void PM_idle_timer_expired(OSObject
*, IOTimerEventSource
*);
59 void tellAppWithResponse ( OSObject
* object
, void * context
);
60 void tellClientWithResponse ( OSObject
* object
, void * context
);
61 void tellClient ( OSObject
* object
, void * context
);
62 IOReturn
serializedAllowPowerChange ( OSObject
*, void *, void *, void *, void *);
63 IOReturn
serializedCancelPowerChange ( OSObject
*, void *, void *, void *, void *);
65 extern const IORegistryPlane
* gIOPowerPlane
;
68 // and there's 1000 nanoseconds in a microsecond:
69 #define ns_per_us 1000
72 // The current change note is processed by a state machine.
73 // Inputs are acks from interested parties, ack from the controlling driver,
74 // ack timeouts, settle timeout, and powerStateDidChange from the parent.
75 // These are the states:
77 kIOPM_OurChangeTellClientsPowerDown
= 1,
78 kIOPM_OurChangeTellPriorityClientsPowerDown
,
79 kIOPM_OurChangeNotifyInterestedDriversWillChange
,
80 kIOPM_OurChangeSetPowerState
,
81 kIOPM_OurChangeWaitForPowerSettle
,
82 kIOPM_OurChangeNotifyInterestedDriversDidChange
,
83 kIOPM_OurChangeFinish
,
84 kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate
,
85 kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
,
86 kIOPM_ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate
,
87 kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
,
88 kIOPM_ParentDownSetPowerState_Delayed
,
89 kIOPM_ParentDownWaitForPowerSettle_Delayed
,
90 kIOPM_ParentDownAcknowledgeChange_Delayed
,
91 kIOPM_ParentUpSetPowerState_Delayed
,
92 kIOPM_ParentUpSetPowerState_Immediate
,
93 kIOPM_ParentUpWaitForSettleTime_Delayed
,
94 kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed
,
95 kIOPM_ParentUpAcknowledgePowerChange_Delayed
,
99 // values of outofbandparameter
106 // used for applyToInterested
108 OSArray
* responseFlags
;
111 UInt32 maxTimeRequested
;
115 unsigned long stateNumber
;
116 IOPMPowerFlags stateFlags
;
119 // five minutes in microseconds
120 #define FIVE_MINUTES 5*60*1000000
121 #define k30seconds 30*1000000
124 There are two different kinds of power state changes. One is initiated by a subclassed device object which has either
125 decided to change power state, or its controlling driver has suggested it, or some other driver wants to use the
126 idle device and has asked it to become usable. The second kind of power state change is initiated by the power
127 domain parent. The two are handled slightly differently.
129 There is a queue of so-called change notifications, or change notes for short. Usually the queue is empty, and when
130 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
131 at one time, a queue is implemented. Example: the subclass device decides it's idle and initiates a change to a lower
132 power state. This causes interested parties to be notified, but they don't all acknowledge right away. This causes the
133 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
134 wants to raise power back up again. This change can't be started, however, because the previous one isn't complete yet,
135 so the second one waits in the queue. During this time, the parent decides to lower or raise the power state of the entire
136 power domain and notifies the device, and that notification goes into the queue, too, and can't be actioned until the
139 This is how a power change initiated by the subclass device is handled:
140 First, all interested parties are notified of the change via their powerStateWillChangeTo method. If they all don't
141 acknowledge via return code, then we have to wait. If they do, or when they finally all acknowledge via our
142 acknowledgePowerChange method, then we can continue. We call the controlling driver, instructing it to change to
143 the new state. Then we wait for power to settle. If there is no settling-time, or after it has passed, we notify
144 interested parties again, this time via their powerStateDidChangeTo methods. When they have all acked, we're done.
145 If we lowered power and don't need the power domain to be in its current power state, we suggest to the parent that
146 it lower the power domain state.
148 This is how a change to a lower power domain state initiated by the parent is handled:
149 First, we figure out what power state we will be in when the new domain state is reached. Then all interested parties are
150 notified that we are moving to that new state. When they have acknowledged, we call the controlling driver to assume
151 that state and we wait for power to settle. Then we acknowledge our preparedness to our parent. When all its interested
152 parties have acknowledged, it lowers power and then notifies its interested parties again. When we get this call, we notify
153 our interested parties that the power state has changed, and when they have all acknowledged, we're done.
155 This is how a change to a higher power domain state initiated by the parent is handled:
156 We figure out what power state we will be in when the new domain state is reached. If it is different from our current
157 state we acknowledge the parent. When all the parent's interested parties have acknowledged, it raises power in the
158 domain and waits for power to settle. Then it notifies everyone that the new state has been reached. When we get this call,
159 we call the controlling driver, instructing it to assume the new state, and wait for power to settle. Then we notify our interested
160 parties. When they all acknowledge we are done.
162 In either of the two cases above, it is possible that we will not be changing state even though the domain is. Examples:
163 A change to a lower domain state may not affect us because we are already in a low enough state, and
164 We will not take advantage of a change to a higher domain state, because we have no need of the higher power.
165 In such a case, there is nothing to do but acknowledge the parent. So when the parent calls our powerDomainWillChange
166 method, and we decide that we will not be changing state, we merely acknowledge the parent, via return code, and wait.
167 When the parent subsequently calls powerStateDidChange, we acknowledge again via return code, and the change is complete.
169 Power state changes are processed in a state machine, and since there are four varieties of power state changes, there are
170 four major paths through the state machine:
172 The fourth is nearly trivial. In this path, the parent is changing the domain state, but we are not changing the device state.
173 The change starts when the parent calls powerDomainWillChange. All we do is acknowledge the parent.
174 When the parent calls powerStateDidChange, we acknowledge the parent again, and we're done.
176 The first is fairly simple. It starts when a power domain child calls requestPowerDomainState and we decide to change power states
177 to accomodate the child, or if our power-controlling driver calls changePowerStateTo, or if some other driver which is using our
178 device calls makeUsable, or if a subclassed object calls changePowerStateToPriv. These are all power changes initiated by us, not
179 forced upon us by the parent. We start by notifying interested parties. If they all acknowledge via return code, we can go
180 on to state "OurChangeSetPowerState". Otherwise, we start the ack timer and wait for the stragglers to acknowlege by calling
181 acknowledgePowerChange. We move on to state "OurChangeSetPowerState" when all the stragglers have acknowledged,
182 or when the ack timer expires on all those which didn't acknowledge. In "OurChangeSetPowerState" we call the power-controlling
183 driver to change the power state of the hardware. If it returns saying it has done so, we go on to state "OurChangeWaitForPowerSettle".
184 Otherwise, we have to wait for it, so we set the ack timer and wait. When it calls acknowledgeSetPowerState, or when the
185 ack timer expires, we go on. In "OurChangeWaitForPowerSettle", we look in the power state array to see if there is any settle time required
186 when changing from our current state to the new state. If not, we go right away to "OurChangeNotifyInterestedDriversDidChange". Otherwise, we
187 set the settle timer and wait. When it expires, we move on. In "OurChangeNotifyInterestedDriversDidChange" state, we notify all our interested parties
188 via their powerStateDidChange methods that we have finished changing power state. If they all acknowledge via return
189 code, we move on to "OurChangeFinish". Otherwise we set the ack timer and wait. When they have all acknowledged, or
190 when the ack timer has expired for those that didn't, we move on to "OurChangeFinish", where we remove the used
191 change note from the head of the queue and start the next one if one exists.
193 Parent-initiated changes are more complex in the state machine. First, power going up and power going down are handled
194 differently, so they have different paths throught the state machine. Second, we can acknowledge the parent's notification
195 in two different ways, so each of the parent paths is really two.
197 When the parent calls our powerDomainWillChange method, notifying us that it will lower power in the domain, we decide
198 what state that will put our device in. Then we embark on the state machine path "IOPMParentDownSetPowerState_Immediate"
199 and "kIOPM_ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate", in which we notify interested parties of the upcoming change, instruct our driver to make
200 the change, check for settle time, and notify interested parties of the completed change. If we get to the end of this path without
201 stalling due to an interested party which didn't acknowledge via return code, due to the controlling driver not able to change
202 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.
203 If we do stall in any of those states, we return IOPMWillAckLater to the parent and enter the parallel path "kIOPM_ParentDownSetPowerState_Delayed"
204 "kIOPM_ParentDownWaitForPowerSettle_Delayed", and "kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed", where we continue with the same processing, except that at the end we
205 acknowledge the parent explicitly via acknowledgePowerChange, and we're done with the change.
206 Then when the parent calls us at powerStateDidChange we acknowledging via return code, because we have already made
207 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.
209 The case of the parent raising power in the domain is handled similarly in that there are parallel paths, one for no-stall
210 that ends in implicit acknowleging the parent, and one that has stalled at least once that ends in explicit acknowledging
211 the parent. This case is different, though in that our device changes state in the second half, after the parent calls
212 powerStateDidChange rather than before, as in the power-lowering case.
214 When the parent calls our powerDomainWillChange method, notifying us that it will raise power in the domain, we acknowledge
215 via return code, because there's really nothing we can do until the power is actually raised in the domain.
216 When the parent calls us at powerStateDidChange, we start by notifying our interested parties. If they all acknowledge via return code,
217 we go on to" kIOPM_ParentUpSetPowerState_Immediate" to instruct the driver to raise its power level. After that, we check for any
218 necessary settling time in "IOPMParentUpWaitForSettleTime_Immediate", and we notify all interested parties that power has changed
219 in "IOPMParentUpNotifyInterestedDriversDidChange_Immediate". If none of these operations stall, we acknowledge the parent via return code, release
220 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",
221 "kIOPM_ParentUpWaitForSettleTime_Delayed", "kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed", and "kIOPM_ParentUpAcknowledgePowerChange_Delayed", which ends with
222 our explicit acknowledgement to the parent.
227 const char priv_key
[ ] = "Power Management private data";
228 const char prot_key
[ ] = "Power Management protected data";
231 void IOService::PMinit ( void )
233 if ( ! initialized
) {
235 // make space for our variables
236 pm_vars
= new IOPMprot
;
242 // add pm_vars & priv to the properties
243 setProperty(prot_key
, (OSObject
*) pm_vars
);
244 setProperty(priv_key
, (OSObject
*) priv
);
246 // then initialize them
248 pm_vars
->theNumberOfPowerStates
= 0;
249 priv
->we_are_root
= false;
250 pm_vars
->theControllingDriver
= NULL
;
251 priv
->our_lock
= IOLockAlloc();
252 priv
->flags_lock
= IOLockAlloc();
253 priv
->queue_lock
= IOLockAlloc();
254 pm_vars
->childLock
= IOLockAlloc();
255 pm_vars
->parentLock
= IOLockAlloc();
256 priv
->interestedDrivers
= new IOPMinformeeList
;
257 priv
->interestedDrivers
->initialize();
258 priv
->changeList
= new IOPMchangeNoteList
;
259 priv
->changeList
->initialize();
260 pm_vars
->aggressiveness
= 0;
261 for (unsigned int i
= 0; i
<= kMaxType
; i
++)
263 pm_vars
->current_aggressiveness_values
[i
] = 0;
264 pm_vars
->current_aggressiveness_valid
[i
] = false;
266 pm_vars
->myCurrentState
= 0;
267 priv
->imminentState
= 0;
268 priv
->ourDesiredPowerState
= 0;
269 pm_vars
->parentsCurrentPowerFlags
= 0;
270 pm_vars
->maxCapability
= 0;
271 priv
->driverDesire
= 0;
272 priv
->deviceDesire
= 0;
273 priv
->initial_change
= true;
274 priv
->need_to_become_usable
= false;
275 priv
->previousRequest
= 0;
276 priv
->device_overrides
= false;
277 priv
->machine_state
= kIOPM_Finished
;
278 priv
->timerEventSrc
= NULL
;
279 priv
->clampTimerEventSrc
= NULL
;
280 pm_vars
->PMworkloop
= NULL
;
281 priv
->activityLock
= NULL
;
282 pm_vars
->ourName
= getName();
283 pm_vars
->thePlatform
= getPlatform();
284 pm_vars
->parentsKnowState
= false;
285 assert( pm_vars
->thePlatform
!= 0 );
286 priv
->clampOn
= false;
287 pm_vars
->serialNumber
= 0;
288 pm_vars
->responseFlags
= NULL
;
289 pm_vars
->doNotPowerDown
= true;
290 pm_vars
->PMcommandGate
= NULL
;
291 priv
->ackTimer
= thread_call_allocate(
292 (thread_call_func_t
)ack_timer_expired
,
293 (thread_call_param_t
)this);
294 priv
->settleTimer
= thread_call_allocate(
295 (thread_call_func_t
)settle_timer_expired
,
296 (thread_call_param_t
)this);
303 //*********************************************************************************
306 // Free up the data created in PMinit, if it exists.
307 //*********************************************************************************
308 void IOService::PMfree ( void )
311 if ( priv
->clampTimerEventSrc
!= NULL
) {
312 getPMworkloop()->removeEventSource(priv
->clampTimerEventSrc
);
313 priv
->clampTimerEventSrc
->release();
314 priv
->clampTimerEventSrc
= NULL
;
316 if ( priv
->timerEventSrc
!= NULL
) {
317 pm_vars
->PMworkloop
->removeEventSource(priv
->timerEventSrc
);
318 priv
->timerEventSrc
->release();
319 priv
->timerEventSrc
= NULL
;
321 if ( priv
->settleTimer
) {
322 thread_call_cancel(priv
->settleTimer
);
323 thread_call_free(priv
->settleTimer
);
324 priv
->settleTimer
= NULL
;
326 if ( priv
->ackTimer
) {
327 thread_call_cancel(priv
->ackTimer
);
328 thread_call_free(priv
->ackTimer
);
329 priv
->ackTimer
= NULL
;
331 if ( priv
->our_lock
) {
332 IOLockFree(priv
->our_lock
);
333 priv
->our_lock
= NULL
;
335 if ( priv
->flags_lock
) {
336 IOLockFree(priv
->flags_lock
);
337 priv
->flags_lock
= NULL
;
339 if ( priv
->activityLock
) {
340 IOLockFree(priv
->activityLock
);
341 priv
->activityLock
= NULL
;
343 priv
->interestedDrivers
->release();
344 priv
->changeList
->release();
345 // remove instance variables
350 if ( pm_vars
->PMcommandGate
) {
351 if(pm_vars
->PMworkloop
)
352 pm_vars
->PMworkloop
->removeEventSource(pm_vars
->PMcommandGate
);
353 pm_vars
->PMcommandGate
->release();
354 pm_vars
->PMcommandGate
= NULL
;
356 if ( pm_vars
->PMworkloop
) {
357 // The work loop object returned from getPMworkLoop() is
358 // never retained, therefore it should not be released.
359 // pm_vars->PMworkloop->release();
360 pm_vars
->PMworkloop
= NULL
;
362 if ( pm_vars
->responseFlags
) {
363 pm_vars
->responseFlags
->release();
364 pm_vars
->responseFlags
= NULL
;
366 // remove instance variables
372 //*********************************************************************************
375 // Disconnect the node from its parents and children in the Power Plane.
376 //*********************************************************************************
377 void IOService::PMstop ( void )
381 IOPowerConnection
* connection
;
382 IOService
* theChild
;
383 IOService
* theParent
;
385 // remove the properties
386 removeProperty(prot_key
);
387 removeProperty(priv_key
);
390 iter
= getParentIterator(gIOPowerPlane
);
394 while ( (next
= iter
->getNextObject()) )
396 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
398 theParent
= (IOService
*)connection
->copyParentEntry(gIOPowerPlane
);
401 theParent
->removePowerChild(connection
);
402 theParent
->release();
409 // detach IOConnections
410 detachAbove( gIOPowerPlane
);
414 // no more power state changes
415 pm_vars
->parentsKnowState
= false;
419 iter
= getChildIterator(gIOPowerPlane
);
423 while ( (next
= iter
->getNextObject()) )
425 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
427 theChild
= ((IOService
*)(connection
->copyChildEntry(gIOPowerPlane
)));
430 // detach nub from child
431 connection
->detachFromChild(theChild
,gIOPowerPlane
);
434 // detach us from nub
435 detachFromChild(connection
,gIOPowerPlane
);
441 // Remove all interested drivers from the list, including the power
442 // controlling driver.
444 // Usually, the controlling driver and the policy-maker functionality
445 // are implemented by the same object, and without the deregistration,
446 // the object will be holding an extra retain on itself, and cannot
449 if ( priv
&& priv
->interestedDrivers
)
451 IOPMinformee
* informee
;
453 while (( informee
= priv
->interestedDrivers
->firstInList() ))
454 deRegisterInterestedDriver( informee
->whatObject
);
459 //*********************************************************************************
462 // A policy-maker calls its nub here when initializing, to be attached into
463 // the power management hierarchy. The default function is to call the
464 // platform expert, which knows how to do it. This method is overridden
465 // by a nub subclass which may either know how to do it, or may need
466 // to take other action.
468 // This may be the only "power management" method used in a nub,
469 // meaning it may not be initialized for power management.
470 //*********************************************************************************
471 void IOService::joinPMtree ( IOService
* driver
)
473 IOPlatformExpert
* thePlatform
;
475 thePlatform
= getPlatform();
476 assert(thePlatform
!= 0 );
477 thePlatform
->PMRegisterDevice(this,driver
);
481 //*********************************************************************************
484 // Power Managment is informing us that we are the root power domain.
485 // The only difference between us and any other power domain is that
486 // we have no parent and therefore never call it.
487 //*********************************************************************************
488 IOReturn
IOService::youAreRoot ( void )
490 priv
-> we_are_root
= true;
491 pm_vars
->parentsKnowState
= true;
492 attachToParent( getRegistryRoot(),gIOPowerPlane
);
498 //*********************************************************************************
501 // Power Management is informing us who our parent is.
502 // If we have a controlling driver, find out, given our newly-informed
503 // power domain state, what state it would be in, and then tell it
504 // to assume that state.
505 //*********************************************************************************
506 IOReturn
IOService::setPowerParent ( IOPowerConnection
* theParent
, bool stateKnown
, IOPMPowerFlags currentState
)
510 IOPowerConnection
* connection
;
511 unsigned long tempDesire
;
513 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogSetParent
,stateKnown
,currentState
);
515 IOLockLock(pm_vars
->parentLock
);
517 if ( stateKnown
&& ((pm_vars
->PMworkloop
== NULL
) || (pm_vars
->PMcommandGate
== NULL
)) )
519 // we have a path to the root
520 // find out the workloop
522 if ( pm_vars
->PMworkloop
!= NULL
)
524 if ( pm_vars
->PMcommandGate
== NULL
)
526 // and make our command gate
527 pm_vars
->PMcommandGate
= IOCommandGate::commandGate((OSObject
*)this);
528 if ( pm_vars
->PMcommandGate
!= NULL
)
530 pm_vars
->PMworkloop
->addEventSource(pm_vars
->PMcommandGate
);
536 IOLockUnlock(pm_vars
->parentLock
);
538 // set our connection data
539 theParent
->setParentCurrentPowerFlags(currentState
);
540 theParent
->setParentKnowsState(stateKnown
);
542 // combine parent knowledge
543 pm_vars
->parentsKnowState
= true;
544 pm_vars
->parentsCurrentPowerFlags
= 0;
546 iter
= getParentIterator(gIOPowerPlane
);
550 while ( (next
= iter
->getNextObject()) )
552 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
554 pm_vars
->parentsKnowState
&= connection
->parentKnowsState();
555 pm_vars
->parentsCurrentPowerFlags
|= connection
->parentCurrentPowerFlags();
561 if ( (pm_vars
->theControllingDriver
!= NULL
) &&
562 (pm_vars
->parentsKnowState
) )
564 pm_vars
->maxCapability
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(pm_vars
->parentsCurrentPowerFlags
);
565 // initially change into the state we are already in
566 tempDesire
= priv
->deviceDesire
;
567 priv
->deviceDesire
= pm_vars
->theControllingDriver
->initialPowerStateForDomainState(pm_vars
->parentsCurrentPowerFlags
);
568 computeDesiredState();
569 priv
->previousRequest
= 0xffffffff;
571 // put this back like before
572 priv
->deviceDesire
= tempDesire
;
579 //*********************************************************************************
582 // Power Management is informing us who our children are.
583 //*********************************************************************************
584 IOReturn
IOService::addPowerChild ( IOService
* theChild
)
586 IOPowerConnection
*connection
;
591 // we're not a power-managed IOService
592 return IOPMNotYetInitialized
;
595 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAddChild
,0,0);
597 // Put ourselves into a usable power state.
598 // We must be in an "on" power state, as our children must be able to access
599 // our hardware after joining the power plane.
600 temporaryMakeUsable();
603 connection
= new IOPowerConnection
;
606 connection
->start(this);
607 connection
->setAwaitingAck(false);
610 attachToChild( connection
,gIOPowerPlane
);
611 connection
->attachToChild( theChild
,gIOPowerPlane
);
612 connection
->release();
614 // tell it the current state of the power domain
615 if ( (pm_vars
->theControllingDriver
== NULL
) ||
616 ! (inPlane(gIOPowerPlane
)) ||
617 ! (pm_vars
->parentsKnowState
) )
619 theChild
->setPowerParent(connection
,false,0);
620 if ( inPlane(gIOPowerPlane
) )
622 for (i
= 0; i
<= kMaxType
; i
++) {
623 if ( pm_vars
->current_aggressiveness_valid
[i
] )
625 theChild
->setAggressiveness (i
, pm_vars
->current_aggressiveness_values
[i
]);
630 theChild
->setPowerParent(connection
,true,pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].outputPowerCharacter
);
631 for (i
= 0; i
<= kMaxType
; i
++)
633 if ( pm_vars
->current_aggressiveness_valid
[i
] )
635 theChild
->setAggressiveness (i
, pm_vars
->current_aggressiveness_values
[i
]);
638 // catch it up if change is in progress
639 add_child_to_active_change(connection
);
646 //******************************************************************************
649 //******************************************************************************
650 IOReturn
IOService::removePowerChild ( IOPowerConnection
* theNub
)
652 IORegistryEntry
*theChild
;
654 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRemoveChild
,0,0);
658 // detach nub from child
659 theChild
= theNub
->copyChildEntry(gIOPowerPlane
);
662 theNub
->detachFromChild(theChild
, gIOPowerPlane
);
665 // detach from the nub
666 detachFromChild(theNub
,gIOPowerPlane
);
668 // are we awaiting an ack from this child?
669 if ( theNub
->getAwaitingAck() )
671 // yes, pretend we got one
672 theNub
->setAwaitingAck(false);
673 if ( acquire_lock() )
675 if (priv
->head_note_pendingAcks
!= 0 )
677 // that's one fewer ack to worry about
678 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
680 if ( priv
->head_note_pendingAcks
== 0 )
682 // yes, stop the timer
684 IOUnlock(priv
->our_lock
);
685 // and now we can continue our power change
688 IOUnlock(priv
->our_lock
);
691 IOUnlock(priv
->our_lock
);
698 // if not fully initialized
699 if ( (pm_vars
->theControllingDriver
== NULL
) ||
700 !(inPlane(gIOPowerPlane
)) ||
701 !(pm_vars
->parentsKnowState
) )
707 // Perhaps the departing child was holding up idle or system sleep - we
708 // need to re-evaluate our childrens' requests.
709 // Clear and re-calculate our kIOPMChildClamp and kIOPMChildClamp2 bits.
710 rebuildChildClampBits();
712 // Change state if we can now tolerate lower power
713 computeDesiredState();
720 //*********************************************************************************
721 // registerPowerDriver
723 // A driver has called us volunteering to control power to our device.
724 // If the power state array it provides is richer than the one we already
725 // know about (supplied by an earlier volunteer), then accept the offer.
726 // Notify all interested parties of our power state, which we now know.
727 //*********************************************************************************
729 IOReturn
IOService::registerPowerDriver ( IOService
* controllingDriver
, IOPMPowerState
* powerStates
, unsigned long numberOfStates
)
732 unsigned long tempDesire
;
734 if ( (numberOfStates
> pm_vars
->theNumberOfPowerStates
)
735 && (numberOfStates
> 1) )
737 if ( priv
->changeList
->currentChange() == -1 )
739 if ( controllingDriver
!= NULL
)
741 if ( numberOfStates
<= IOPMMaxPowerStates
)
743 switch ( powerStates
[0].version
)
746 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriver
,
747 (unsigned long)numberOfStates
, (unsigned long)powerStates
[0].version
);
748 for ( i
= 0; i
< numberOfStates
; i
++ )
750 pm_vars
->thePowerStates
[i
] = powerStates
[i
];
754 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriver
,
755 (unsigned long) numberOfStates
,(unsigned long) powerStates
[0].version
);
756 for ( i
= 0; i
< numberOfStates
; i
++ )
758 pm_vars
->thePowerStates
[i
].version
= powerStates
[i
].version
;
759 pm_vars
->thePowerStates
[i
].capabilityFlags
= powerStates
[i
].capabilityFlags
;
760 pm_vars
->thePowerStates
[i
].outputPowerCharacter
= powerStates
[i
].outputPowerCharacter
;
761 pm_vars
->thePowerStates
[i
].inputPowerRequirement
= powerStates
[i
].inputPowerRequirement
;
762 pm_vars
->thePowerStates
[i
].staticPower
= powerStates
[i
].staticPower
;
763 pm_vars
->thePowerStates
[i
].unbudgetedPower
= powerStates
[i
].unbudgetedPower
;
764 pm_vars
->thePowerStates
[i
].powerToAttain
= powerStates
[i
].powerToAttain
;
765 pm_vars
->thePowerStates
[i
].timeToAttain
= powerStates
[i
].timeToAttain
;
766 pm_vars
->thePowerStates
[i
].settleUpTime
= powerStates
[i
].settleUpTime
;
767 pm_vars
->thePowerStates
[i
].timeToLower
= powerStates
[i
].timeToLower
;
768 pm_vars
->thePowerStates
[i
].settleDownTime
= powerStates
[i
].settleDownTime
;
769 pm_vars
->thePowerStates
[i
].powerDomainBudget
= powerStates
[i
].powerDomainBudget
;
773 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr1
,
774 (unsigned long)powerStates
[0].version
,0);
778 // make a mask of all the character bits we know about
779 pm_vars
->myCharacterFlags
= 0;
780 for ( i
= 0; i
< numberOfStates
; i
++ ) {
781 pm_vars
->myCharacterFlags
|= pm_vars
->thePowerStates
[i
].outputPowerCharacter
;
784 pm_vars
->theNumberOfPowerStates
= numberOfStates
;
785 pm_vars
->theControllingDriver
= controllingDriver
;
786 if ( priv
->interestedDrivers
->findItem(controllingDriver
) == NULL
)
788 // register it as interested, unless already done
789 registerInterestedDriver (controllingDriver
);
791 if ( priv
->need_to_become_usable
) {
792 priv
->need_to_become_usable
= false;
793 priv
->deviceDesire
= pm_vars
->theNumberOfPowerStates
- 1;
796 if ( inPlane(gIOPowerPlane
) &&
797 (pm_vars
->parentsKnowState
) ) {
798 pm_vars
->maxCapability
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(pm_vars
->parentsCurrentPowerFlags
);
799 // initially change into the state we are already in
800 tempDesire
= priv
->deviceDesire
;
801 priv
->deviceDesire
= pm_vars
->theControllingDriver
->initialPowerStateForDomainState(pm_vars
->parentsCurrentPowerFlags
);
802 computeDesiredState();
804 // put this back like before
805 priv
->deviceDesire
= tempDesire
;
808 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr2
,(unsigned long)numberOfStates
,0);
811 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr4
,0,0);
816 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr5
,(unsigned long)numberOfStates
,0);
821 //*********************************************************************************
822 // registerInterestedDriver
824 // Add the caller to our list of interested drivers and return our current
825 // power state. If we don't have a power-controlling driver yet, we will
826 // call this interested driver again later when we do get a driver and find
827 // out what the current power state of the device is.
828 //*********************************************************************************
830 IOPMPowerFlags
IOService::registerInterestedDriver ( IOService
* theDriver
)
832 IOPMinformee
*newInformee
;
833 IOPMPowerFlags futureCapability
;
835 if (theDriver
== NULL
) {
839 // make new driver node
840 newInformee
= new IOPMinformee
;
841 newInformee
->initialize(theDriver
);
842 // add it to list of drivers
843 priv
->interestedDrivers
->addToList(newInformee
);
845 if ( (pm_vars
->theControllingDriver
== NULL
) ||
846 !(inPlane(gIOPowerPlane
)) ||
847 !(pm_vars
->parentsKnowState
) )
849 // can't tell it a state yet
850 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInterestedDriver
,IOPMNotPowerManaged
,0);
851 return IOPMNotPowerManaged
;
854 // can we notify new driver of a change in progress?
855 switch (priv
->machine_state
) {
856 case kIOPM_OurChangeSetPowerState
:
857 case kIOPM_OurChangeFinish
:
858 case kIOPM_ParentDownSetPowerState_Delayed
:
859 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
860 case kIOPM_ParentUpSetPowerState_Delayed
:
861 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
862 // yes, remember what we tell it
863 futureCapability
= priv
->head_note_capabilityFlags
;
864 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInterestedDriver
,(unsigned long)futureCapability
,1);
866 add_driver_to_active_change(newInformee
);
867 // and return the same thing
868 return futureCapability
;
871 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInterestedDriver
,
872 (unsigned long) pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
,2);
874 // no, return current capability
875 return pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
;
879 //*********************************************************************************
880 // deRegisterInterestedDriver
882 //*********************************************************************************
883 IOReturn
IOService::deRegisterInterestedDriver ( IOService
* theDriver
)
885 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRemoveDriver
,0,0);
887 // remove the departing driver
888 priv
->interestedDrivers
->removeFromList(theDriver
);
894 //*********************************************************************************
895 // acknowledgePowerChange
897 // After we notified one of the interested drivers or a power-domain child
898 // of an impending change in power, it has called to say it is now
899 // prepared for the change. If this object is the last to
900 // acknowledge this change, we take whatever action we have been waiting
902 // That may include acknowledging to our parent. In this case, we do it
903 // last of all to insure that this doesn't cause the parent to call us some-
904 // where else and alter data we are relying on here (like the very existance
905 // of a "current change note".)
906 //*********************************************************************************
908 IOReturn
IOService::acknowledgePowerChange ( IOService
* whichObject
)
910 IOPMinformee
*ackingObject
;
911 unsigned long childPower
= kIOPMUnknown
;
914 // one of our interested drivers?
915 ackingObject
= priv
->interestedDrivers
->findItem(whichObject
);
916 if ( ackingObject
== NULL
)
918 if ( ! isChild(whichObject
,gIOPowerPlane
) )
920 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr1
,0,0);
921 //kprintf("errant driver: %s\n",whichObject->getName());
925 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChildAcknowledge
,priv
->head_note_pendingAcks
,0);
928 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogDriverAcknowledge
,priv
->head_note_pendingAcks
,0);
931 if (! acquire_lock() )
936 if (priv
->head_note_pendingAcks
!= 0 )
938 // yes, make sure we're expecting acks
939 if ( ackingObject
!= NULL
)
941 // it's an interested driver
942 // make sure we're expecting this ack
943 if ( ackingObject
->timer
!= 0 )
946 ackingObject
->timer
= 0;
947 // that's one fewer to worry about
948 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
950 if ( priv
->head_note_pendingAcks
== 0 )
952 // yes, stop the timer
954 IOUnlock(priv
->our_lock
);
955 // and now we can continue
960 // this driver has already acked
961 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr2
,0,0);
962 //kprintf("errant driver: %s\n",whichObject->getName());
966 // make sure we're expecting this ack
967 if ( ((IOPowerConnection
*)whichObject
)->getAwaitingAck() )
969 // that's one fewer to worry about
970 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
971 ((IOPowerConnection
*)whichObject
)->setAwaitingAck(false);
972 theChild
= (IOService
*)whichObject
->copyChildEntry(gIOPowerPlane
);
975 childPower
= theChild
->currentPowerConsumption();
978 if ( childPower
== kIOPMUnknown
)
980 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
= kIOPMUnknown
;
982 if ( pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
!= kIOPMUnknown
)
984 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
+= childPower
;
988 if ( priv
->head_note_pendingAcks
== 0 ) {
989 // yes, stop the timer
991 IOUnlock(priv
->our_lock
);
992 // and now we can continue
999 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr3
,0,0); // not expecting anybody to ack
1000 //kprintf("errant driver: %s\n",whichObject->getName());
1002 IOUnlock(priv
->our_lock
);
1006 //*********************************************************************************
1007 // acknowledgeSetPowerState
1009 // After we instructed our controlling driver to change power states,
1010 // it has called to say it has finished doing so.
1011 // We continue to process the power state change.
1012 //*********************************************************************************
1014 IOReturn
IOService::acknowledgeSetPowerState ( void )
1016 if (!acquire_lock())
1019 IOReturn timer
= priv
->driver_timer
;
1020 if ( timer
== -1 ) {
1021 // driver is acking instead of using return code
1022 OUR_PMLog(kPMLogDriverAcknowledgeSet
, (UInt32
) this, timer
);
1023 priv
->driver_timer
= 0;
1025 else if ( timer
> 0 ) { // are we expecting this?
1026 // yes, stop the timer
1028 priv
->driver_timer
= 0;
1029 OUR_PMLog(kPMLogDriverAcknowledgeSet
, (UInt32
) this, timer
);
1030 IOUnlock(priv
->our_lock
);
1034 // not expecting this
1035 OUR_PMLog(kPMLogAcknowledgeErr4
, (UInt32
) this, 0);
1038 IOUnlock(priv
->our_lock
);
1043 //*********************************************************************************
1046 // Either the controlling driver has called acknowledgeSetPowerState
1047 // or the acknowledgement timer has expired while waiting for that.
1048 // We carry on processing the current change note.
1049 //*********************************************************************************
1051 void IOService::driver_acked ( void )
1054 switch (priv
->machine_state
) {
1055 case kIOPM_OurChangeWaitForPowerSettle
:
1056 OurChangeWaitForPowerSettle();
1058 case kIOPM_ParentDownWaitForPowerSettle_Delayed
:
1059 ParentDownWaitForPowerSettle_Delayed();
1061 case kIOPM_ParentUpWaitForSettleTime_Delayed
:
1062 ParentUpWaitForSettleTime_Delayed();
1068 //*********************************************************************************
1069 // powerDomainWillChangeTo
1071 // Called by the power-hierarchy parent notifying of a new power state
1072 // in the power domain.
1073 // We enqueue a parent power-change to our queue of power changes.
1074 // This may or may not cause us to change power, depending on what
1075 // kind of change is occuring in the domain.
1076 //*********************************************************************************
1078 IOReturn
IOService::powerDomainWillChangeTo ( IOPMPowerFlags newPowerStateFlags
, IOPowerConnection
* whichParent
)
1082 IOPowerConnection
*connection
;
1083 unsigned long newStateNumber
;
1084 IOPMPowerFlags combinedPowerFlags
;
1086 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogWillChange
,(unsigned long)newPowerStateFlags
,0);
1088 if ( ! inPlane(gIOPowerPlane
) )
1091 return IOPMAckImplied
;
1094 IOLockLock(pm_vars
->parentLock
);
1096 if ( (pm_vars
->PMworkloop
== NULL
) || (pm_vars
->PMcommandGate
== NULL
) )
1098 // we have a path to the root
1100 // so find out the workloop
1101 if ( pm_vars
->PMworkloop
!= NULL
)
1103 // and make our command gate
1104 if ( pm_vars
->PMcommandGate
== NULL
)
1106 pm_vars
->PMcommandGate
= IOCommandGate::commandGate((OSObject
*)this);
1107 if ( pm_vars
->PMcommandGate
!= NULL
)
1109 pm_vars
->PMworkloop
->addEventSource(pm_vars
->PMcommandGate
);
1115 IOLockUnlock(pm_vars
->parentLock
);
1117 // combine parents' power states
1118 // to determine our maximum state within the new power domain
1119 combinedPowerFlags
= 0;
1121 iter
= getParentIterator(gIOPowerPlane
);
1125 while ( (next
= iter
->getNextObject()) )
1127 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1129 if ( connection
== whichParent
){
1130 combinedPowerFlags
|= newPowerStateFlags
;
1132 combinedPowerFlags
|= connection
->parentCurrentPowerFlags();
1139 if ( pm_vars
->theControllingDriver
== NULL
)
1141 // we can't take any more action
1142 return IOPMAckImplied
;
1144 newStateNumber
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(combinedPowerFlags
);
1146 return enqueuePowerChange(IOPMParentInitiated
| IOPMDomainWillChange
,
1147 newStateNumber
,combinedPowerFlags
,whichParent
,newPowerStateFlags
);
1151 //*********************************************************************************
1152 // powerDomainDidChangeTo
1154 // Called by the power-hierarchy parent after the power state of the power domain
1155 // has settled at a new level.
1156 // We enqueue a parent power-change to our queue of power changes.
1157 // This may or may not cause us to change power, depending on what
1158 // kind of change is occuring in the domain.
1159 //*********************************************************************************
1161 IOReturn
IOService::powerDomainDidChangeTo ( IOPMPowerFlags newPowerStateFlags
, IOPowerConnection
* whichParent
)
1163 unsigned long newStateNumber
;
1165 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogDidChange
,newPowerStateFlags
,0);
1167 setParentInfo(newPowerStateFlags
,whichParent
);
1169 if ( pm_vars
->theControllingDriver
== NULL
) {
1170 return IOPMAckImplied
;
1173 newStateNumber
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(pm_vars
->parentsCurrentPowerFlags
);
1174 // tell interested parties about it
1175 return enqueuePowerChange(IOPMParentInitiated
| IOPMDomainDidChange
,
1176 newStateNumber
,pm_vars
->parentsCurrentPowerFlags
,whichParent
,0);
1180 //*********************************************************************************
1183 // Set our connection data for one specific parent, and then combine all the parent
1185 //*********************************************************************************
1187 void IOService::setParentInfo ( IOPMPowerFlags newPowerStateFlags
, IOPowerConnection
* whichParent
)
1191 IOPowerConnection
*connection
;
1193 // set our connection data
1194 whichParent
->setParentCurrentPowerFlags(newPowerStateFlags
);
1195 whichParent
->setParentKnowsState(true);
1197 IOLockLock(pm_vars
->parentLock
);
1199 // recompute our parent info
1200 pm_vars
->parentsCurrentPowerFlags
= 0;
1201 pm_vars
->parentsKnowState
= true;
1203 iter
= getParentIterator(gIOPowerPlane
);
1207 while ( (next
= iter
->getNextObject()) )
1209 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1211 pm_vars
->parentsKnowState
&= connection
->parentKnowsState();
1212 pm_vars
->parentsCurrentPowerFlags
|= connection
->parentCurrentPowerFlags();
1217 IOLockUnlock(pm_vars
->parentLock
);
1220 //*********************************************************************************
1221 // rebuildChildClampBits
1223 // The ChildClamp bits (kIOPMChildClamp & kIOPMChildClamp2) in our capabilityFlags
1224 // indicate that one of our children (or grandchildren or great-grandchildren or ...)
1225 // doesn't support idle or system sleep in its current state. Since we don't track the
1226 // origin of each bit, every time any child changes state we have to clear these bits
1227 // and rebuild them.
1228 //*********************************************************************************
1230 void IOService::rebuildChildClampBits(void)
1235 IOPowerConnection
*connection
;
1238 // A child's desires has changed. We need to rebuild the child-clamp bits in our
1239 // power state array. Start by clearing the bits in each power state.
1241 for ( i
= 0; i
< pm_vars
->theNumberOfPowerStates
; i
++ )
1243 pm_vars
->thePowerStates
[i
].capabilityFlags
&= ~(kIOPMChildClamp
| kIOPMChildClamp2
);
1246 // Now loop through the children. When we encounter the calling child, save
1247 // the computed state as this child's desire. And while we're at it, set the ChildClamp bits
1248 // in any of our states that some child has requested with clamp on.
1250 iter
= getChildIterator(gIOPowerPlane
);
1254 while ( (next
= iter
->getNextObject()) )
1256 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1258 if ( connection
->getPreventIdleSleepFlag() )
1259 pm_vars
->thePowerStates
[connection
->getDesiredDomainState()].capabilityFlags
|= kIOPMChildClamp
;
1260 if ( connection
->getPreventSystemSleepFlag() )
1261 pm_vars
->thePowerStates
[connection
->getDesiredDomainState()].capabilityFlags
|= kIOPMChildClamp2
;
1270 //*********************************************************************************
1271 // requestPowerDomainState
1273 // The kIOPMPreventIdleSleep and/or kIOPMPreventIdleSleep bits may be be set in the parameter.
1274 // It is not considered part of the state specification.
1275 //*********************************************************************************
1276 IOReturn
IOService::requestPowerDomainState ( IOPMPowerFlags desiredState
, IOPowerConnection
* whichChild
, unsigned long specification
)
1279 unsigned long computedState
;
1280 unsigned long theDesiredState
= desiredState
& ~(kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
1283 IOPowerConnection
*connection
;
1285 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRequestDomain
,
1286 (unsigned long)desiredState
,(unsigned long)specification
);
1288 if ( pm_vars
->theControllingDriver
== NULL
)
1290 return IOPMNotYetInitialized
;
1293 switch (specification
) {
1294 case IOPMLowestState
:
1296 while ( i
< pm_vars
->theNumberOfPowerStates
)
1298 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1304 if ( i
>= pm_vars
->theNumberOfPowerStates
)
1306 return IOPMNoSuchState
;
1310 case IOPMNextLowerState
:
1311 i
= pm_vars
->myCurrentState
- 1;
1312 while ( (int) i
>= 0 )
1314 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1322 return IOPMNoSuchState
;
1326 case IOPMHighestState
:
1327 i
= pm_vars
->theNumberOfPowerStates
;
1328 while ( (int) i
>= 0 )
1331 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1338 return IOPMNoSuchState
;
1342 case IOPMNextHigherState
:
1343 i
= pm_vars
->myCurrentState
+ 1;
1344 while ( i
< pm_vars
->theNumberOfPowerStates
)
1346 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1352 if ( i
== pm_vars
->theNumberOfPowerStates
)
1354 return IOPMNoSuchState
;
1359 return IOPMBadSpecification
;
1364 IOLockLock(pm_vars
->childLock
);
1366 // Now loop through the children. When we encounter the calling child, save
1367 // the computed state as this child's desire.
1368 iter
= getChildIterator(gIOPowerPlane
);
1372 while ( (next
= iter
->getNextObject()) )
1374 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1376 if ( connection
== whichChild
)
1378 connection
->setDesiredDomainState(computedState
);
1379 connection
->setPreventIdleSleepFlag(desiredState
& kIOPMPreventIdleSleep
);
1380 connection
->setPreventSystemSleepFlag(desiredState
& kIOPMPreventSystemSleep
);
1381 connection
->setChildHasRequestedPower();
1388 // Since a child's power requirements may have changed, clear and rebuild
1389 // kIOPMChildClamp and kIOPMChildClamp2 (idle and system sleep clamps)
1390 rebuildChildClampBits();
1392 IOLockUnlock(pm_vars
->childLock
);
1394 // this may be different now
1395 computeDesiredState();
1397 if ( inPlane(gIOPowerPlane
) &&
1398 (pm_vars
->parentsKnowState
) ) {
1399 // change state if all children can now tolerate lower power
1403 // are we clamped on, waiting for this child?
1404 if ( priv
->clampOn
) {
1405 // yes, remove the clamp
1406 priv
->clampOn
= false;
1407 changePowerStateToPriv(0);
1414 //*********************************************************************************
1415 // temporaryPowerClampOn
1417 // A power domain wants to clamp its power on till it has children which
1418 // will thendetermine the power domain state.
1420 // We enter the highest state until addPowerChild is called.
1421 //*********************************************************************************
1423 IOReturn
IOService::temporaryPowerClampOn ( void )
1425 priv
->clampOn
= true;
1431 //*********************************************************************************
1434 // Some client of our device is asking that we become usable. Although
1435 // this has not come from a subclassed device object, treat it exactly
1436 // as if it had. In this way, subsequent requests for lower power from
1437 // a subclassed device object will pre-empt this request.
1439 // We treat this as a subclass object request to switch to the
1440 // highest power state.
1441 //*********************************************************************************
1443 IOReturn
IOService::makeUsable ( void )
1445 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogMakeUsable
,0,0);
1447 if ( pm_vars
->theControllingDriver
== NULL
)
1449 priv
->need_to_become_usable
= true;
1452 priv
->deviceDesire
= pm_vars
->theNumberOfPowerStates
- 1;
1453 computeDesiredState();
1454 if ( inPlane(gIOPowerPlane
) && (pm_vars
->parentsKnowState
) )
1456 return changeState();
1461 //******************************************************************************
1462 // temporaryMakeUsable
1464 // Private function, called by IOService::addPowerChild to ensure that the
1465 // device is temporarily in a usable power state so that attached power
1466 // children may properly initialize.
1467 //******************************************************************************
1469 IOReturn
IOService::temporaryMakeUsable ( void )
1471 IOReturn ret
= kIOReturnSuccess
;
1472 unsigned long tempDesire
;
1474 pm_vars
->thePlatform
->PMLog( pm_vars
->ourName
,
1477 priv
->deviceDesire
);
1479 if ( pm_vars
->theControllingDriver
== NULL
)
1481 priv
->need_to_become_usable
= true;
1484 tempDesire
= priv
->deviceDesire
;
1485 priv
->deviceDesire
= pm_vars
->theNumberOfPowerStates
- 1;
1486 computeDesiredState();
1487 if ( inPlane(gIOPowerPlane
) && (pm_vars
->parentsKnowState
) )
1489 ret
= changeState();
1491 priv
->deviceDesire
= tempDesire
;
1496 //*********************************************************************************
1497 // currentCapability
1499 //*********************************************************************************
1501 IOPMPowerFlags
IOService::currentCapability ( void )
1503 if ( pm_vars
->theControllingDriver
== NULL
)
1507 return pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
;
1512 //*********************************************************************************
1513 // changePowerStateTo
1515 // For some reason, our power-controlling driver has decided it needs to change
1516 // power state. We enqueue the power change so that appropriate parties
1517 // will be notified, and then we will instruct the driver to make the change.
1518 //*********************************************************************************
1520 IOReturn
IOService::changePowerStateTo ( unsigned long ordinal
)
1522 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeStateTo
,ordinal
,0);
1524 if ( ordinal
>= pm_vars
->theNumberOfPowerStates
)
1526 return IOPMParameterError
;
1528 priv
->driverDesire
= ordinal
;
1529 computeDesiredState();
1530 if ( inPlane(gIOPowerPlane
) && (pm_vars
->parentsKnowState
) )
1532 return changeState();
1538 //*********************************************************************************
1539 // changePowerStateToPriv
1541 // For some reason, a subclassed device object has decided it needs to change
1542 // power state. We enqueue the power change so that appropriate parties
1543 // will be notified, and then we will instruct the driver to make the change.
1544 //*********************************************************************************
1546 IOReturn
IOService::changePowerStateToPriv ( unsigned long ordinal
)
1548 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeStateToPriv
,ordinal
,0);
1550 if ( pm_vars
->theControllingDriver
== NULL
)
1552 return IOPMNotYetInitialized
;
1554 if ( ordinal
>= pm_vars
->theNumberOfPowerStates
)
1556 return IOPMParameterError
;
1558 priv
->deviceDesire
= ordinal
;
1559 computeDesiredState();
1560 if ( inPlane(gIOPowerPlane
) && (pm_vars
->parentsKnowState
) )
1562 return changeState();
1569 //*********************************************************************************
1570 // computeDesiredState
1572 //*********************************************************************************
1574 void IOService::computeDesiredState ( void )
1578 IOPowerConnection
*connection
;
1579 unsigned long newDesiredState
= 0;
1581 // Compute the maximum of our children's desires, our controlling driver's desire, and the subclass device's desire.
1582 if ( ! priv
->device_overrides
)
1584 iter
= getChildIterator(gIOPowerPlane
);
1588 while ( (next
= iter
->getNextObject()) )
1590 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1592 if ( connection
->getDesiredDomainState() > newDesiredState
)
1594 newDesiredState
= connection
->getDesiredDomainState();
1601 if ( priv
->driverDesire
> newDesiredState
)
1603 newDesiredState
= priv
->driverDesire
;
1607 if ( priv
->deviceDesire
> newDesiredState
)
1609 newDesiredState
= priv
->deviceDesire
;
1612 priv
->ourDesiredPowerState
= newDesiredState
;
1616 //*********************************************************************************
1619 // A subclass object, our controlling driver, or a power domain child
1620 // has asked for a different power state. Here we compute what new
1621 // state we should enter and enqueue the change (or start it).
1622 //*********************************************************************************
1624 IOReturn
IOService::changeState ( void )
1626 // if not fully initialized
1627 if ( (pm_vars
->theControllingDriver
== NULL
) ||
1628 !(inPlane(gIOPowerPlane
)) ||
1629 !(pm_vars
->parentsKnowState
) )
1631 // we can do no more
1635 return enqueuePowerChange(IOPMWeInitiated
,priv
->ourDesiredPowerState
,0,0,0);
1639 //*********************************************************************************
1640 // currentPowerConsumption
1642 //*********************************************************************************
1644 unsigned long IOService::currentPowerConsumption ( void )
1646 if ( pm_vars
->theControllingDriver
== NULL
)
1648 return kIOPMUnknown
;
1650 if ( pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
& kIOPMStaticPowerValid
)
1652 return pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].staticPower
;
1654 return kIOPMUnknown
;
1657 //*********************************************************************************
1660 // The activity tickle with parameter kIOPMSubclassPolicyis not handled
1661 // here and should have been intercepted by the subclass.
1662 // The tickle with parameter kIOPMSuperclassPolicy1 causes the activity
1663 // flag to be set, and the device state checked. If the device has been
1664 // powered down, it is powered up again.
1665 //*********************************************************************************
1667 bool IOService::activityTickle ( unsigned long type
, unsigned long stateNumber
)
1669 IOPMrootDomain
*pmRootDomain
;
1670 AbsoluteTime uptime
;
1672 if ( type
== kIOPMSuperclassPolicy1
)
1674 if ( pm_vars
->theControllingDriver
== NULL
)
1679 if( priv
->activityLock
== NULL
)
1681 priv
->activityLock
= IOLockAlloc();
1684 IOTakeLock(priv
->activityLock
);
1685 priv
->device_active
= true;
1687 clock_get_uptime(&uptime
);
1688 priv
->device_active_timestamp
= uptime
;
1690 if ( pm_vars
->myCurrentState
>= stateNumber
)
1692 IOUnlock(priv
->activityLock
);
1695 IOUnlock(priv
->activityLock
);
1697 // Transfer execution to the PM workloop
1698 if( (pmRootDomain
= getPMRootDomain()) )
1699 pmRootDomain
->unIdleDevice(this, stateNumber
);
1706 //*********************************************************************************
1709 // A child is calling to get a pointer to the Power Management workloop.
1710 // We got it or get it from one of our parents.
1711 //*********************************************************************************
1713 IOWorkLoop
* IOService::getPMworkloop ( void )
1718 if ( ! inPlane(gIOPowerPlane
) )
1722 // we have no workloop yet
1723 if ( pm_vars
->PMworkloop
== NULL
)
1725 nub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
1728 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
1730 // ask one of our parents for the workloop
1733 pm_vars
->PMworkloop
= parent
->getPMworkloop();
1738 return pm_vars
->PMworkloop
;
1742 //*********************************************************************************
1743 // setIdleTimerPeriod
1745 // A subclass policy-maker is going to use our standard idleness
1746 // detection service. Make a command queue and an idle timer and
1747 // connect them to the power management workloop. Finally,
1749 //*********************************************************************************
1751 IOReturn
IOService::setIdleTimerPeriod ( unsigned long period
)
1753 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMsetIdleTimerPeriod
,period
, 0);
1755 priv
->idle_timer_period
= period
;
1759 if ( getPMworkloop() == NULL
)
1761 return kIOReturnError
;
1764 // make the timer event
1765 if ( priv
->timerEventSrc
== NULL
)
1767 priv
->timerEventSrc
= IOTimerEventSource::timerEventSource(this,
1768 PM_idle_timer_expired
);
1769 if ((!priv
->timerEventSrc
) ||
1770 (pm_vars
->PMworkloop
->addEventSource(priv
->timerEventSrc
) != kIOReturnSuccess
) )
1772 return kIOReturnError
;
1776 if ( priv
->activityLock
== NULL
)
1778 priv
->activityLock
= IOLockAlloc();
1781 start_PM_idle_timer();
1786 //******************************************************************************
1789 // Returns how many "seconds from now" the device should idle into its
1790 // next lowest power state.
1791 //******************************************************************************
1792 SInt32
IOService::nextIdleTimeout(
1793 AbsoluteTime currentTime
,
1794 AbsoluteTime lastActivity
,
1795 unsigned int powerState
)
1802 // Calculate time difference using funky macro from clock.h.
1803 delta
= currentTime
;
1804 SUB_ABSOLUTETIME(&delta
, &lastActivity
);
1806 // Figure it in seconds.
1807 absolutetime_to_nanoseconds(delta
, &delta_ns
);
1808 delta_secs
= (SInt32
)(delta_ns
/ NSEC_PER_SEC
);
1810 // Be paranoid about delta somehow exceeding timer period.
1811 if (delta_secs
< (int) priv
->idle_timer_period
)
1812 delay_secs
= (int) priv
->idle_timer_period
- delta_secs
;
1814 delay_secs
= (int) priv
->idle_timer_period
;
1816 return (SInt32
)delay_secs
;
1819 //******************************************************************************
1820 // start_PM_idle_timer
1822 // The parameter is a pointer to us. Use it to call our timeout method.
1823 //******************************************************************************
1824 void IOService::start_PM_idle_timer ( void )
1826 static const int maxTimeout
= 100000;
1827 static const int minTimeout
= 1;
1828 AbsoluteTime uptime
;
1831 IOLockLock(priv
->activityLock
);
1833 clock_get_uptime(&uptime
);
1835 // Subclasses may modify idle sleep algorithm
1836 idle_in
= nextIdleTimeout(uptime
,
1837 priv
->device_active_timestamp
,
1838 pm_vars
->myCurrentState
);
1840 // Check for out-of range responses
1841 if(idle_in
> maxTimeout
)
1843 // use standard implementation
1844 idle_in
= IOService::nextIdleTimeout(uptime
,
1845 priv
->device_active_timestamp
,
1846 pm_vars
->myCurrentState
);
1847 } else if(idle_in
< minTimeout
) {
1852 priv
->timerEventSrc
->setTimeout(idle_in
, NSEC_PER_SEC
);
1854 IOLockUnlock(priv
->activityLock
);
1859 //*********************************************************************************
1860 // PM_idle_timer_expired
1862 // The parameter is a pointer to us. Use it to call our timeout method.
1863 //*********************************************************************************
1865 void PM_idle_timer_expired(OSObject
* ourSelves
, IOTimerEventSource
*)
1867 ((IOService
*)ourSelves
)->PM_idle_timer_expiration();
1871 //*********************************************************************************
1872 // PM_idle_timer_expiration
1874 // The idle timer has expired. If there has been activity since the last
1875 // expiration, just restart the timer and return. If there has not been
1876 // activity, switch to the next lower power state and restart the timer.
1877 //*********************************************************************************
1879 void IOService::PM_idle_timer_expiration ( void )
1881 if ( ! initialized
)
1887 if ( priv
->idle_timer_period
> 0 )
1889 IOTakeLock(priv
->activityLock
);
1890 if ( priv
->device_active
)
1892 priv
->device_active
= false;
1893 IOUnlock(priv
->activityLock
);
1894 start_PM_idle_timer();
1897 if ( pm_vars
->myCurrentState
> 0 )
1900 unsigned long newState
= pm_vars
->myCurrentState
- 1;
1902 IOUnlock(priv
->activityLock
);
1903 changePowerStateToPriv(newState
);
1904 if ( newState
>= priv
->ourDesiredPowerState
)
1905 start_PM_idle_timer();
1908 IOUnlock(priv
->activityLock
);
1909 start_PM_idle_timer();
1914 // **********************************************************************************
1917 // We are un-idling a device due to its activity tickle. This routine runs on the
1918 // PM workloop, and is initiated by IOService::activityTickle.
1919 // We process all activityTickle state requests on the list.
1920 // **********************************************************************************
1921 void IOService::command_received ( void *statePtr
, void *, void * , void * )
1923 unsigned long stateNumber
;
1925 stateNumber
= (unsigned long)statePtr
;
1927 // If not initialized, we're unloading
1928 if ( ! initialized
) return;
1930 if ( (pm_vars
->myCurrentState
< stateNumber
) &&
1931 (priv
->imminentState
< stateNumber
) )
1933 changePowerStateToPriv(stateNumber
);
1935 // After we raise our state, re-schedule the idle timer.
1936 if(priv
->timerEventSrc
)
1937 start_PM_idle_timer();
1942 //*********************************************************************************
1943 // setAggressiveness
1945 // Pass on the input parameters to all power domain children. All those which are
1946 // power domains will pass it on to their children, etc.
1947 //*********************************************************************************
1949 IOReturn
IOService::setAggressiveness ( unsigned long type
, unsigned long newLevel
)
1953 IOPowerConnection
*connection
;
1956 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogSetAggressiveness
,type
, newLevel
);
1958 if ( type
<= kMaxType
)
1960 pm_vars
->current_aggressiveness_values
[type
] = newLevel
;
1961 pm_vars
->current_aggressiveness_valid
[type
] = true;
1964 iter
= getChildIterator(gIOPowerPlane
);
1968 while ( (next
= iter
->getNextObject()) )
1970 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1972 child
= ((IOService
*)(connection
->copyChildEntry(gIOPowerPlane
)));
1975 child
->setAggressiveness(type
, newLevel
);
1986 //*********************************************************************************
1987 // getAggressiveness
1989 // Called by the user client.
1990 //*********************************************************************************
1992 IOReturn
IOService::getAggressiveness ( unsigned long type
, unsigned long * currentLevel
)
1994 if ( type
> kMaxType
)
1995 return kIOReturnBadArgument
;
1997 if ( !pm_vars
->current_aggressiveness_valid
[type
] )
1998 return kIOReturnInvalid
;
2000 *currentLevel
= pm_vars
->current_aggressiveness_values
[type
];
2002 return kIOReturnSuccess
;
2005 //*********************************************************************************
2008 // Pass this to all power domain children. All those which are
2009 // power domains will pass it on to their children, etc.
2010 //*********************************************************************************
2012 IOReturn
IOService::systemWake ( void )
2016 IOPowerConnection
*connection
;
2017 IOService
*theChild
;
2019 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogSystemWake
,0, 0);
2021 iter
= getChildIterator(gIOPowerPlane
);
2025 while ( (next
= iter
->getNextObject()) )
2027 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
2029 theChild
= (IOService
*)connection
->copyChildEntry(gIOPowerPlane
);
2032 theChild
->systemWake();
2033 theChild
->release();
2040 if ( pm_vars
->theControllingDriver
!= NULL
)
2042 if ( pm_vars
->theControllingDriver
->didYouWakeSystem() )
2052 //*********************************************************************************
2053 // temperatureCriticalForZone
2055 //*********************************************************************************
2057 IOReturn
IOService::temperatureCriticalForZone ( IOService
* whichZone
)
2059 IOService
*theParent
;
2062 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogCriticalTemp
,0,0);
2064 if ( inPlane(gIOPowerPlane
) && !(priv
->we_are_root
) )
2066 theNub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
2069 theParent
= (IOService
*)theNub
->copyParentEntry(gIOPowerPlane
);
2073 theParent
->temperatureCriticalForZone(whichZone
);
2074 theParent
->release();
2082 //*********************************************************************************
2083 // powerOverrideOnPriv
2085 //*********************************************************************************
2088 IOReturn
IOService::powerOverrideOnPriv ( void )
2090 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogOverrideOn
,0,0);
2092 // turn on the override
2093 priv
->device_overrides
= true;
2094 computeDesiredState();
2096 // change state if that changed something
2097 return changeState();
2101 //*********************************************************************************
2102 // powerOverrideOffPriv
2104 //*********************************************************************************
2105 IOReturn
IOService::powerOverrideOffPriv ( void )
2107 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogOverrideOff
,0,0);
2109 // turn off the override
2110 priv
->device_overrides
= false;
2111 computeDesiredState();
2114 return makeUsable();
2116 // change state if that changed something
2117 return changeState();
2122 //*********************************************************************************
2123 // enqueuePowerChange
2125 // Allocate a new state change notification, initialize it with fields from the
2126 // caller, and add it to the tail of the list of pending power changes.
2128 // If it is early enough in the list, and almost all the time it is the only one in
2129 // the list, start the power change.
2131 // In rare instances, this change will preempt the previous change in the list.
2132 // If the previous change is un-actioned in any way (because we are still
2133 // processing an even earlier power change), and if both the previous change
2134 // in the list and this change are initiated by us (not the parent), then we
2135 // needn't perform the previous change, so we collapse the list a little.
2136 //*********************************************************************************
2138 IOReturn
IOService::enqueuePowerChange (
2139 unsigned long flags
,
2140 unsigned long whatStateOrdinal
,
2141 unsigned long domainState
,
2142 IOPowerConnection
* whichParent
,
2143 unsigned long singleParentState
)
2148 // Create and initialize the new change note
2150 IOLockLock(priv
->queue_lock
);
2151 newNote
= priv
->changeList
->createChangeNote();
2152 if ( newNote
== -1 ) {
2153 // uh-oh, our list is full
2154 IOLockUnlock(priv
->queue_lock
);
2155 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogEnqueueErr
,0,0);
2156 return IOPMAckImplied
;
2159 priv
->changeList
->changeNote
[newNote
].newStateNumber
= whatStateOrdinal
;
2160 priv
->changeList
->changeNote
[newNote
].outputPowerCharacter
= pm_vars
->thePowerStates
[whatStateOrdinal
].outputPowerCharacter
;
2161 priv
->changeList
->changeNote
[newNote
].inputPowerRequirement
= pm_vars
->thePowerStates
[whatStateOrdinal
].inputPowerRequirement
;
2162 priv
->changeList
->changeNote
[newNote
].capabilityFlags
= pm_vars
->thePowerStates
[whatStateOrdinal
].capabilityFlags
;
2163 priv
->changeList
->changeNote
[newNote
].flags
= flags
;
2164 priv
->changeList
->changeNote
[newNote
].parent
= NULL
;
2165 if (flags
& IOPMParentInitiated
)
2167 priv
->changeList
->changeNote
[newNote
].domainState
= domainState
;
2168 priv
->changeList
->changeNote
[newNote
].parent
= whichParent
;
2169 whichParent
->retain();
2170 priv
->changeList
->changeNote
[newNote
].singleParentState
= singleParentState
;
2173 previousNote
= priv
->changeList
->previousChangeNote(newNote
);
2175 if ( previousNote
== -1 )
2178 // Queue is empty, we can start this change.
2180 if (flags
& IOPMWeInitiated
)
2182 IOLockUnlock(priv
->queue_lock
);
2183 start_our_change(newNote
);
2186 IOLockUnlock(priv
->queue_lock
);
2187 return start_parent_change(newNote
);
2191 // The queue is not empty. Try to collapse this new change and the previous one in queue into one change.
2192 // This is possible only if both changes are initiated by us, and neither has been started yet.
2193 // Do this more than once if possible.
2195 // (A change is started iff it is at the head of the queue)
2197 while ( (previousNote
!= priv
->head_note
) && (previousNote
!= -1) &&
2198 (priv
->changeList
->changeNote
[newNote
].flags
& priv
->changeList
->changeNote
[previousNote
].flags
& IOPMWeInitiated
) )
2200 priv
->changeList
->changeNote
[previousNote
].outputPowerCharacter
= priv
->changeList
->changeNote
[newNote
].outputPowerCharacter
;
2201 priv
->changeList
->changeNote
[previousNote
].inputPowerRequirement
= priv
->changeList
->changeNote
[newNote
].inputPowerRequirement
;
2202 priv
->changeList
->changeNote
[previousNote
].capabilityFlags
=priv
-> changeList
->changeNote
[newNote
].capabilityFlags
;
2203 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogCollapseQueue
,priv
->changeList
->changeNote
[newNote
].newStateNumber
,
2204 priv
->changeList
->changeNote
[previousNote
].newStateNumber
);
2205 priv
->changeList
->changeNote
[previousNote
].newStateNumber
= priv
->changeList
->changeNote
[newNote
].newStateNumber
;
2206 priv
->changeList
->releaseTailChangeNote();
2207 newNote
= previousNote
;
2208 previousNote
= priv
->changeList
->previousChangeNote(newNote
);
2210 IOLockUnlock(priv
->queue_lock
);
2211 // in any case, we can't start yet
2212 return IOPMWillAckLater
;
2215 //*********************************************************************************
2218 // Notify all interested parties either that a change is impending or that the
2219 // previously-notified change is done and power has settled.
2220 // The parameter identifies whether this is the
2221 // pre-change notification or the post-change notification.
2223 //*********************************************************************************
2225 IOReturn
IOService::notifyAll ( bool is_prechange
)
2227 IOPMinformee
* nextObject
;
2230 IOPowerConnection
* connection
;
2232 // To prevent acknowledgePowerChange from finishing the change note and
2233 // removing it from the queue if
2234 // some driver calls it, we inflate the number of pending acks so it
2235 // cannot become zero. We'll fix it later.
2237 if(!acquire_lock()) return IOPMAckImplied
;
2239 OSAddAtomic(1, (SInt32
*)&priv
->head_note_pendingAcks
);
2241 // OK, we will go through the lists of interested drivers and
2242 // power domain children and notify each one of this change.
2244 nextObject
= priv
->interestedDrivers
->firstInList();
2245 while ( nextObject
!= NULL
) {
2247 OSAddAtomic(1, (SInt32
*)&priv
->head_note_pendingAcks
);
2249 IOUnlock(priv
->our_lock
);
2251 inform(nextObject
, is_prechange
);
2258 nextObject
= priv
->interestedDrivers
->nextInList(nextObject
);
2261 // did they all ack?
2262 if ( priv
->head_note_pendingAcks
> 1 ) {
2264 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2268 IOUnlock(priv
->our_lock
);
2271 iter
= getChildIterator(gIOPowerPlane
);
2272 // summing their power consumption
2273 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
= 0;
2275 if ( iter
&& acquire_lock())
2277 while ( (next
= iter
->getNextObject()) )
2279 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
2281 OSAddAtomic(1, (SInt32
*)&priv
->head_note_pendingAcks
);
2283 IOUnlock(priv
->our_lock
);
2285 notifyChild(connection
, is_prechange
);
2294 IOUnlock(priv
->our_lock
);
2297 if (! acquire_lock() ) {
2300 // now make this real
2301 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
2304 if (priv
->head_note_pendingAcks
== 0 ) {
2306 IOUnlock(priv
->our_lock
);
2307 // return ack to parent
2308 return IOPMAckImplied
;
2312 IOUnlock(priv
->our_lock
);
2314 exit
: // unable to acquire_lock exit case
2316 return IOPMWillAckLater
;
2320 //*********************************************************************************
2323 // Notify a power domain child of an upcoming power change.
2325 // If the object acknowledges the current change, we return TRUE.
2326 //*********************************************************************************
2328 bool IOService::notifyChild ( IOPowerConnection
* theNub
, bool is_prechange
)
2330 IOReturn k
= IOPMAckImplied
;
2331 unsigned long childPower
;
2332 IOService
*theChild
;
2334 theChild
= (IOService
*)(theNub
->copyChildEntry(gIOPowerPlane
));
2337 // The child has been detached since we grabbed the child iterator.
2338 // Decrement pending_acks, already incremented in notifyAll,
2339 // to account for this unexpected departure.
2341 if( acquire_lock() )
2343 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
2344 IOUnlock(priv
->our_lock
);
2349 // Unless the child handles the notification immediately and returns
2350 // kIOPMAckImplied, we'll be awaiting their acknowledgement later.
2351 theNub
->setAwaitingAck(true);
2355 k
= theChild
->powerDomainWillChangeTo(priv
->head_note_outputFlags
,theNub
);
2357 k
= theChild
->powerDomainDidChangeTo(priv
->head_note_outputFlags
,theNub
);
2360 // did the return code ack?
2361 if ( k
== IOPMAckImplied
)
2364 if( acquire_lock() )
2366 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
2367 IOUnlock(priv
->our_lock
);
2370 theNub
->setAwaitingAck(false);
2371 childPower
= theChild
->currentPowerConsumption();
2372 if ( childPower
== kIOPMUnknown
)
2374 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
= kIOPMUnknown
;
2376 if ( pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
!= kIOPMUnknown
)
2378 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
+= childPower
;
2381 theChild
->release();
2384 theChild
->release();
2389 //*********************************************************************************
2392 // Notify an interested driver of an upcoming power change.
2394 // If the object acknowledges the current change, we return TRUE.
2395 //*********************************************************************************
2397 bool IOService::inform ( IOPMinformee
* nextObject
, bool is_prechange
)
2399 IOReturn k
= IOPMAckImplied
;
2402 nextObject
->timer
= -1;
2406 pm_vars
->thePlatform
->PMLog (pm_vars
->ourName
,PMlogInformDriverPreChange
,
2407 (unsigned long)priv
->head_note_capabilityFlags
,(unsigned long)priv
->head_note_state
);
2408 k
= nextObject
->whatObject
->powerStateWillChangeTo( priv
->head_note_capabilityFlags
,priv
->head_note_state
,this);
2410 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInformDriverPostChange
,
2411 (unsigned long)priv
->head_note_capabilityFlags
,(unsigned long)priv
->head_note_state
);
2412 k
= nextObject
->whatObject
->powerStateDidChangeTo(priv
->head_note_capabilityFlags
,priv
->head_note_state
,this);
2415 // did it ack behind our back?
2416 if ( nextObject
->timer
== 0 )
2422 if ( (k
==IOPMAckImplied
) // no, did the return code ack?
2423 || (k
< 0) ) // somebody goofed
2426 nextObject
->timer
= 0;
2428 if( acquire_lock() )
2430 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
2431 IOUnlock(priv
->our_lock
);
2437 nextObject
->timer
= (k
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
2443 //*********************************************************************************
2444 // OurChangeTellClientsPowerDown
2446 // All registered applications and kernel clients have positively acknowledged our
2447 // intention of lowering power. Here we notify them all that we will definitely
2448 // lower the power. If we don't have to wait for any of them to acknowledge, we
2449 // carry on by notifying interested drivers. Otherwise, we do wait.
2450 //*********************************************************************************
2452 void IOService::OurChangeTellClientsPowerDown ( void )
2455 priv
->machine_state
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
2457 // are we waiting for responses?
2458 if ( tellChangeDown1(priv
->head_note_state
) )
2460 // no, notify priority clients
2461 OurChangeTellPriorityClientsPowerDown();
2463 // If we are waiting for responses, execution will resume via
2464 // allowCancelCommon() or ack timeout
2468 //*********************************************************************************
2469 // OurChangeTellPriorityClientsPowerDown
2471 // All registered applications and kernel clients have positively acknowledged our
2472 // intention of lowering power. Here we notify "priority" clients that we are
2473 // lowering power. If we don't have to wait for any of them to acknowledge, we
2474 // carry on by notifying interested drivers. Otherwise, we do wait.
2475 //*********************************************************************************
2477 void IOService::OurChangeTellPriorityClientsPowerDown ( void )
2480 priv
->machine_state
= kIOPM_OurChangeNotifyInterestedDriversWillChange
;
2481 // are we waiting for responses?
2482 if ( tellChangeDown2(priv
->head_note_state
) )
2484 // no, notify interested drivers
2485 return OurChangeNotifyInterestedDriversWillChange();
2487 // If we are waiting for responses, execution will resume via
2488 // allowCancelCommon() or ack timeout
2492 //*********************************************************************************
2493 // OurChangeNotifyInterestedDriversWillChange
2495 // All registered applications and kernel clients have acknowledged our notification
2496 // that we are lowering power. Here we notify interested drivers. If we don't have
2497 // to wait for any of them to acknowledge, we instruct our power driver to make the change.
2498 // Otherwise, we do wait.
2499 //*********************************************************************************
2501 void IOService::OurChangeNotifyInterestedDriversWillChange ( void )
2503 // no, in case they don't all ack
2504 priv
->machine_state
= kIOPM_OurChangeSetPowerState
;
2505 if ( notifyAll(true) == IOPMAckImplied
)
2507 // not waiting for responses
2508 OurChangeSetPowerState();
2510 // If we are waiting for responses, execution will resume via
2511 // all_acked() or ack timeout
2515 //*********************************************************************************
2516 // OurChangeSetPowerState
2518 // All interested drivers have acknowledged our pre-change notification of a power
2519 // change we initiated. Here we instruct our controlling driver to make
2520 // the change to the hardware. If it does so, we continue processing
2521 // (waiting for settle and notifying interested parties post-change.)
2522 // If it doesn't, we have to wait for it to acknowledge and then continue.
2523 //*********************************************************************************
2525 void IOService::OurChangeSetPowerState ( void )
2527 priv
->machine_state
= kIOPM_OurChangeWaitForPowerSettle
;
2529 IOLockLock(priv
->our_lock
);
2531 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2533 // it's done, carry on
2534 IOLockUnlock(priv
->our_lock
);
2535 OurChangeWaitForPowerSettle();
2537 // it's not, wait for it
2538 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2540 IOLockUnlock(priv
->our_lock
);
2541 // execution will resume via ack_timer_ticked()
2546 //*********************************************************************************
2547 // OurChangeWaitForPowerSettle
2549 // Our controlling driver has changed power state on the hardware
2550 // during a power change we initiated. Here we see if we need to wait
2551 // for power to settle before continuing. If not, we continue processing
2552 // (notifying interested parties post-change). If so, we wait and
2554 //*********************************************************************************
2556 void IOService::OurChangeWaitForPowerSettle ( void )
2558 priv
->settle_time
= compute_settle_time();
2559 if ( priv
->settle_time
== 0 )
2561 OurChangeNotifyInterestedDriversDidChange();
2563 priv
->machine_state
= kIOPM_OurChangeNotifyInterestedDriversDidChange
;
2564 startSettleTimer(priv
->settle_time
);
2569 //*********************************************************************************
2570 // OurChangeNotifyInterestedDriversDidChange
2572 // Power has settled on a power change we initiated. Here we notify
2573 // all our interested parties post-change. If they all acknowledge, we're
2574 // done with this change note, and we can start on the next one.
2575 // Otherwise we have to wait for acknowledgements and finish up later.
2576 //*********************************************************************************
2578 void IOService::OurChangeNotifyInterestedDriversDidChange ( void )
2580 // in case they don't all ack
2581 priv
->machine_state
= kIOPM_OurChangeFinish
;
2582 if ( notifyAll(false) == IOPMAckImplied
)
2584 // not waiting for responses
2587 // If we are waiting for responses, execution will resume via
2588 // all_acked() or ack timeout
2592 //*********************************************************************************
2595 // Power has settled on a power change we initiated, and
2596 // all our interested parties have acknowledged. We're
2597 // done with this change note, and we can start on the next one.
2598 //*********************************************************************************
2600 void IOService::OurChangeFinish ( void )
2606 //*********************************************************************************
2607 // ParentDownTellPriorityClientsPowerDown_Immediate
2609 // All applications and kernel clients have been notified of a power lowering
2610 // initiated by the parent and we didn't have to wait for any responses. Here
2611 // we notify any priority clients. If they all ack, we continue with the power change.
2612 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2613 //*********************************************************************************
2615 IOReturn
IOService::ParentDownTellPriorityClientsPowerDown_Immediate ( void )
2617 // in case they don't all ack
2618 priv
->machine_state
= kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
;
2619 // are we waiting for responses?
2620 if ( tellChangeDown2(priv
->head_note_state
) )
2622 // no, notify interested drivers
2623 return ParentDownNotifyInterestedDriversWillChange_Immediate();
2625 // If we are waiting for responses, execution will resume via
2626 // allowCancelCommon() or ack timeout
2627 return IOPMWillAckLater
;
2631 //*********************************************************************************
2632 // ParentDownTellPriorityClientsPowerDown_Immediate2
2634 // All priority kernel clients have been notified of a power lowering
2635 // initiated by the parent and we didn't have to wait for any responses. Here
2636 // we notify any interested drivers and power domain children. If they all ack,
2637 // we continue with the power change.
2638 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2639 //*********************************************************************************
2641 IOReturn
IOService::ParentDownNotifyInterestedDriversWillChange_Immediate ( void )
2643 // in case they don't all ack
2644 priv
->machine_state
= kIOPM_ParentDownSetPowerState_Delayed
;
2645 if ( notifyAll(true) == IOPMAckImplied
)
2648 return ParentDownSetPowerState_Immediate();
2650 // If we are waiting for responses, execution will resume via
2651 // all_acked() or ack timeout
2652 return IOPMWillAckLater
;
2656 //*********************************************************************************
2657 // ParentDownTellPriorityClientsPowerDown_Immediate4
2659 // All applications and kernel clients have been notified of a power lowering
2660 // initiated by the parent and we had to wait for responses. Here
2661 // we notify any priority clients. If they all ack, we continue with the power change.
2662 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2663 //*********************************************************************************
2665 void IOService::ParentDownTellPriorityClientsPowerDown_Delayed ( void )
2667 // in case they don't all ack
2668 priv
->machine_state
= kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
;
2670 // are we waiting for responses?
2671 if ( tellChangeDown2(priv
->head_note_state
) )
2673 // no, notify interested drivers
2674 ParentDownNotifyInterestedDriversWillChange_Delayed();
2676 // If we are waiting for responses, execution will resume via
2677 // allowCancelCommon() or ack timeout
2681 //*********************************************************************************
2682 // ParentDownTellPriorityClientsPowerDown_Immediate5
2684 // All applications and kernel clients have been notified of a power lowering
2685 // initiated by the parent and we had to wait for their responses. Here we notify
2686 // any interested drivers and power domain children. If they all ack, we continue
2687 // with the power change.
2688 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2689 //*********************************************************************************
2691 void IOService::ParentDownNotifyInterestedDriversWillChange_Delayed ( void )
2693 // in case they don't all ack
2694 priv
->machine_state
= kIOPM_ParentDownSetPowerState_Delayed
;
2695 if ( notifyAll(true) == IOPMAckImplied
)
2698 ParentDownSetPowerState_Delayed();
2700 // If we are waiting for responses, execution will resume via
2701 // all_acked() or ack timeout
2705 //*********************************************************************************
2706 // ParentDownSetPowerState_Immediate
2708 // All parties have acknowledged our pre-change notification of a power
2709 // lowering initiated by the parent. Here we instruct our controlling driver
2710 // to put the hardware in the state it needs to be in when the domain is
2711 // lowered. If it does so, we continue processing
2712 // (waiting for settle and acknowledging the parent.)
2713 // If it doesn't, we have to wait for it to acknowledge and then continue.
2714 //*********************************************************************************
2716 IOReturn
IOService::ParentDownSetPowerState_Immediate ( void )
2718 priv
->machine_state
= kIOPM_ParentDownWaitForPowerSettle_Delayed
;
2720 IOLockLock(priv
->our_lock
);
2722 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2724 // it's done, carry on
2725 IOLockUnlock(priv
->our_lock
);
2726 return ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate();
2728 // it's not, wait for it
2729 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2731 IOLockUnlock(priv
->our_lock
);
2732 return IOPMWillAckLater
;
2736 //*********************************************************************************
2737 // ParentDownSetPowerState_Delayed
2739 // We had to wait for it, but all parties have acknowledged our pre-change
2740 // notification of a power lowering initiated by the parent.
2741 // Here we instruct our controlling driver
2742 // to put the hardware in the state it needs to be in when the domain is
2743 // lowered. If it does so, we continue processing
2744 // (waiting for settle and acknowledging the parent.)
2745 // If it doesn't, we have to wait for it to acknowledge and then continue.
2746 //*********************************************************************************
2748 void IOService::ParentDownSetPowerState_Delayed ( void )
2750 priv
-> machine_state
= kIOPM_ParentDownWaitForPowerSettle_Delayed
;
2752 IOLockLock(priv
->our_lock
);
2754 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2756 // it's done, carry on
2757 IOLockUnlock(priv
->our_lock
);
2758 ParentDownWaitForPowerSettle_Delayed();
2760 // it's not, wait for it
2761 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2763 IOLockUnlock(priv
->our_lock
);
2768 //*********************************************************************************
2769 // ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate
2771 // Our controlling driver has changed power state on the hardware
2772 // during a power change initiated by our parent. Here we see if we need
2773 // to wait for power to settle before continuing. If not, we continue
2774 // processing (acknowledging our preparedness to the parent).
2775 // If so, we wait and continue later.
2776 //*********************************************************************************
2778 IOReturn
IOService::ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate ( void )
2782 priv
->settle_time
= compute_settle_time();
2783 if ( priv
->settle_time
== 0 )
2785 // store current state in case they don't all ack
2786 priv
->machine_state
= kIOPM_ParentDownAcknowledgeChange_Delayed
;
2787 if ( notifyAll(false) == IOPMAckImplied
)
2789 // not waiting for responses
2790 nub
= priv
->head_note_parent
;
2794 return IOPMAckImplied
;
2796 // If we are waiting for responses, execution will resume via
2797 // all_acked() or ack timeout
2798 return IOPMWillAckLater
;
2800 // let settle time elapse, then notify interest drivers of our power state change in ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
2801 priv
->machine_state
= kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
;
2802 startSettleTimer(priv
->settle_time
);
2803 return IOPMWillAckLater
;
2808 //*********************************************************************************
2809 // ParentDownWaitForPowerSettle_Delayed
2811 // Our controlling driver has changed power state on the hardware
2812 // during a power change initiated by our parent. We have had to wait
2813 // for acknowledgement from interested parties, or we have had to wait
2814 // for the controlling driver to change the state. Here we see if we need
2815 // to wait for power to settle before continuing. If not, we continue
2816 // processing (acknowledging our preparedness to the parent).
2817 // If so, we wait and continue later.
2818 //*********************************************************************************
2820 void IOService::ParentDownWaitForPowerSettle_Delayed ( void )
2822 priv
->settle_time
= compute_settle_time();
2823 if ( priv
->settle_time
== 0 )
2825 ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed();
2827 priv
->machine_state
= kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
;
2828 startSettleTimer(priv
->settle_time
);
2833 //*********************************************************************************
2834 // ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
2836 // Power has settled on a power change initiated by our parent. Here we
2837 // notify interested parties.
2838 //*********************************************************************************
2840 void IOService::ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed ( void )
2842 IORegistryEntry
*nub
;
2845 // in case they don't all ack
2846 priv
->machine_state
= kIOPM_ParentDownAcknowledgeChange_Delayed
;
2847 if ( notifyAll(false) == IOPMAckImplied
) {
2848 nub
= priv
->head_note_parent
;
2851 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
2853 parent
->acknowledgePowerChange((IOService
*)nub
);
2858 // If we are waiting for responses, execution will resume via
2859 // all_acked() or ack timeout in ParentDownAcknowledgeChange_Delayed.
2860 // Notice the duplication of code just above and in ParentDownAcknowledgeChange_Delayed.
2864 //*********************************************************************************
2865 // ParentDownAcknowledgeChange_Delayed
2867 // We had to wait for it, but all parties have acknowledged our post-change
2868 // notification of a power lowering initiated by the parent.
2869 // Here we acknowledge the parent.
2870 // We are done with this change note, and we can start on the next one.
2871 //*********************************************************************************
2873 void IOService::ParentDownAcknowledgeChange_Delayed ( void )
2875 IORegistryEntry
*nub
;
2878 nub
= priv
->head_note_parent
;
2881 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
2884 parent
->acknowledgePowerChange((IOService
*)nub
);
2891 //*********************************************************************************
2892 // ParentUpSetPowerState_Delayed
2894 // Our parent has informed us via powerStateDidChange that it has
2895 // raised the power in our power domain, and we have had to wait
2896 // for some interested party to acknowledge our notification.
2897 // Here we instruct our controlling
2898 // driver to program the hardware to take advantage of the higher domain
2899 // power. If it does so, we continue processing
2900 // (waiting for settle and notifying interested parties post-change.)
2901 // If it doesn't, we have to wait for it to acknowledge and then continue.
2902 //*********************************************************************************
2904 void IOService::ParentUpSetPowerState_Delayed ( void )
2906 priv
->machine_state
= kIOPM_ParentUpWaitForSettleTime_Delayed
;
2908 IOLockLock(priv
->our_lock
);
2910 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2912 // it did it, carry on
2913 IOLockUnlock(priv
->our_lock
);
2914 ParentUpWaitForSettleTime_Delayed();
2916 // it didn't, wait for it
2917 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2919 IOLockUnlock(priv
->our_lock
);
2924 //*********************************************************************************
2925 // ParentUpSetPowerState_Immediate
2927 // Our parent has informed us via powerStateDidChange that it has
2928 // raised the power in our power domain. Here we instruct our controlling
2929 // driver to program the hardware to take advantage of the higher domain
2930 // power. If it does so, we continue processing
2931 // (waiting for settle and notifying interested parties post-change.)
2932 // If it doesn't, we have to wait for it to acknowledge and then continue.
2933 //*********************************************************************************
2935 IOReturn
IOService::ParentUpSetPowerState_Immediate ( void )
2937 priv
->machine_state
= kIOPM_ParentUpWaitForSettleTime_Delayed
;
2939 IOLockLock(priv
->our_lock
);
2941 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2943 // it did it, carry on
2944 IOLockUnlock(priv
->our_lock
);
2945 return ParentUpWaitForSettleTime_Immediate();
2948 // it didn't, wait for it
2949 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2951 IOLockUnlock(priv
->our_lock
);
2952 return IOPMWillAckLater
;
2957 //*********************************************************************************
2958 // ParentUpWaitForSettleTime_Immediate
2960 // Our controlling driver has changed power state on the hardware
2961 // during a power raise initiated by the parent. Here we see if we need to wait
2962 // for power to settle before continuing. If not, we continue processing
2963 // (notifying interested parties post-change). If so, we wait and
2965 //*********************************************************************************
2967 IOReturn
IOService::ParentUpWaitForSettleTime_Immediate ( void )
2969 priv
->settle_time
= compute_settle_time();
2970 if ( priv
->settle_time
== 0 )
2972 return ParentUpNotifyInterestedDriversDidChange_Immediate();
2974 priv
->machine_state
= kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed
;
2975 startSettleTimer(priv
->settle_time
);
2976 return IOPMWillAckLater
;
2981 //*********************************************************************************
2982 // ParentUpWaitForSettleTime_Delayed
2984 // Our controlling driver has changed power state on the hardware
2985 // during a power raise initiated by the parent, but we had to wait for it.
2986 // Here we see if we need to wait for power to settle before continuing.
2987 // If not, we continue processing (notifying interested parties post-change).
2988 // If so, we wait and continue later.
2989 //*********************************************************************************
2991 void IOService::ParentUpWaitForSettleTime_Delayed ( void )
2993 priv
->settle_time
= compute_settle_time();
2994 if ( priv
->settle_time
== 0 )
2996 ParentUpNotifyInterestedDriversDidChange_Delayed();
2998 priv
->machine_state
= kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed
;
2999 startSettleTimer(priv
->settle_time
);
3004 //*********************************************************************************
3005 // ParentUpNotifyInterestedDriversDidChange_Immediate
3007 // No power settling was required on a power raise initiated by the parent.
3008 // Here we notify all our interested parties post-change. If they all acknowledge,
3009 // we're done with this change note, and we can start on the next one.
3010 // Otherwise we have to wait for acknowledgements and finish up later.
3011 //*********************************************************************************
3013 IOReturn
IOService::ParentUpNotifyInterestedDriversDidChange_Immediate ( void )
3017 // in case they don't all ack
3018 priv
->machine_state
= kIOPM_ParentUpAcknowledgePowerChange_Delayed
;
3019 if ( notifyAll(false) == IOPMAckImplied
)
3021 nub
= priv
->head_note_parent
;
3025 return IOPMAckImplied
;
3027 // If we are waiting for responses, execution will resume via
3028 // all_acked() or ack timeout in ParentUpAcknowledgePowerChange_Delayed.
3029 return IOPMWillAckLater
;
3033 //*********************************************************************************
3034 // ParentUpNotifyInterestedDriversDidChange_Delayed
3036 // Power has settled on a power raise initiated by the parent.
3037 // Here we notify all our interested parties post-change. If they all acknowledge,
3038 // we're done with this change note, and we can start on the next one.
3039 // Otherwise we have to wait for acknowledgements and finish up later.
3040 //*********************************************************************************
3042 void IOService::ParentUpNotifyInterestedDriversDidChange_Delayed ( void )
3044 // in case they don't all ack
3045 priv
->machine_state
= kIOPM_ParentUpAcknowledgePowerChange_Delayed
;
3046 if ( notifyAll(false) == IOPMAckImplied
)
3048 ParentUpAcknowledgePowerChange_Delayed();
3050 // If we are waiting for responses, execution will resume via
3051 // all_acked() or ack timeout in ParentUpAcknowledgePowerChange_Delayed.
3055 //*********************************************************************************
3056 // ParentUpAcknowledgePowerChange_Delayed
3058 // All parties have acknowledged our post-change notification of a power
3059 // raising initiated by the parent. Here we acknowledge the parent.
3060 // We are done with this change note, and we can start on the next one.
3061 //*********************************************************************************
3063 void IOService::ParentUpAcknowledgePowerChange_Delayed ( void )
3065 IORegistryEntry
*nub
;
3068 nub
= priv
->head_note_parent
;
3071 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
3074 parent
->acknowledgePowerChange((IOService
*)nub
);
3081 //*********************************************************************************
3084 // A power change is complete, and the used post-change note is at
3085 // the head of the queue. Remove it and set myCurrentState to the result
3086 // of the change. Start up the next change in queue.
3087 //*********************************************************************************
3089 void IOService::all_done ( void )
3091 unsigned long previous_state
;
3092 IORegistryEntry
*nub
;
3095 priv
->machine_state
= kIOPM_Finished
;
3098 if ( priv
->head_note_flags
& IOPMWeInitiated
)
3100 // could our driver switch to the new state?
3101 if ( !( priv
->head_note_flags
& IOPMNotDone
) )
3103 // yes, did power raise?
3104 if ( pm_vars
->myCurrentState
< priv
->head_note_state
)
3106 // yes, inform clients and apps
3107 tellChangeUp (priv
->head_note_state
);
3109 // no, if this lowers our
3110 if ( ! priv
->we_are_root
)
3112 // power requirements, tell the parent
3113 ask_parent(priv
->head_note_state
);
3116 previous_state
= pm_vars
->myCurrentState
;
3118 pm_vars
->myCurrentState
= priv
->head_note_state
;
3119 priv
->imminentState
= pm_vars
->myCurrentState
;
3120 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeDone
,(unsigned long)pm_vars
->myCurrentState
,0);
3121 // inform subclass policy-maker
3122 powerChangeDone(previous_state
);
3126 // parent's power change
3127 if ( priv
->head_note_flags
& IOPMParentInitiated
)
3129 if ( ((priv
->head_note_flags
& IOPMDomainWillChange
) && (pm_vars
->myCurrentState
>= priv
->head_note_state
)) ||
3130 ((priv
->head_note_flags
& IOPMDomainDidChange
) && (pm_vars
->myCurrentState
< priv
->head_note_state
)) )
3133 if ( pm_vars
->myCurrentState
< priv
->head_note_state
)
3135 // yes, inform clients and apps
3136 tellChangeUp (priv
->head_note_state
);
3139 previous_state
= pm_vars
->myCurrentState
;
3140 pm_vars
->myCurrentState
= priv
->head_note_state
;
3141 priv
->imminentState
= pm_vars
->myCurrentState
;
3142 pm_vars
->maxCapability
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(priv
->head_note_domainState
);
3144 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeDone
,(unsigned long)pm_vars
->myCurrentState
,0);
3145 // inform subclass policy-maker
3146 powerChangeDone(previous_state
);
3150 IOLockLock(priv
->queue_lock
);
3151 // we're done with this
3152 priv
->changeList
->releaseHeadChangeNote();
3154 // start next one in queue
3155 priv
->head_note
= priv
->changeList
->currentChange();
3156 if ( priv
->head_note
!= -1 )
3159 IOLockUnlock(priv
->queue_lock
);
3160 if (priv
->changeList
->changeNote
[priv
->head_note
].flags
& IOPMWeInitiated
)
3162 start_our_change(priv
->head_note
);
3164 nub
= priv
->changeList
->changeNote
[priv
->head_note
].parent
;
3165 if (nub
) nub
->retain(); // might be released by start_parent_change()
3166 if ( start_parent_change(priv
->head_note
) == IOPMAckImplied
)
3168 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
3171 parent
->acknowledgePowerChange((IOService
*)nub
);
3175 if (nub
) nub
->release();
3178 IOLockUnlock(priv
->queue_lock
);
3184 //*********************************************************************************
3187 // A driver or child has acknowledged our notification of an upcoming power
3188 // change, and this acknowledgement is the last one pending
3189 // before we change power or after changing power.
3191 //*********************************************************************************
3195 void IOService::all_acked( void )
3197 switch (priv
->machine_state
) {
3198 case kIOPM_OurChangeSetPowerState
:
3199 OurChangeSetPowerState();
3201 case kIOPM_OurChangeFinish
:
3204 case kIOPM_ParentDownSetPowerState_Delayed
:
3205 ParentDownSetPowerState_Delayed();
3207 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3208 ParentDownAcknowledgeChange_Delayed();
3210 case kIOPM_ParentUpSetPowerState_Delayed
:
3211 ParentUpSetPowerState_Delayed();
3213 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3214 ParentUpAcknowledgePowerChange_Delayed();
3219 //*********************************************************************************
3220 // settleTimerExpired
3222 // Power has settled after our last change. Notify interested parties that
3223 // there is a new power state.
3224 //*********************************************************************************
3226 void IOService::settleTimerExpired ( void )
3228 if ( ! initialized
)
3234 switch (priv
->machine_state
) {
3235 case kIOPM_OurChangeNotifyInterestedDriversDidChange
:
3236 OurChangeNotifyInterestedDriversDidChange();
3238 case kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
:
3239 ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed();
3241 case kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed
:
3242 ParentUpNotifyInterestedDriversDidChange_Delayed();
3248 //*********************************************************************************
3249 // compute_settle_time
3251 // Compute the power-settling delay in microseconds for the
3252 // change from myCurrentState to head_note_state.
3253 //*********************************************************************************
3255 unsigned long IOService::compute_settle_time ( void )
3257 unsigned long totalTime
;
3260 // compute total time to attain the new state
3262 i
= pm_vars
->myCurrentState
;
3264 // we're lowering power
3265 if ( priv
->head_note_state
< pm_vars
->myCurrentState
)
3267 while ( i
> priv
->head_note_state
)
3269 totalTime
+= pm_vars
->thePowerStates
[i
].settleDownTime
;
3274 // we're raising power
3275 if ( priv
->head_note_state
> pm_vars
->myCurrentState
)
3277 while ( i
< priv
->head_note_state
)
3279 totalTime
+= pm_vars
->thePowerStates
[i
+1].settleUpTime
;
3288 //*********************************************************************************
3291 // Enter with a power-settling delay in microseconds and start a nano-second
3292 // timer for that delay.
3293 //*********************************************************************************
3295 IOReturn
IOService::startSettleTimer ( unsigned long delay
)
3297 AbsoluteTime deadline
;
3299 clock_interval_to_deadline(delay
, kMicrosecondScale
, &deadline
);
3301 thread_call_enter_delayed(priv
->settleTimer
, deadline
);
3306 //*********************************************************************************
3309 // The acknowledgement timeout periodic timer has ticked.
3310 // If we are awaiting acks for a power change notification,
3311 // we decrement the timer word of each interested driver which hasn't acked.
3312 // If a timer word becomes zero, we pretend the driver aknowledged.
3313 // If we are waiting for the controlling driver to change the power
3314 // state of the hardware, we decrement its timer word, and if it becomes
3315 // zero, we pretend the driver acknowledged.
3316 //*********************************************************************************
3318 void IOService::ack_timer_ticked ( void )
3320 IOPMinformee
* nextObject
;
3322 if ( ! initialized
)
3328 if (! acquire_lock() )
3333 switch (priv
->machine_state
) {
3334 case kIOPM_OurChangeWaitForPowerSettle
:
3335 case kIOPM_ParentDownWaitForPowerSettle_Delayed
:
3336 case kIOPM_ParentUpWaitForSettleTime_Delayed
:
3337 // are we waiting for our driver to make its change?
3338 if ( priv
->driver_timer
!= 0 ) {
3340 priv
->driver_timer
-= 1;
3341 // it's tardy, we'll go on without it
3342 if ( priv
->driver_timer
== 0 )
3344 IOUnlock(priv
->our_lock
);
3345 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogCtrlDriverTardy
,0,0);
3348 // still waiting, set timer again
3350 IOUnlock(priv
->our_lock
);
3354 IOUnlock(priv
->our_lock
);
3358 case kIOPM_OurChangeSetPowerState
:
3359 case kIOPM_OurChangeFinish
:
3360 case kIOPM_ParentDownSetPowerState_Delayed
:
3361 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3362 case kIOPM_ParentUpSetPowerState_Delayed
:
3363 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3364 // are we waiting for interested parties to acknowledge?
3365 if (priv
->head_note_pendingAcks
!= 0 )
3367 // yes, go through the list of interested drivers
3368 nextObject
= priv
->interestedDrivers
->firstInList();
3369 // and check each one
3370 while ( nextObject
!= NULL
)
3372 if ( nextObject
->timer
> 0 )
3374 nextObject
->timer
-= 1;
3375 // this one should have acked by now
3376 if ( nextObject
->timer
== 0 )
3378 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogIntDriverTardy
,0,0);
3379 //kprintf("interested driver tardy: %s\n",nextObject->whatObject->getName());
3380 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
3383 nextObject
= priv
->interestedDrivers
->nextInList(nextObject
);
3386 // is that the last?
3387 if ( priv
->head_note_pendingAcks
== 0 )
3389 IOUnlock(priv
->our_lock
);
3390 // yes, we can continue
3393 // no, set timer again
3395 IOUnlock(priv
->our_lock
);
3398 IOUnlock(priv
->our_lock
);
3402 // apps didn't respond to parent-down notification
3403 case kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate
:
3404 IOUnlock(priv
->our_lock
);
3405 IOLockLock(priv
->flags_lock
);
3406 if (pm_vars
->responseFlags
)
3408 // get rid of this stuff
3409 pm_vars
->responseFlags
->release();
3410 pm_vars
->responseFlags
= NULL
;
3412 IOLockUnlock(priv
->flags_lock
);
3413 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,5);
3414 // carry on with the change
3415 ParentDownTellPriorityClientsPowerDown_Delayed();
3418 case kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
:
3419 IOUnlock(priv
->our_lock
);
3420 IOLockLock(priv
->flags_lock
);
3421 if (pm_vars
->responseFlags
)
3423 // get rid of this stuff
3424 pm_vars
->responseFlags
->release();
3425 pm_vars
->responseFlags
= NULL
;
3427 IOLockUnlock(priv
->flags_lock
);
3428 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,1);
3429 // carry on with the change
3430 ParentDownNotifyInterestedDriversWillChange_Delayed();
3433 case kIOPM_OurChangeTellClientsPowerDown
:
3434 // apps didn't respond to our power-down request
3435 IOUnlock(priv
->our_lock
);
3436 IOLockLock(priv
->flags_lock
);
3437 if (pm_vars
->responseFlags
)
3439 // get rid of this stuff
3440 pm_vars
->responseFlags
->release();
3441 pm_vars
->responseFlags
= NULL
;
3443 IOLockUnlock(priv
->flags_lock
);
3444 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,2);
3445 // rescind the request
3446 tellNoChangeDown(priv
->head_note_state
);
3447 // mark the change note un-actioned
3448 priv
->head_note_flags
|= IOPMNotDone
;
3453 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
3454 // clients didn't respond to our power-down note
3455 IOUnlock(priv
->our_lock
);
3456 IOLockLock(priv
->flags_lock
);
3457 if (pm_vars
->responseFlags
)
3459 // get rid of this stuff
3460 pm_vars
->responseFlags
->release();
3461 pm_vars
->responseFlags
= NULL
;
3463 IOLockUnlock(priv
->flags_lock
);
3464 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,4);
3465 // carry on with the change
3466 OurChangeTellPriorityClientsPowerDown();
3469 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
3470 // apps didn't respond to our power-down notification
3471 IOUnlock(priv
->our_lock
);
3472 IOLockLock(priv
->flags_lock
);
3473 if (pm_vars
->responseFlags
)
3475 // get rid of this stuff
3476 pm_vars
->responseFlags
->release();
3477 pm_vars
->responseFlags
= NULL
;
3479 IOLockUnlock(priv
->flags_lock
);
3480 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,3);
3481 // carry on with the change
3482 OurChangeNotifyInterestedDriversWillChange();
3486 // not waiting for acks
3487 IOUnlock(priv
->our_lock
);
3493 //*********************************************************************************
3496 //*********************************************************************************
3498 void IOService::start_ack_timer ( void )
3500 AbsoluteTime deadline
;
3502 clock_interval_to_deadline(ACK_TIMER_PERIOD
, kNanosecondScale
, &deadline
);
3504 thread_call_enter_delayed(priv
->ackTimer
, deadline
);
3508 //*********************************************************************************
3511 //*********************************************************************************
3513 void IOService::stop_ack_timer ( void )
3515 thread_call_cancel(priv
->ackTimer
);
3519 //*********************************************************************************
3520 // c-language timer expiration functions
3522 //*********************************************************************************
3524 static void ack_timer_expired ( thread_call_param_t us
)
3526 ((IOService
*)us
)->ack_timer_ticked();
3530 static void settle_timer_expired ( thread_call_param_t us
)
3532 ((IOService
*)us
)->settleTimerExpired();
3536 //*********************************************************************************
3537 // add_child_to_active_change
3539 // A child has just registered with us. If there is
3540 // currently a change in progress, get the new party involved: if we
3541 // have notified all parties and are waiting for acks, notify the new
3543 //*********************************************************************************
3545 IOReturn
IOService::add_child_to_active_change ( IOPowerConnection
* newObject
)
3547 if (! acquire_lock() )
3552 switch (priv
->machine_state
)
3554 case kIOPM_OurChangeSetPowerState
:
3555 case kIOPM_ParentDownSetPowerState_Delayed
:
3556 case kIOPM_ParentUpSetPowerState_Delayed
:
3557 // one for this child and one to prevent
3558 OSAddAtomic(2, (SInt32
*)&priv
->head_note_pendingAcks
);
3559 // incoming acks from changing our state
3560 IOUnlock(priv
->our_lock
);
3561 notifyChild(newObject
, true);
3562 if (! acquire_lock() )
3565 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
3568 // are we still waiting for acks?
3569 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
3570 if ( priv
->head_note_pendingAcks
== 0 )
3572 // no, stop the timer
3574 IOUnlock(priv
->our_lock
);
3576 // and now we can continue
3581 case kIOPM_OurChangeFinish
:
3582 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3583 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3584 // one for this child and one to prevent
3585 OSAddAtomic(2, (SInt32
*)&priv
->head_note_pendingAcks
);
3586 // incoming acks from changing our state
3587 IOUnlock(priv
->our_lock
);
3588 notifyChild(newObject
, false);
3589 if (! acquire_lock() )
3592 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
3595 // are we still waiting for acks?
3596 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
3597 if ( priv
->head_note_pendingAcks
== 0 )
3599 // no, stop the timer
3601 IOUnlock(priv
->our_lock
);
3603 // and now we can continue
3609 IOUnlock(priv
->our_lock
);
3614 //*********************************************************************************
3615 // add_driver_to_active_change
3617 // An interested driver has just registered with us. If there is
3618 // currently a change in progress, get the new party involved: if we
3619 // have notified all parties and are waiting for acks, notify the new
3621 //*********************************************************************************
3623 IOReturn
IOService::add_driver_to_active_change ( IOPMinformee
* newObject
)
3625 if (! acquire_lock() )
3630 switch (priv
->machine_state
) {
3631 case kIOPM_OurChangeSetPowerState
:
3632 case kIOPM_ParentDownSetPowerState_Delayed
:
3633 case kIOPM_ParentUpSetPowerState_Delayed
:
3634 // one for this driver and one to prevent
3635 OSAddAtomic(2, (SInt32
*)&priv
->head_note_pendingAcks
);
3636 // incoming acks from changing our state
3637 IOUnlock(priv
->our_lock
);
3638 // inform the driver
3639 inform(newObject
, true);
3640 if (! acquire_lock() )
3643 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
3646 // are we still waiting for acks?
3647 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
3648 if ( priv
->head_note_pendingAcks
== 0 )
3650 // no, stop the timer
3652 IOUnlock(priv
->our_lock
);
3654 // and now we can continue
3659 case kIOPM_OurChangeFinish
:
3660 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3661 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3662 // one for this driver and one to prevent
3663 OSAddAtomic(2, (SInt32
*)&priv
->head_note_pendingAcks
);
3664 // incoming acks from changing our state
3665 IOUnlock(priv
->our_lock
);
3666 // inform the driver
3667 inform(newObject
, false);
3668 if (! acquire_lock() ) {
3670 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
3673 // are we still waiting for acks?
3674 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
3675 if ( priv
->head_note_pendingAcks
== 0 ) {
3676 // no, stop the timer
3678 IOUnlock(priv
->our_lock
);
3680 // and now we can continue
3686 IOUnlock(priv
->our_lock
);
3691 //*********************************************************************************
3692 // start_parent_change
3694 // Here we begin the processing of a change note initiated by our parent
3695 // which is at the head of the queue.
3697 // It is possible for the change to be processed to completion and removed from the queue.
3698 // There are several possible interruptions to the processing, though, and they are:
3699 // we may have to wait for interested parties to acknowledge our pre-change notification,
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 IOReturn
IOService::start_parent_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_domainState
= priv
->changeList
->changeNote
[priv
->head_note
].domainState
;
3715 priv
->head_note_parent
= priv
->changeList
->changeNote
[priv
->head_note
].parent
;
3716 priv
->head_note_capabilityFlags
= priv
->changeList
->changeNote
[priv
->head_note
].capabilityFlags
;
3718 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartParentChange
,
3719 (unsigned long)priv
->head_note_state
,(unsigned long)pm_vars
->myCurrentState
);
3721 // if we need something and haven't told the parent, do so
3722 ask_parent( priv
->ourDesiredPowerState
);
3724 // power domain is lowering
3725 if ( priv
->head_note_state
< pm_vars
->myCurrentState
)
3727 setParentInfo(priv
->changeList
->changeNote
[priv
->head_note
].singleParentState
,priv
->head_note_parent
);
3728 priv
->initial_change
= false;
3729 // tell apps and kernel clients
3730 priv
->machine_state
= kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate
;
3732 // are we waiting for responses?
3733 if ( tellChangeDown1(priv
->head_note_state
) )
3735 // no, notify priority clients
3736 return ParentDownTellPriorityClientsPowerDown_Immediate();
3739 return IOPMWillAckLater
;
3742 // parent is raising power, we may or may not
3743 if ( priv
->head_note_state
> pm_vars
->myCurrentState
)
3745 if ( priv
->ourDesiredPowerState
> pm_vars
->myCurrentState
)
3747 if ( priv
->ourDesiredPowerState
< priv
->head_note_state
)
3749 // we do, but not all the way
3750 priv
->head_note_state
= priv
->ourDesiredPowerState
;
3751 priv
->imminentState
= priv
->head_note_state
;
3752 priv
->head_note_outputFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].outputPowerCharacter
;
3753 priv
->head_note_capabilityFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].capabilityFlags
;
3754 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAmendParentChange
,(unsigned long)priv
->head_note_state
,0);
3758 priv
->head_note_state
= pm_vars
->myCurrentState
;
3759 priv
->imminentState
= priv
->head_note_state
;
3760 priv
->head_note_outputFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].outputPowerCharacter
;
3761 priv
->head_note_capabilityFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].capabilityFlags
;
3762 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAmendParentChange
,(unsigned long)priv
->head_note_state
,0);
3766 if ( (priv
->head_note_state
> pm_vars
->myCurrentState
) &&
3767 (priv
->head_note_flags
& IOPMDomainDidChange
) )
3770 priv
->initial_change
= false;
3771 priv
->machine_state
= kIOPM_ParentUpSetPowerState_Delayed
;
3772 if ( notifyAll(true) == IOPMAckImplied
) {
3773 return ParentUpSetPowerState_Immediate();
3775 // they didn't all ack
3776 return IOPMWillAckLater
;
3780 // a null change or power will go up
3781 return IOPMAckImplied
;
3785 //*********************************************************************************
3788 // Here we begin the processing of a change note initiated by us
3789 // which is at the head of the queue.
3791 // It is possible for the change to be processed to completion and removed from the queue.
3792 // There are several possible interruptions to the processing, though, and they are:
3793 // we may have to wait for interested parties to acknowledge our pre-change notification,
3794 // changes initiated by the parent will wait in the middle for powerStateDidChange,
3795 // we may have to wait for our controlling driver to change the hardware power state,
3796 // there may be a settling time after changing the hardware power state,
3797 // we may have to wait for interested parties to acknowledge our post-change notification,
3798 // we may have to wait for the acknowledgement timer expiration to substitute for the
3799 // acknowledgement from a failing driver.
3800 //*********************************************************************************
3802 void IOService::start_our_change ( unsigned long queue_head
)
3804 priv
->head_note
= queue_head
;
3805 priv
->head_note_flags
= priv
->changeList
->changeNote
[priv
->head_note
].flags
;
3806 priv
->head_note_state
= priv
->changeList
->changeNote
[priv
->head_note
].newStateNumber
;
3807 priv
->imminentState
= priv
->head_note_state
;
3808 priv
->head_note_outputFlags
= priv
->changeList
->changeNote
[priv
->head_note
].outputPowerCharacter
;
3809 priv
->head_note_capabilityFlags
= priv
->changeList
->changeNote
[priv
->head_note
].capabilityFlags
;
3811 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartDeviceChange
,
3812 (unsigned long)priv
->head_note_state
,(unsigned long)pm_vars
->myCurrentState
);
3814 // can our driver switch to the new state?
3815 if ( priv
->head_note_capabilityFlags
& IOPMNotAttainable
)
3817 // no, ask the parent to do it then
3818 if ( ! priv
->we_are_root
)
3820 ask_parent(priv
->head_note_state
);
3822 // mark the change note un-actioned
3823 priv
-> head_note_flags
|= IOPMNotDone
;
3829 // is there enough power in the domain?
3830 if ( (pm_vars
->maxCapability
< priv
->head_note_state
) && (! priv
->we_are_root
) )
3832 // no, ask the parent to raise it
3833 if ( ! priv
->we_are_root
)
3835 ask_parent(priv
->head_note_state
);
3837 // no, mark the change note un-actioned
3838 priv
->head_note_flags
|= IOPMNotDone
;
3840 // till the parent raises power
3845 if ( ! priv
->initial_change
)
3847 if ( priv
->head_note_state
== pm_vars
->myCurrentState
)
3849 // we initiated a null change; forget it
3854 priv
->initial_change
= false;
3857 if ( priv
->head_note_state
< pm_vars
->myCurrentState
)
3859 // yes, in case we have to wait for acks
3860 priv
->machine_state
= kIOPM_OurChangeTellClientsPowerDown
;
3861 pm_vars
->doNotPowerDown
= false;
3863 // ask apps and kernel clients if we can drop power
3864 pm_vars
->outofbandparameter
= kNotifyApps
;
3865 if ( askChangeDown(priv
->head_note_state
) )
3867 // don't have to wait, did any clients veto?
3868 if ( pm_vars
->doNotPowerDown
)
3870 // yes, rescind the warning
3871 tellNoChangeDown(priv
->head_note_state
);
3872 // mark the change note un-actioned
3873 priv
-> head_note_flags
|= IOPMNotDone
;
3877 // no, tell'em we're dropping power
3878 OurChangeTellClientsPowerDown();
3882 // we are raising power
3883 if ( ! priv
->we_are_root
)
3885 // if this changes our power requirement, tell the parent
3886 ask_parent(priv
->head_note_state
);
3888 // in case they don't all ack
3889 priv
->machine_state
= kIOPM_OurChangeSetPowerState
;
3891 // notify interested drivers and children
3892 if ( notifyAll(true) == IOPMAckImplied
)
3894 OurChangeSetPowerState();
3900 //*********************************************************************************
3903 // Call the power domain parent to ask for a higher power state in the domain
3904 // or to suggest a lower power state.
3905 //*********************************************************************************
3907 IOReturn
IOService::ask_parent ( unsigned long requestedState
)
3911 IOPowerConnection
*connection
;
3913 unsigned long ourRequest
= pm_vars
->thePowerStates
[requestedState
].inputPowerRequirement
;
3915 if ( pm_vars
->thePowerStates
[requestedState
].capabilityFlags
& (kIOPMChildClamp
| kIOPMPreventIdleSleep
) )
3917 ourRequest
|= kIOPMPreventIdleSleep
;
3919 if ( pm_vars
->thePowerStates
[requestedState
].capabilityFlags
& (kIOPMChildClamp2
| kIOPMPreventSystemSleep
) )
3921 ourRequest
|= kIOPMPreventSystemSleep
;
3924 // is this a new desire?
3925 if ( priv
->previousRequest
== ourRequest
)
3927 // no, the parent knows already, just return
3931 if ( priv
->we_are_root
)
3935 priv
->previousRequest
= ourRequest
;
3937 iter
= getParentIterator(gIOPowerPlane
);
3941 while ( (next
= iter
->getNextObject()) )
3943 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
3945 parent
= (IOService
*)connection
->copyParentEntry(gIOPowerPlane
);
3947 if ( parent
->requestPowerDomainState(ourRequest
,connection
,IOPMLowestState
)!= IOPMNoErr
)
3949 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRequestDenied
,
3950 (unsigned long)priv
->previousRequest
,0);
3963 //*********************************************************************************
3966 // Call the controlling driver and have it change the power state of the
3967 // hardware. If it returns IOPMAckImplied, the change is complete, and
3968 // we return IOPMAckImplied. Otherwise, it will ack when the change
3969 // is done; we return IOPMWillAckLater.
3970 //*********************************************************************************
3971 IOReturn
IOService::instruct_driver ( unsigned long newState
)
3975 // can our driver switch to the desired state?
3976 if ( pm_vars
->thePowerStates
[newState
].capabilityFlags
& IOPMNotAttainable
)
3979 return IOPMAckImplied
;
3982 priv
->driver_timer
= -1;
3985 IOLockUnlock(priv
->our_lock
);
3986 OUR_PMLog( kPMLogProgramHardware
, (UInt32
) this, newState
);
3987 delay
= pm_vars
->theControllingDriver
->setPowerState( newState
,this );
3988 OUR_PMLog((UInt32
) -kPMLogProgramHardware
, (UInt32
) this, (UInt32
) delay
);
3989 IOLockLock(priv
->our_lock
);
3992 if ( delay
== IOPMAckImplied
)
3994 priv
->driver_timer
= 0;
3995 return IOPMAckImplied
;
3998 // it acked behind our back
3999 if ( priv
->driver_timer
== 0 )
4001 return IOPMAckImplied
;
4007 return IOPMAckImplied
;
4011 priv
->driver_timer
= (delay
/ ( ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
4012 return IOPMWillAckLater
;
4016 //*********************************************************************************
4019 // We are acquiring the lock we use to protect our queue head from
4020 // simutaneous access by a thread which calls acknowledgePowerStateChange
4021 // or acknowledgeSetPowerState and the ack timer expiration thread.
4022 // Return TRUE if we acquire the lock, and the queue head didn't change
4023 // while we were acquiring the lock (and maybe blocked).
4024 // If there is no queue head, or it changes while we are blocked,
4025 // return FALSE with the lock unlocked.
4026 //*********************************************************************************
4028 bool IOService::acquire_lock ( void )
4030 long current_change_note
;
4032 current_change_note
= priv
->head_note
;
4033 if ( current_change_note
== -1 ) {
4037 IOTakeLock(priv
->our_lock
);
4038 if ( current_change_note
== priv
->head_note
)
4042 // we blocked and something changed radically
4043 // so there's nothing to do any more
4044 IOUnlock(priv
->our_lock
);
4050 //*********************************************************************************
4053 // Ask registered applications and kernel clients if we can change to a lower
4056 // Subclass can override this to send a different message type. Parameter is
4057 // the destination state number.
4059 // Return true if we don't have to wait for acknowledgements
4060 //*********************************************************************************
4062 bool IOService::askChangeDown ( unsigned long stateNum
)
4064 return tellClientsWithResponse(kIOMessageCanDevicePowerOff
);
4068 //*********************************************************************************
4071 // Notify registered applications and kernel clients that we are definitely
4074 // Return true if we don't have to wait for acknowledgements
4075 //*********************************************************************************
4077 bool IOService::tellChangeDown1 ( unsigned long stateNum
)
4079 pm_vars
->outofbandparameter
= kNotifyApps
;
4080 return tellChangeDown(stateNum
);
4084 //*********************************************************************************
4087 // Notify priority clients that we are definitely dropping power.
4089 // Return true if we don't have to wait for acknowledgements
4090 //*********************************************************************************
4092 bool IOService::tellChangeDown2 ( unsigned long stateNum
)
4094 pm_vars
->outofbandparameter
= kNotifyPriority
;
4095 return tellChangeDown(stateNum
);
4099 //*********************************************************************************
4102 // Notify registered applications and kernel clients that we are definitely
4105 // Subclass can override this to send a different message type. Parameter is
4106 // the destination state number.
4108 // Return true if we don't have to wait for acknowledgements
4109 //*********************************************************************************
4111 bool IOService::tellChangeDown ( unsigned long stateNum
)
4113 return tellClientsWithResponse(kIOMessageDeviceWillPowerOff
);
4117 //*********************************************************************************
4118 // tellClientsWithResponse
4120 // Notify registered applications and kernel clients that we are definitely
4123 // Return true if we don't have to wait for acknowledgements
4124 //*********************************************************************************
4126 bool IOService::tellClientsWithResponse ( int messageType
)
4128 struct context theContext
;
4129 AbsoluteTime deadline
;
4132 pm_vars
->responseFlags
= OSArray::withCapacity( 1 );
4133 pm_vars
->serialNumber
+= 1;
4135 theContext
.responseFlags
= pm_vars
->responseFlags
;
4136 theContext
.serialNumber
= pm_vars
->serialNumber
;
4137 theContext
.flags_lock
= priv
->flags_lock
;
4138 theContext
.counter
= 1;
4139 theContext
.msgType
= messageType
;
4140 theContext
.us
= this;
4141 theContext
.maxTimeRequested
= 0;
4142 theContext
.stateNumber
= priv
->head_note_state
;
4143 theContext
.stateFlags
= priv
->head_note_capabilityFlags
;
4145 IOLockLock(priv
->flags_lock
);
4147 // position zero is false to
4148 // prevent allowCancelCommon from succeeding
4149 aBool
= OSBoolean::withBoolean(false);
4150 theContext
.responseFlags
->setObject(0,aBool
);
4152 IOLockUnlock(priv
->flags_lock
);
4154 switch ( pm_vars
->outofbandparameter
) {
4156 applyToInterested(gIOAppPowerStateInterest
,tellAppWithResponse
,(void *)&theContext
);
4157 applyToInterested(gIOGeneralInterest
,tellClientWithResponse
,(void *)&theContext
);
4159 case kNotifyPriority
:
4160 applyToInterested(gIOPriorityPowerStateInterest
,tellClientWithResponse
,(void *)&theContext
);
4164 if (! acquire_lock() )
4168 IOLockLock(priv
->flags_lock
);
4169 // now fix position zero
4170 aBool
= OSBoolean::withBoolean(true);
4171 theContext
.responseFlags
->replaceObject(0,aBool
);
4173 IOLockUnlock(priv
->flags_lock
);
4175 // do we have to wait for somebody?
4176 if ( ! checkForDone() )
4178 // yes, start the ackTimer
4179 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,theContext
.maxTimeRequested
,0);
4180 clock_interval_to_deadline(theContext
.maxTimeRequested
/ 1000, kMillisecondScale
, &deadline
);
4182 thread_call_enter_delayed(priv
->ackTimer
, deadline
);
4184 IOUnlock(priv
->our_lock
);
4188 IOUnlock(priv
->our_lock
);
4189 IOLockLock(priv
->flags_lock
);
4191 // everybody responded
4192 pm_vars
->responseFlags
->release();
4193 pm_vars
->responseFlags
= NULL
;
4194 IOLockUnlock(priv
->flags_lock
);
4200 //*********************************************************************************
4201 // tellAppWithResponse
4203 // We send a message to an application, and we expect a response, so we compute a
4204 // cookie we can identify the response with.
4205 //*********************************************************************************
4206 void tellAppWithResponse ( OSObject
* object
, void * context
)
4208 struct context
*theContext
= (struct context
*)context
;
4210 IOPMprot
*pm_vars
= theContext
->us
->pm_vars
;
4212 if( OSDynamicCast( IOService
, object
) )
4214 // Automatically 'ack' in kernel clients
4215 IOLockLock(theContext
->flags_lock
);
4216 aBool
= OSBoolean::withBoolean(true);
4217 theContext
->responseFlags
->setObject(theContext
->counter
,aBool
);
4219 IOLockUnlock(theContext
->flags_lock
);
4221 const char *who
= ((IOService
*) object
)->getName();
4222 pm_vars
->thePlatform
->PMLog(who
,
4223 kPMLogClientAcknowledge
, theContext
->msgType
, * (UInt32
*) object
);
4225 UInt32 refcon
= ((theContext
->serialNumber
& 0xFFFF)<<16)
4226 + (theContext
->counter
& 0xFFFF);
4227 IOLockLock(theContext
->flags_lock
);
4228 aBool
= OSBoolean::withBoolean(false);
4229 theContext
->responseFlags
->setObject(theContext
->counter
,aBool
);
4231 IOLockUnlock(theContext
->flags_lock
);
4233 OUR_PMLog(kPMLogAppNotify
, theContext
->msgType
, refcon
);
4234 theContext
->us
->messageClient(theContext
->msgType
,object
,(void *)refcon
);
4235 if ( theContext
->maxTimeRequested
< k30seconds
)
4237 theContext
->maxTimeRequested
= k30seconds
;
4240 theContext
->counter
+= 1;
4243 //*********************************************************************************
4244 // tellClientWithResponse
4246 // We send a message to an in-kernel client, and we expect a response, so we compute a
4247 // cookie we can identify the response with.
4248 // If it doesn't understand the notification (it is not power-management savvy)
4249 // we won't wait for it to prepare for sleep. If it tells us via a return code
4250 // in the passed struct that it is currently ready, we won't wait for it to prepare.
4251 // If it tells us via the return code in the struct that it does need time, we will chill.
4252 //*********************************************************************************
4253 void tellClientWithResponse ( OSObject
* object
, void * context
)
4255 struct context
*theContext
= (struct context
*)context
;
4256 IOPowerStateChangeNotification notify
;
4262 refcon
= ((theContext
->serialNumber
& 0xFFFF)<<16) + (theContext
->counter
& 0xFFFF);
4263 IOLockLock(theContext
->flags_lock
);
4264 aBool
= OSBoolean::withBoolean(false);
4265 theContext
->responseFlags
->setObject(theContext
->counter
,aBool
);
4267 IOLockUnlock(theContext
->flags_lock
);
4269 IOPMprot
*pm_vars
= theContext
->us
->pm_vars
;
4270 if (gIOKitDebug
& kIOLogPower
) {
4271 OUR_PMLog(kPMLogClientNotify
, refcon
, (UInt32
) theContext
->msgType
);
4272 if (OSDynamicCast(IOService
, object
)) {
4273 const char *who
= ((IOService
*) object
)->getName();
4274 pm_vars
->thePlatform
->PMLog(who
,
4275 kPMLogClientNotify
, * (UInt32
*) object
, (UInt32
) object
);
4276 } else if (OSDynamicCast(_IOServiceInterestNotifier
, object
)) {
4277 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
4278 OUR_PMLog(kPMLogClientNotify
, (UInt32
) n
->handler
, 0);
4282 notify
.powerRef
= (void *)refcon
;
4283 notify
.returnValue
= 0;
4284 notify
.stateNumber
= theContext
->stateNumber
;
4285 notify
.stateFlags
= theContext
->stateFlags
;
4286 retCode
= theContext
->us
->messageClient(theContext
->msgType
,object
,(void *)¬ify
);
4287 if ( retCode
== kIOReturnSuccess
)
4289 if ( notify
.returnValue
== 0 )
4291 // client doesn't want time to respond
4292 IOLockLock(theContext
->flags_lock
);
4293 aBool
= OSBoolean::withBoolean(true);
4294 // so set its flag true
4295 theContext
->responseFlags
->replaceObject(theContext
->counter
,aBool
);
4297 IOLockUnlock(theContext
->flags_lock
);
4298 OUR_PMLog(kPMLogClientAcknowledge
, refcon
, (UInt32
) object
);
4300 IOLockLock(theContext
->flags_lock
);
4302 // it does want time, and it hasn't responded yet
4303 theFlag
= theContext
->responseFlags
->getObject(theContext
->counter
);
4306 if ( ((OSBoolean
*)theFlag
)->isFalse() )
4308 // so note its time requirement
4309 if ( theContext
->maxTimeRequested
< notify
.returnValue
)
4311 theContext
->maxTimeRequested
= notify
.returnValue
;
4315 IOLockUnlock(theContext
->flags_lock
);
4318 OUR_PMLog(kPMLogClientAcknowledge
, refcon
, 0);
4319 // not a client of ours
4320 IOLockLock(theContext
->flags_lock
);
4321 // so we won't be waiting for response
4322 aBool
= OSBoolean::withBoolean(true);
4323 theContext
->responseFlags
->replaceObject(theContext
->counter
,aBool
);
4325 IOLockUnlock(theContext
->flags_lock
);
4327 theContext
->counter
+= 1;
4331 //*********************************************************************************
4334 // Notify registered applications and kernel clients that we are not
4337 // Subclass can override this to send a different message type. Parameter is
4338 // the aborted destination state number.
4339 //*********************************************************************************
4341 void IOService::tellNoChangeDown ( unsigned long )
4343 return tellClients(kIOMessageDeviceWillNotPowerOff
);
4347 //*********************************************************************************
4350 // Notify registered applications and kernel clients that we are raising power.
4352 // Subclass can override this to send a different message type. Parameter is
4353 // the aborted destination state number.
4354 //*********************************************************************************
4356 void IOService::tellChangeUp ( unsigned long )
4358 return tellClients(kIOMessageDeviceHasPoweredOn
);
4362 //*********************************************************************************
4365 // Notify registered applications and kernel clients of something.
4366 //*********************************************************************************
4368 void IOService::tellClients ( int messageType
)
4370 struct context theContext
;
4372 theContext
.msgType
= messageType
;
4373 theContext
.us
= this;
4374 theContext
.stateNumber
= priv
->head_note_state
;
4375 theContext
.stateFlags
= priv
->head_note_capabilityFlags
;
4377 applyToInterested(gIOAppPowerStateInterest
,tellClient
,(void *)&theContext
);
4378 applyToInterested(gIOGeneralInterest
,tellClient
,(void *)&theContext
);
4382 //*********************************************************************************
4385 // Notify a registered application or kernel client of something.
4386 //*********************************************************************************
4387 void tellClient ( OSObject
* object
, void * context
)
4389 struct context
*theContext
= (struct context
*)context
;
4390 IOPowerStateChangeNotification notify
;
4392 notify
.powerRef
= (void *) 0;
4393 notify
.returnValue
= 0;
4394 notify
.stateNumber
= theContext
->stateNumber
;
4395 notify
.stateFlags
= theContext
->stateFlags
;
4397 theContext
->us
->messageClient(theContext
->msgType
,object
, ¬ify
);
4401 // **********************************************************************************
4404 // **********************************************************************************
4405 bool IOService::checkForDone ( void )
4410 IOLockLock(priv
->flags_lock
);
4411 if ( pm_vars
->responseFlags
== NULL
)
4413 IOLockUnlock(priv
->flags_lock
);
4417 for ( i
= 0; ; i
++ )
4419 theFlag
= pm_vars
->responseFlags
->getObject(i
);
4420 if ( theFlag
== NULL
)
4424 if ( ((OSBoolean
*)theFlag
)->isFalse() )
4426 IOLockUnlock(priv
->flags_lock
);
4430 IOLockUnlock(priv
->flags_lock
);
4435 // **********************************************************************************
4438 // **********************************************************************************
4439 bool IOService::responseValid ( unsigned long x
)
4441 UInt16 serialComponent
;
4442 UInt16 ordinalComponent
;
4444 unsigned long refcon
= (unsigned long)x
;
4447 serialComponent
= (refcon
>>16) & 0xFFFF;
4448 ordinalComponent
= refcon
& 0xFFFF;
4450 if ( serialComponent
!= pm_vars
->serialNumber
)
4455 IOLockLock(priv
->flags_lock
);
4456 if ( pm_vars
->responseFlags
== NULL
)
4458 IOLockUnlock(priv
->flags_lock
);
4462 theFlag
= pm_vars
->responseFlags
->getObject(ordinalComponent
);
4466 IOLockUnlock(priv
->flags_lock
);
4470 if ( ((OSBoolean
*)theFlag
)->isFalse() )
4472 aBool
= OSBoolean::withBoolean(true);
4473 pm_vars
->responseFlags
->replaceObject(ordinalComponent
,aBool
);
4477 IOLockUnlock(priv
->flags_lock
);
4482 // **********************************************************************************
4485 // Our power state is about to lower, and we have notified applications
4486 // and kernel clients, and one of them has acknowledged. If this is the last to do
4487 // so, and all acknowledgements are positive, we continue with the power change.
4489 // We serialize this processing with timer expiration with a command gate on the
4490 // power management workloop, which the timer expiration is command gated to as well.
4491 // **********************************************************************************
4492 IOReturn
IOService::allowPowerChange ( unsigned long refcon
)
4494 if ( ! initialized
)
4497 return kIOReturnSuccess
;
4500 return pm_vars
->PMcommandGate
->runAction(serializedAllowPowerChange
,(void *)refcon
);
4504 IOReturn
serializedAllowPowerChange ( OSObject
*owner
, void * refcon
, void *, void *, void *)
4506 return ((IOService
*)owner
)->serializedAllowPowerChange2((unsigned long)refcon
);
4509 IOReturn
IOService::serializedAllowPowerChange2 ( unsigned long refcon
)
4512 if ( ! responseValid(refcon
) )
4514 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr5
,refcon
,0);
4516 return kIOReturnSuccess
;
4518 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientAcknowledge
,refcon
,0);
4520 return allowCancelCommon();
4524 // **********************************************************************************
4525 // cancelPowerChange
4527 // Our power state is about to lower, and we have notified applications
4528 // and kernel clients, and one of them has vetoed the change. If this is the last
4529 // client to respond, we abandon the power change.
4531 // We serialize this processing with timer expiration with a command gate on the
4532 // power management workloop, which the timer expiration is command gated to as well.
4533 // **********************************************************************************
4534 IOReturn
IOService::cancelPowerChange ( unsigned long refcon
)
4536 if ( ! initialized
)
4539 return kIOReturnSuccess
;
4542 return pm_vars
->PMcommandGate
->runAction(serializedCancelPowerChange
,(void *)refcon
);
4546 IOReturn
serializedCancelPowerChange ( OSObject
*owner
, void * refcon
, void *, void *, void *)
4548 return ((IOService
*)owner
)->serializedCancelPowerChange2((unsigned long)refcon
);
4551 IOReturn
IOService::serializedCancelPowerChange2 ( unsigned long refcon
)
4554 if ( ! responseValid(refcon
) )
4556 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr5
,refcon
,0);
4558 return kIOReturnSuccess
;
4560 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientCancel
,refcon
,0);
4562 pm_vars
->doNotPowerDown
= true;
4564 return allowCancelCommon();
4568 // **********************************************************************************
4569 // allowCancelCommon
4571 // **********************************************************************************
4572 IOReturn
IOService::allowCancelCommon ( void )
4574 if (! acquire_lock() )
4576 return kIOReturnSuccess
;
4579 // is this the last response?
4580 if ( checkForDone() )
4582 // yes, stop the timer
4584 IOUnlock(priv
->our_lock
);
4585 IOLockLock(priv
->flags_lock
);
4586 if ( pm_vars
->responseFlags
)
4588 pm_vars
->responseFlags
->release();
4589 pm_vars
->responseFlags
= NULL
;
4591 IOLockUnlock(priv
->flags_lock
);
4592 switch (priv
->machine_state
) {
4593 case kIOPM_OurChangeTellClientsPowerDown
:
4594 // our change, was it vetoed?
4595 if ( ! pm_vars
->doNotPowerDown
)
4597 // no, we can continue
4598 OurChangeTellClientsPowerDown();
4600 // yes, rescind the warning
4601 tellNoChangeDown(priv
->head_note_state
);
4602 // mark the change note un-actioned
4603 priv
->head_note_flags
|= IOPMNotDone
;
4609 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
4610 OurChangeTellPriorityClientsPowerDown();
4612 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
4613 // our change, continue
4614 OurChangeNotifyInterestedDriversWillChange();
4616 case kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate
:
4617 // parent change, continue
4618 ParentDownTellPriorityClientsPowerDown_Delayed();
4620 case kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
:
4621 // parent change, continue
4622 ParentDownNotifyInterestedDriversWillChange_Delayed();
4627 IOUnlock(priv
->our_lock
);
4630 return kIOReturnSuccess
;
4635 //*********************************************************************************
4636 // c_PM_clamp_Timer_Expired (C Func)
4638 // Called when our clamp timer expires...we will call the object method.
4639 //*********************************************************************************
4641 static void c_PM_Clamp_Timer_Expired (OSObject
* client
, IOTimerEventSource
*)
4644 ((IOService
*)client
)->PM_Clamp_Timer_Expired ();
4649 //*********************************************************************************
4650 // PM_Clamp_Timer_Expired
4652 // called when clamp timer expires...set power state to 0.
4653 //*********************************************************************************
4655 void IOService::PM_Clamp_Timer_Expired (void)
4658 if ( ! initialized
)
4664 changePowerStateToPriv (0);
4668 //******************************************************************************
4671 // Set to highest available power state for a minimum of duration milliseconds
4672 //******************************************************************************
4674 #define kFiveMinutesInNanoSeconds (300 * NSEC_PER_SEC)
4676 void IOService::clampPowerOn (unsigned long duration
)
4679 changePowerStateToPriv (pm_vars
->theNumberOfPowerStates
-1);
4681 if ( priv
->clampTimerEventSrc
== NULL
) {
4682 priv
->clampTimerEventSrc
= IOTimerEventSource::timerEventSource(this,
4683 c_PM_Clamp_Timer_Expired
);
4685 IOWorkLoop
* workLoop
= getPMworkloop ();
4687 if ( !priv
->clampTimerEventSrc
|| !workLoop
||
4688 ( workLoop
->addEventSource( priv
->clampTimerEventSrc
) != kIOReturnSuccess
) ) {
4693 priv
->clampTimerEventSrc
->setTimeout(300*USEC_PER_SEC
, USEC_PER_SEC
);
4697 //*********************************************************************************
4700 // Does nothing here. This should be implemented in a subclass driver.
4701 //*********************************************************************************
4703 IOReturn
IOService::setPowerState ( unsigned long powerStateOrdinal
, IOService
* whatDevice
)
4709 //*********************************************************************************
4710 // maxCapabilityForDomainState
4712 // Finds the highest power state in the array whose input power
4713 // requirement is equal to the input parameter. Where a more intelligent
4714 // decision is possible, override this in the subclassed driver.
4715 //*********************************************************************************
4717 unsigned long IOService::maxCapabilityForDomainState ( IOPMPowerFlags domainState
)
4721 if (pm_vars
->theNumberOfPowerStates
== 0 )
4725 for ( i
= (pm_vars
->theNumberOfPowerStates
)-1; i
>= 0; i
-- )
4727 if ( (domainState
& pm_vars
->thePowerStates
[i
].inputPowerRequirement
) == pm_vars
->thePowerStates
[i
].inputPowerRequirement
)
4736 //*********************************************************************************
4737 // initialPowerStateForDomainState
4739 // Finds the highest power state in the array whose input power
4740 // requirement is equal to the input parameter. Where a more intelligent
4741 // decision is possible, override this in the subclassed driver.
4742 //*********************************************************************************
4744 unsigned long IOService::initialPowerStateForDomainState ( IOPMPowerFlags domainState
)
4748 if (pm_vars
->theNumberOfPowerStates
== 0 )
4752 for ( i
= (pm_vars
->theNumberOfPowerStates
)-1; i
>= 0; i
-- )
4754 if ( (domainState
& pm_vars
->thePowerStates
[i
].inputPowerRequirement
) == pm_vars
->thePowerStates
[i
].inputPowerRequirement
)
4763 //*********************************************************************************
4764 // powerStateForDomainState
4766 // Finds the highest power state in the array whose input power
4767 // requirement is equal to the input parameter. Where a more intelligent
4768 // decision is possible, override this in the subclassed driver.
4769 //*********************************************************************************
4771 unsigned long IOService::powerStateForDomainState ( IOPMPowerFlags domainState
)
4775 if (pm_vars
->theNumberOfPowerStates
== 0 )
4779 for ( i
= (pm_vars
->theNumberOfPowerStates
)-1; i
>= 0; i
-- )
4781 if ( (domainState
& pm_vars
->thePowerStates
[i
].inputPowerRequirement
) == pm_vars
->thePowerStates
[i
].inputPowerRequirement
)
4790 //*********************************************************************************
4793 // Does nothing here. This should be implemented in a subclass driver.
4794 //*********************************************************************************
4796 bool IOService::didYouWakeSystem ( void )
4802 //*********************************************************************************
4803 // powerStateWillChangeTo
4805 // Does nothing here. This should be implemented in a subclass driver.
4806 //*********************************************************************************
4808 IOReturn
IOService::powerStateWillChangeTo ( IOPMPowerFlags
, unsigned long, IOService
*)
4814 //*********************************************************************************
4815 // powerStateDidChangeTo
4817 // Does nothing here. This should be implemented in a subclass driver.
4818 //*********************************************************************************
4820 IOReturn
IOService::powerStateDidChangeTo ( IOPMPowerFlags
, unsigned long, IOService
*)
4826 //*********************************************************************************
4829 // Does nothing here. This should be implemented in a subclass policy-maker.
4830 //*********************************************************************************
4832 void IOService::powerChangeDone ( unsigned long )
4837 //*********************************************************************************
4840 // Does nothing here. This should be implemented in a subclass driver.
4841 //*********************************************************************************
4843 IOReturn
IOService::newTemperature ( long currentTemp
, IOService
* whichZone
)
4851 #define super OSObject
4853 OSDefineMetaClassAndStructors(IOPMprot
, OSObject
)
4854 //*********************************************************************************
4857 // Serialize protected instance variables for debug output.
4858 //*********************************************************************************
4859 bool IOPMprot::serialize(OSSerialize
*s
) const
4861 OSString
* theOSString
;
4868 // estimate how many bytes we need to present all power states
4869 buf_size
= 150 // beginning and end of string
4870 + (275 * (int)theNumberOfPowerStates
) // size per state
4871 + 100; // extra room just for kicks
4873 buffer
= ptr
= IONew(char, buf_size
);
4877 ptr
+= sprintf(ptr
,"{ theNumberOfPowerStates = %d, ",(unsigned int)theNumberOfPowerStates
);
4879 if ( theNumberOfPowerStates
!= 0 ) {
4880 ptr
+= sprintf(ptr
,"version %d, ",(unsigned int)thePowerStates
[0].version
);
4883 if ( theNumberOfPowerStates
!= 0 ) {
4884 for ( i
= 0; i
< (int)theNumberOfPowerStates
; i
++ ) {
4885 ptr
+= sprintf(ptr
, "power state %d = { ",i
);
4886 ptr
+= sprintf(ptr
,"capabilityFlags %08x, ",(unsigned int)thePowerStates
[i
].capabilityFlags
);
4887 ptr
+= sprintf(ptr
,"outputPowerCharacter %08x, ",(unsigned int)thePowerStates
[i
].outputPowerCharacter
);
4888 ptr
+= sprintf(ptr
,"inputPowerRequirement %08x, ",(unsigned int)thePowerStates
[i
].inputPowerRequirement
);
4889 ptr
+= sprintf(ptr
,"staticPower %d, ",(unsigned int)thePowerStates
[i
].staticPower
);
4890 ptr
+= sprintf(ptr
,"unbudgetedPower %d, ",(unsigned int)thePowerStates
[i
].unbudgetedPower
);
4891 ptr
+= sprintf(ptr
,"powerToAttain %d, ",(unsigned int)thePowerStates
[i
].powerToAttain
);
4892 ptr
+= sprintf(ptr
,"timeToAttain %d, ",(unsigned int)thePowerStates
[i
].timeToAttain
);
4893 ptr
+= sprintf(ptr
,"settleUpTime %d, ",(unsigned int)thePowerStates
[i
].settleUpTime
);
4894 ptr
+= sprintf(ptr
,"timeToLower %d, ",(unsigned int)thePowerStates
[i
].timeToLower
);
4895 ptr
+= sprintf(ptr
,"settleDownTime %d, ",(unsigned int)thePowerStates
[i
].settleDownTime
);
4896 ptr
+= sprintf(ptr
,"powerDomainBudget %d }, ",(unsigned int)thePowerStates
[i
].powerDomainBudget
);
4900 ptr
+= sprintf(ptr
,"aggressiveness = %d, ",(unsigned int)aggressiveness
);
4901 ptr
+= sprintf(ptr
,"myCurrentState = %d, ",(unsigned int)myCurrentState
);
4902 ptr
+= sprintf(ptr
,"parentsCurrentPowerFlags = %08x, ",(unsigned int)parentsCurrentPowerFlags
);
4903 ptr
+= sprintf(ptr
,"maxCapability = %d }",(unsigned int)maxCapability
);
4905 theOSString
= OSString::withCString(buffer
);
4906 rtn_code
= theOSString
->serialize(s
);
4907 theOSString
->release();
4908 IODelete(buffer
, char, buf_size
);
4915 #define super OSObject
4917 OSDefineMetaClassAndStructors(IOPMpriv
, OSObject
)
4918 //*********************************************************************************
4921 // Serialize private instance variables for debug output.
4922 //*********************************************************************************
4923 bool IOPMpriv::serialize(OSSerialize
*s
) const
4925 OSString
* theOSString
;
4929 IOPMinformee
* nextObject
;
4931 buffer
= ptr
= IONew(char, 2000);
4935 ptr
+= sprintf(ptr
,"{ this object = %08x",(unsigned int)owner
);
4936 if ( we_are_root
) {
4937 ptr
+= sprintf(ptr
," (root)");
4939 ptr
+= sprintf(ptr
,", ");
4941 nextObject
= interestedDrivers
->firstInList(); // display interested drivers
4942 while ( nextObject
!= NULL
) {
4943 ptr
+= sprintf(ptr
,"interested driver = %08x, ",(unsigned int)nextObject
->whatObject
);
4944 nextObject
= interestedDrivers
->nextInList(nextObject
);
4947 if ( machine_state
!= kIOPM_Finished
) {
4948 ptr
+= sprintf(ptr
,"machine_state = %d, ",(unsigned int)machine_state
);
4949 ptr
+= sprintf(ptr
,"driver_timer = %d, ",(unsigned int)driver_timer
);
4950 ptr
+= sprintf(ptr
,"settle_time = %d, ",(unsigned int)settle_time
);
4951 ptr
+= sprintf(ptr
,"head_note_flags = %08x, ",(unsigned int)head_note_flags
);
4952 ptr
+= sprintf(ptr
,"head_note_state = %d, ",(unsigned int)head_note_state
);
4953 ptr
+= sprintf(ptr
,"head_note_outputFlags = %08x, ",(unsigned int)head_note_outputFlags
);
4954 ptr
+= sprintf(ptr
,"head_note_domainState = %08x, ",(unsigned int)head_note_domainState
);
4955 ptr
+= sprintf(ptr
,"head_note_capabilityFlags = %08x, ",(unsigned int)head_note_capabilityFlags
);
4956 ptr
+= sprintf(ptr
,"head_note_pendingAcks = %d, ",(unsigned int)head_note_pendingAcks
);
4959 if ( device_overrides
) {
4960 ptr
+= sprintf(ptr
,"device overrides, ");
4962 ptr
+= sprintf(ptr
,"driverDesire = %d, ",(unsigned int)driverDesire
);
4963 ptr
+= sprintf(ptr
,"deviceDesire = %d, ",(unsigned int)deviceDesire
);
4964 ptr
+= sprintf(ptr
,"ourDesiredPowerState = %d, ",(unsigned int)ourDesiredPowerState
);
4965 ptr
+= sprintf(ptr
,"previousRequest = %d }",(unsigned int)previousRequest
);
4967 theOSString
= OSString::withCString(buffer
);
4968 rtn_code
= theOSString
->serialize(s
);
4969 theOSString
->release();
4970 IODelete(buffer
, char, 2000);