2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 #include <IOKit/assert.h>
25 #include <IOKit/IOCommandGate.h>
26 #include <IOKit/IOKitDebug.h>
27 #include <IOKit/IOLib.h>
28 #include <IOKit/IOMessage.h>
29 #include <IOKit/IOPlatformExpert.h>
30 #include <IOKit/IOService.h>
31 #include <IOKit/IOTimerEventSource.h>
32 #include <IOKit/IOWorkLoop.h>
34 #include <IOKit/pwr_mgt/IOPMchangeNoteList.h>
35 #include <IOKit/pwr_mgt/IOPMinformee.h>
36 #include <IOKit/pwr_mgt/IOPMinformeeList.h>
37 #include <IOKit/pwr_mgt/IOPMlog.h>
38 #include <IOKit/pwr_mgt/IOPowerConnection.h>
39 #include <IOKit/pwr_mgt/RootDomain.h>
41 // Required for notification instrumentation
42 #include "IOServicePrivate.h"
44 #define super IORegistryEntry
46 #define OUR_PMLog(t, a, b) \
47 do { pm_vars->thePlatform->PMLog(pm_vars->ourName, t, a, b); } while(0)
49 static void ack_timer_expired(thread_call_param_t
);
50 static void settle_timer_expired(thread_call_param_t
);
51 static void PM_idle_timer_expired(OSObject
*, IOTimerEventSource
*);
52 void tellAppWithResponse ( OSObject
* object
, void * context
);
53 void tellClientWithResponse ( OSObject
* object
, void * context
);
54 void tellClient ( OSObject
* object
, void * context
);
55 IOReturn
serializedAllowPowerChange ( OSObject
*, void *, void *, void *, void *);
56 IOReturn
serializedCancelPowerChange ( OSObject
*, void *, void *, void *, void *);
58 extern const IORegistryPlane
* gIOPowerPlane
;
61 // and there's 1000 nanoseconds in a microsecond:
62 #define ns_per_us 1000
65 // The current change note is processed by a state machine.
66 // Inputs are acks from interested parties, ack from the controlling driver,
67 // ack timeouts, settle timeout, and powerStateDidChange from the parent.
68 // These are the states:
70 kIOPM_OurChangeTellClientsPowerDown
= 1,
71 kIOPM_OurChangeTellPriorityClientsPowerDown
,
72 kIOPM_OurChangeNotifyInterestedDriversWillChange
,
73 kIOPM_OurChangeSetPowerState
,
74 kIOPM_OurChangeWaitForPowerSettle
,
75 kIOPM_OurChangeNotifyInterestedDriversDidChange
,
76 kIOPM_OurChangeFinish
,
77 kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate
,
78 kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
,
79 kIOPM_ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate
,
80 kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
,
81 kIOPM_ParentDownSetPowerState_Delayed
,
82 kIOPM_ParentDownWaitForPowerSettle_Delayed
,
83 kIOPM_ParentDownAcknowledgeChange_Delayed
,
84 kIOPM_ParentUpSetPowerState_Delayed
,
85 kIOPM_ParentUpSetPowerState_Immediate
,
86 kIOPM_ParentUpWaitForSettleTime_Delayed
,
87 kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed
,
88 kIOPM_ParentUpAcknowledgePowerChange_Delayed
,
92 // values of outofbandparameter
99 // used for applyToInterested
101 OSArray
* responseFlags
;
104 UInt32 maxTimeRequested
;
108 unsigned long stateNumber
;
109 IOPMPowerFlags stateFlags
;
112 // five minutes in microseconds
113 #define FIVE_MINUTES 5*60*1000000
114 #define k30seconds 30*1000000
117 There are two different kinds of power state changes. One is initiated by a subclassed device object which has either
118 decided to change power state, or its controlling driver has suggested it, or some other driver wants to use the
119 idle device and has asked it to become usable. The second kind of power state change is initiated by the power
120 domain parent. The two are handled slightly differently.
122 There is a queue of so-called change notifications, or change notes for short. Usually the queue is empty, and when
123 it isn't, usually there is one change note in it, but since it's possible to have more than one power state change pending
124 at one time, a queue is implemented. Example: the subclass device decides it's idle and initiates a change to a lower
125 power state. This causes interested parties to be notified, but they don't all acknowledge right away. This causes the
126 change note to sit in the queue until all the acks are received. During this time, the device decides it isn't idle anymore and
127 wants to raise power back up again. This change can't be started, however, because the previous one isn't complete yet,
128 so the second one waits in the queue. During this time, the parent decides to lower or raise the power state of the entire
129 power domain and notifies the device, and that notification goes into the queue, too, and can't be actioned until the
132 This is how a power change initiated by the subclass device is handled:
133 First, all interested parties are notified of the change via their powerStateWillChangeTo method. If they all don't
134 acknowledge via return code, then we have to wait. If they do, or when they finally all acknowledge via our
135 acknowledgePowerChange method, then we can continue. We call the controlling driver, instructing it to change to
136 the new state. Then we wait for power to settle. If there is no settling-time, or after it has passed, we notify
137 interested parties again, this time via their powerStateDidChangeTo methods. When they have all acked, we're done.
138 If we lowered power and don't need the power domain to be in its current power state, we suggest to the parent that
139 it lower the power domain state.
141 This is how a change to a lower power domain state initiated by the parent is handled:
142 First, we figure out what power state we will be in when the new domain state is reached. Then all interested parties are
143 notified that we are moving to that new state. When they have acknowledged, we call the controlling driver to assume
144 that state and we wait for power to settle. Then we acknowledge our preparedness to our parent. When all its interested
145 parties have acknowledged, it lowers power and then notifies its interested parties again. When we get this call, we notify
146 our interested parties that the power state has changed, and when they have all acknowledged, we're done.
148 This is how a change to a higher power domain state initiated by the parent is handled:
149 We figure out what power state we will be in when the new domain state is reached. If it is different from our current
150 state we acknowledge the parent. When all the parent's interested parties have acknowledged, it raises power in the
151 domain and waits for power to settle. Then it notifies everyone that the new state has been reached. When we get this call,
152 we call the controlling driver, instructing it to assume the new state, and wait for power to settle. Then we notify our interested
153 parties. When they all acknowledge we are done.
155 In either of the two cases above, it is possible that we will not be changing state even though the domain is. Examples:
156 A change to a lower domain state may not affect us because we are already in a low enough state, and
157 We will not take advantage of a change to a higher domain state, because we have no need of the higher power.
158 In such a case, there is nothing to do but acknowledge the parent. So when the parent calls our powerDomainWillChange
159 method, and we decide that we will not be changing state, we merely acknowledge the parent, via return code, and wait.
160 When the parent subsequently calls powerStateDidChange, we acknowledge again via return code, and the change is complete.
162 Power state changes are processed in a state machine, and since there are four varieties of power state changes, there are
163 four major paths through the state machine:
165 The fourth is nearly trivial. In this path, the parent is changing the domain state, but we are not changing the device state.
166 The change starts when the parent calls powerDomainWillChange. All we do is acknowledge the parent.
167 When the parent calls powerStateDidChange, we acknowledge the parent again, and we're done.
169 The first is fairly simple. It starts when a power domain child calls requestPowerDomainState and we decide to change power states
170 to accomodate the child, or if our power-controlling driver calls changePowerStateTo, or if some other driver which is using our
171 device calls makeUsable, or if a subclassed object calls changePowerStateToPriv. These are all power changes initiated by us, not
172 forced upon us by the parent. We start by notifying interested parties. If they all acknowledge via return code, we can go
173 on to state "OurChangeSetPowerState". Otherwise, we start the ack timer and wait for the stragglers to acknowlege by calling
174 acknowledgePowerChange. We move on to state "OurChangeSetPowerState" when all the stragglers have acknowledged,
175 or when the ack timer expires on all those which didn't acknowledge. In "OurChangeSetPowerState" we call the power-controlling
176 driver to change the power state of the hardware. If it returns saying it has done so, we go on to state "OurChangeWaitForPowerSettle".
177 Otherwise, we have to wait for it, so we set the ack timer and wait. When it calls acknowledgeSetPowerState, or when the
178 ack timer expires, we go on. In "OurChangeWaitForPowerSettle", we look in the power state array to see if there is any settle time required
179 when changing from our current state to the new state. If not, we go right away to "OurChangeNotifyInterestedDriversDidChange". Otherwise, we
180 set the settle timer and wait. When it expires, we move on. In "OurChangeNotifyInterestedDriversDidChange" state, we notify all our interested parties
181 via their powerStateDidChange methods that we have finished changing power state. If they all acknowledge via return
182 code, we move on to "OurChangeFinish". Otherwise we set the ack timer and wait. When they have all acknowledged, or
183 when the ack timer has expired for those that didn't, we move on to "OurChangeFinish", where we remove the used
184 change note from the head of the queue and start the next one if one exists.
186 Parent-initiated changes are more complex in the state machine. First, power going up and power going down are handled
187 differently, so they have different paths throught the state machine. Second, we can acknowledge the parent's notification
188 in two different ways, so each of the parent paths is really two.
190 When the parent calls our powerDomainWillChange method, notifying us that it will lower power in the domain, we decide
191 what state that will put our device in. Then we embark on the state machine path "IOPMParentDownSetPowerState_Immediate"
192 and "kIOPM_ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate", in which we notify interested parties of the upcoming change, instruct our driver to make
193 the change, check for settle time, and notify interested parties of the completed change. If we get to the end of this path without
194 stalling due to an interested party which didn't acknowledge via return code, due to the controlling driver not able to change
195 state right away, or due to a non-zero settling time, then we return IOPMAckImplied to the parent, and we're done with the change.
196 If we do stall in any of those states, we return IOPMWillAckLater to the parent and enter the parallel path "kIOPM_ParentDownSetPowerState_Delayed"
197 "kIOPM_ParentDownWaitForPowerSettle_Delayed", and "kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed", where we continue with the same processing, except that at the end we
198 acknowledge the parent explicitly via acknowledgePowerChange, and we're done with the change.
199 Then when the parent calls us at powerStateDidChange we acknowledging via return code, because we have already made
200 the power change. In any case, when we are done we remove the used change note from the head of the queue and start on the next one.
202 The case of the parent raising power in the domain is handled similarly in that there are parallel paths, one for no-stall
203 that ends in implicit acknowleging the parent, and one that has stalled at least once that ends in explicit acknowledging
204 the parent. This case is different, though in that our device changes state in the second half, after the parent calls
205 powerStateDidChange rather than before, as in the power-lowering case.
207 When the parent calls our powerDomainWillChange method, notifying us that it will raise power in the domain, we acknowledge
208 via return code, because there's really nothing we can do until the power is actually raised in the domain.
209 When the parent calls us at powerStateDidChange, we start by notifying our interested parties. If they all acknowledge via return code,
210 we go on to" kIOPM_ParentUpSetPowerState_Immediate" to instruct the driver to raise its power level. After that, we check for any
211 necessary settling time in "IOPMParentUpWaitForSettleTime_Immediate", and we notify all interested parties that power has changed
212 in "IOPMParentUpNotifyInterestedDriversDidChange_Immediate". If none of these operations stall, we acknowledge the parent via return code, release
213 the change note, and start the next, if there is one. If one of them does stall, we enter the parallel path "kIOPM_ParentUpSetPowerState_Delayed",
214 "kIOPM_ParentUpWaitForSettleTime_Delayed", "kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed", and "kIOPM_ParentUpAcknowledgePowerChange_Delayed", which ends with
215 our explicit acknowledgement to the parent.
220 const char priv_key
[ ] = "Power Management private data";
221 const char prot_key
[ ] = "Power Management protected data";
224 void IOService::PMinit ( void )
226 if ( ! initialized
) {
228 // make space for our variables
229 pm_vars
= new IOPMprot
;
235 // add pm_vars & priv to the properties
236 setProperty(prot_key
, (OSObject
*) pm_vars
);
237 setProperty(priv_key
, (OSObject
*) priv
);
239 // then initialize them
241 pm_vars
->theNumberOfPowerStates
= 0;
242 priv
->we_are_root
= false;
243 pm_vars
->theControllingDriver
= NULL
;
244 priv
->our_lock
= IOLockAlloc();
245 priv
->flags_lock
= IOLockAlloc();
246 priv
->queue_lock
= IOLockAlloc();
247 pm_vars
->childLock
= IOLockAlloc();
248 pm_vars
->parentLock
= IOLockAlloc();
249 priv
->interestedDrivers
= new IOPMinformeeList
;
250 priv
->interestedDrivers
->initialize();
251 priv
->changeList
= new IOPMchangeNoteList
;
252 priv
->changeList
->initialize();
253 pm_vars
->aggressiveness
= 0;
254 for (unsigned int i
= 0; i
<= kMaxType
; i
++)
256 pm_vars
->current_aggressiveness_values
[i
] = 0;
257 pm_vars
->current_aggressiveness_valid
[i
] = false;
259 pm_vars
->myCurrentState
= 0;
260 priv
->imminentState
= 0;
261 priv
->ourDesiredPowerState
= 0;
262 pm_vars
->parentsCurrentPowerFlags
= 0;
263 pm_vars
->maxCapability
= 0;
264 priv
->driverDesire
= 0;
265 priv
->deviceDesire
= 0;
266 priv
->initial_change
= true;
267 priv
->need_to_become_usable
= false;
268 priv
->previousRequest
= 0;
269 priv
->device_overrides
= false;
270 priv
->machine_state
= kIOPM_Finished
;
271 priv
->timerEventSrc
= NULL
;
272 priv
->clampTimerEventSrc
= NULL
;
273 pm_vars
->PMworkloop
= NULL
;
274 priv
->activityLock
= NULL
;
275 pm_vars
->ourName
= getName();
276 pm_vars
->thePlatform
= getPlatform();
277 pm_vars
->parentsKnowState
= false;
278 assert( pm_vars
->thePlatform
!= 0 );
279 priv
->clampOn
= false;
280 pm_vars
->serialNumber
= 0;
281 pm_vars
->responseFlags
= NULL
;
282 pm_vars
->doNotPowerDown
= true;
283 pm_vars
->PMcommandGate
= NULL
;
284 priv
->ackTimer
= thread_call_allocate((thread_call_func_t
)ack_timer_expired
, (thread_call_param_t
)this);
285 priv
->settleTimer
= thread_call_allocate((thread_call_func_t
)settle_timer_expired
, (thread_call_param_t
)this);
291 //*********************************************************************************
294 // Free up the data created in PMinit, if it exists.
295 //*********************************************************************************
296 void IOService::PMfree ( void )
299 if ( priv
->clampTimerEventSrc
!= NULL
) {
300 getPMworkloop()->removeEventSource(priv
->clampTimerEventSrc
);
301 priv
->clampTimerEventSrc
->release();
302 priv
->clampTimerEventSrc
= NULL
;
304 if ( priv
->timerEventSrc
!= NULL
) {
305 pm_vars
->PMworkloop
->removeEventSource(priv
->timerEventSrc
);
306 priv
->timerEventSrc
->release();
307 priv
->timerEventSrc
= NULL
;
309 if ( priv
->settleTimer
) {
310 thread_call_cancel(priv
->settleTimer
);
311 thread_call_free(priv
->settleTimer
);
312 priv
->settleTimer
= NULL
;
314 if ( priv
->ackTimer
) {
315 thread_call_cancel(priv
->ackTimer
);
316 thread_call_free(priv
->ackTimer
);
317 priv
->ackTimer
= NULL
;
319 if ( priv
->our_lock
) {
320 IOLockFree(priv
->our_lock
);
321 priv
->our_lock
= NULL
;
323 if ( priv
->flags_lock
) {
324 IOLockFree(priv
->flags_lock
);
325 priv
->flags_lock
= NULL
;
327 if ( priv
->activityLock
) {
328 IOLockFree(priv
->activityLock
);
329 priv
->activityLock
= NULL
;
331 priv
->interestedDrivers
->release();
332 priv
->changeList
->release();
333 // remove instance variables
338 if ( pm_vars
->PMcommandGate
) {
339 if(pm_vars
->PMworkloop
)
340 pm_vars
->PMworkloop
->removeEventSource(pm_vars
->PMcommandGate
);
341 pm_vars
->PMcommandGate
->release();
342 pm_vars
->PMcommandGate
= NULL
;
344 if ( pm_vars
->PMworkloop
) {
345 // The work loop object returned from getPMworkLoop() is
346 // never retained, therefore it should not be released.
347 // pm_vars->PMworkloop->release();
348 pm_vars
->PMworkloop
= NULL
;
350 if ( pm_vars
->responseFlags
) {
351 pm_vars
->responseFlags
->release();
352 pm_vars
->responseFlags
= NULL
;
354 // remove instance variables
360 //*********************************************************************************
363 // Disconnect the node from its parents and children in the Power Plane.
364 //*********************************************************************************
365 void IOService::PMstop ( void )
369 IOPowerConnection
* connection
;
370 IOService
* theChild
;
371 IOService
* theParent
;
373 // remove the properties
374 removeProperty(prot_key
);
375 removeProperty(priv_key
);
378 iter
= getParentIterator(gIOPowerPlane
);
382 while ( (next
= iter
->getNextObject()) )
384 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
386 theParent
= (IOService
*)connection
->copyParentEntry(gIOPowerPlane
);
389 theParent
->removePowerChild(connection
);
390 theParent
->release();
397 // detach IOConnections
398 detachAbove( gIOPowerPlane
);
402 // no more power state changes
403 pm_vars
->parentsKnowState
= false;
407 iter
= getChildIterator(gIOPowerPlane
);
411 while ( (next
= iter
->getNextObject()) )
413 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
415 theChild
= ((IOService
*)(connection
->copyChildEntry(gIOPowerPlane
)));
418 // detach nub from child
419 connection
->detachFromChild(theChild
,gIOPowerPlane
);
422 // detach us from nub
423 detachFromChild(connection
,gIOPowerPlane
);
429 // Remove all interested drivers from the list, including the power
430 // controlling driver.
432 // Usually, the controlling driver and the policy-maker functionality
433 // are implemented by the same object, and without the deregistration,
434 // the object will be holding an extra retain on itself, and cannot
437 if ( priv
&& priv
->interestedDrivers
)
439 IOPMinformee
* informee
;
441 while (( informee
= priv
->interestedDrivers
->firstInList() ))
442 deRegisterInterestedDriver( informee
->whatObject
);
447 //*********************************************************************************
450 // A policy-maker calls its nub here when initializing, to be attached into
451 // the power management hierarchy. The default function is to call the
452 // platform expert, which knows how to do it. This method is overridden
453 // by a nub subclass which may either know how to do it, or may need
454 // to take other action.
456 // This may be the only "power management" method used in a nub,
457 // meaning it may not be initialized for power management.
458 //*********************************************************************************
459 void IOService::joinPMtree ( IOService
* driver
)
461 IOPlatformExpert
* thePlatform
;
463 thePlatform
= getPlatform();
464 assert(thePlatform
!= 0 );
465 thePlatform
->PMRegisterDevice(this,driver
);
469 //*********************************************************************************
472 // Power Managment is informing us that we are the root power domain.
473 // The only difference between us and any other power domain is that
474 // we have no parent and therefore never call it.
475 //*********************************************************************************
476 IOReturn
IOService::youAreRoot ( void )
478 priv
-> we_are_root
= true;
479 pm_vars
->parentsKnowState
= true;
480 attachToParent( getRegistryRoot(),gIOPowerPlane
);
486 //*********************************************************************************
489 // Power Management is informing us who our parent is.
490 // If we have a controlling driver, find out, given our newly-informed
491 // power domain state, what state it would be in, and then tell it
492 // to assume that state.
493 //*********************************************************************************
494 IOReturn
IOService::setPowerParent ( IOPowerConnection
* theParent
, bool stateKnown
, IOPMPowerFlags currentState
)
498 IOPowerConnection
* connection
;
499 unsigned long tempDesire
;
501 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogSetParent
,stateKnown
,currentState
);
503 IOLockLock(pm_vars
->parentLock
);
505 if ( stateKnown
&& ((pm_vars
->PMworkloop
== NULL
) || (pm_vars
->PMcommandGate
== NULL
)) )
507 // we have a path to the root
508 // find out the workloop
510 if ( pm_vars
->PMworkloop
!= NULL
)
512 if ( pm_vars
->PMcommandGate
== NULL
)
514 // and make our command gate
515 pm_vars
->PMcommandGate
= IOCommandGate::commandGate((OSObject
*)this);
516 if ( pm_vars
->PMcommandGate
!= NULL
)
518 pm_vars
->PMworkloop
->addEventSource(pm_vars
->PMcommandGate
);
524 IOLockUnlock(pm_vars
->parentLock
);
526 // set our connection data
527 theParent
->setParentCurrentPowerFlags(currentState
);
528 theParent
->setParentKnowsState(stateKnown
);
530 // combine parent knowledge
531 pm_vars
->parentsKnowState
= true;
532 pm_vars
->parentsCurrentPowerFlags
= 0;
534 iter
= getParentIterator(gIOPowerPlane
);
538 while ( (next
= iter
->getNextObject()) )
540 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
542 pm_vars
->parentsKnowState
&= connection
->parentKnowsState();
543 pm_vars
->parentsCurrentPowerFlags
|= connection
->parentCurrentPowerFlags();
549 if ( (pm_vars
->theControllingDriver
!= NULL
) &&
550 (pm_vars
->parentsKnowState
) )
552 pm_vars
->maxCapability
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(pm_vars
->parentsCurrentPowerFlags
);
553 // initially change into the state we are already in
554 tempDesire
= priv
->deviceDesire
;
555 priv
->deviceDesire
= pm_vars
->theControllingDriver
->initialPowerStateForDomainState(pm_vars
->parentsCurrentPowerFlags
);
556 computeDesiredState();
557 priv
->previousRequest
= 0xffffffff;
559 // put this back like before
560 priv
->deviceDesire
= tempDesire
;
567 //*********************************************************************************
570 // Power Management is informing us who our children are.
571 //*********************************************************************************
572 IOReturn
IOService::addPowerChild ( IOService
* theChild
)
574 IOPowerConnection
*connection
;
579 // we're not a power-managed IOService
580 return IOPMNotYetInitialized
;
583 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAddChild
,0,0);
585 // Put ourselves into a usable power state.
586 // We must be in an "on" power state, as our children must be able to access
587 // our hardware after joining the power plane.
591 connection
= new IOPowerConnection
;
594 connection
->start(this);
595 connection
->setAwaitingAck(false);
598 attachToChild( connection
,gIOPowerPlane
);
599 connection
->attachToChild( theChild
,gIOPowerPlane
);
600 connection
->release();
602 // tell it the current state of the power domain
603 if ( (pm_vars
->theControllingDriver
== NULL
) ||
604 ! (inPlane(gIOPowerPlane
)) ||
605 ! (pm_vars
->parentsKnowState
) )
607 theChild
->setPowerParent(connection
,false,0);
608 if ( inPlane(gIOPowerPlane
) )
610 for (i
= 0; i
<= kMaxType
; i
++) {
611 if ( pm_vars
->current_aggressiveness_valid
[i
] )
613 theChild
->setAggressiveness (i
, pm_vars
->current_aggressiveness_values
[i
]);
618 theChild
->setPowerParent(connection
,true,pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].outputPowerCharacter
);
619 for (i
= 0; i
<= kMaxType
; i
++)
621 if ( pm_vars
->current_aggressiveness_valid
[i
] )
623 theChild
->setAggressiveness (i
, pm_vars
->current_aggressiveness_values
[i
]);
626 // catch it up if change is in progress
627 add_child_to_active_change(connection
);
634 //*********************************************************************************
637 //*********************************************************************************
638 IOReturn
IOService::removePowerChild ( IOPowerConnection
* theNub
)
640 IORegistryEntry
*theChild
;
643 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRemoveChild
,0,0);
647 // detach nub from child
648 theChild
= theNub
->copyChildEntry(gIOPowerPlane
);
651 theNub
->detachFromChild(theChild
, gIOPowerPlane
);
654 // detach from the nub
655 detachFromChild(theNub
,gIOPowerPlane
);
657 // are we awaiting an ack from this child?
658 if ( theNub
->getAwaitingAck() )
660 // yes, pretend we got one
661 theNub
->setAwaitingAck(false);
662 if ( acquire_lock() )
664 if (priv
->head_note_pendingAcks
!= 0 )
666 // that's one fewer ack to worry about
667 priv
->head_note_pendingAcks
-= 1;
669 if ( priv
->head_note_pendingAcks
== 0 )
671 // yes, stop the timer
673 IOUnlock(priv
->our_lock
);
674 // and now we can continue our power change
677 IOUnlock(priv
->our_lock
);
680 IOUnlock(priv
->our_lock
);
687 // if not fully initialized
688 if ( (pm_vars
->theControllingDriver
== NULL
) ||
689 !(inPlane(gIOPowerPlane
)) ||
690 !(pm_vars
->parentsKnowState
) )
696 // Perhaps the departing child was holding up idle or system sleep - we need to re-evaluate our
697 // childrens' requests. Clear and re-calculate our kIOPMChildClamp and kIOPMChildClamp2 bits.
698 rebuildChildClampBits();
703 iter
= getChildIterator(gIOPowerPlane
);
704 if ( !iter
|| !iter
->getNextObject() )
706 // paired to match the makeUsable() call in addPowerChild()
707 changePowerStateToPriv(0);
709 if(iter
) iter
->release();
712 // this may be different now
713 computeDesiredState();
714 // change state if we can now tolerate lower power
721 //*********************************************************************************
722 // registerPowerDriver
724 // A driver has called us volunteering to control power to our device.
725 // If the power state array it provides is richer than the one we already
726 // know about (supplied by an earlier volunteer), then accept the offer.
727 // Notify all interested parties of our power state, which we now know.
728 //*********************************************************************************
730 IOReturn
IOService::registerPowerDriver ( IOService
* controllingDriver
, IOPMPowerState
* powerStates
, unsigned long numberOfStates
)
733 unsigned long tempDesire
;
735 if ( (numberOfStates
> pm_vars
->theNumberOfPowerStates
)
736 && (numberOfStates
> 1) )
738 if ( priv
->changeList
->currentChange() == -1 )
740 if ( controllingDriver
!= NULL
)
742 if ( numberOfStates
<= IOPMMaxPowerStates
)
744 switch ( powerStates
[0].version
)
747 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriver
,
748 (unsigned long)numberOfStates
, (unsigned long)powerStates
[0].version
);
749 for ( i
= 0; i
< numberOfStates
; i
++ )
751 pm_vars
->thePowerStates
[i
] = powerStates
[i
];
755 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriver
,
756 (unsigned long) numberOfStates
,(unsigned long) powerStates
[0].version
);
757 for ( i
= 0; i
< numberOfStates
; i
++ )
759 pm_vars
->thePowerStates
[i
].version
= powerStates
[i
].version
;
760 pm_vars
->thePowerStates
[i
].capabilityFlags
= powerStates
[i
].capabilityFlags
;
761 pm_vars
->thePowerStates
[i
].outputPowerCharacter
= powerStates
[i
].outputPowerCharacter
;
762 pm_vars
->thePowerStates
[i
].inputPowerRequirement
= powerStates
[i
].inputPowerRequirement
;
763 pm_vars
->thePowerStates
[i
].staticPower
= powerStates
[i
].staticPower
;
764 pm_vars
->thePowerStates
[i
].unbudgetedPower
= powerStates
[i
].unbudgetedPower
;
765 pm_vars
->thePowerStates
[i
].powerToAttain
= powerStates
[i
].powerToAttain
;
766 pm_vars
->thePowerStates
[i
].timeToAttain
= powerStates
[i
].timeToAttain
;
767 pm_vars
->thePowerStates
[i
].settleUpTime
= powerStates
[i
].settleUpTime
;
768 pm_vars
->thePowerStates
[i
].timeToLower
= powerStates
[i
].timeToLower
;
769 pm_vars
->thePowerStates
[i
].settleDownTime
= powerStates
[i
].settleDownTime
;
770 pm_vars
->thePowerStates
[i
].powerDomainBudget
= powerStates
[i
].powerDomainBudget
;
774 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr1
,
775 (unsigned long)powerStates
[0].version
,0);
779 // make a mask of all the character bits we know about
780 pm_vars
->myCharacterFlags
= 0;
781 for ( i
= 0; i
< numberOfStates
; i
++ ) {
782 pm_vars
->myCharacterFlags
|= pm_vars
->thePowerStates
[i
].outputPowerCharacter
;
785 pm_vars
->theNumberOfPowerStates
= numberOfStates
;
786 pm_vars
->theControllingDriver
= controllingDriver
;
787 if ( priv
->interestedDrivers
->findItem(controllingDriver
) == NULL
)
789 // register it as interested, unless already done
790 registerInterestedDriver (controllingDriver
);
792 if ( priv
->need_to_become_usable
) {
793 priv
->need_to_become_usable
= false;
794 priv
->deviceDesire
= pm_vars
->theNumberOfPowerStates
- 1;
797 if ( inPlane(gIOPowerPlane
) &&
798 (pm_vars
->parentsKnowState
) ) {
799 pm_vars
->maxCapability
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(pm_vars
->parentsCurrentPowerFlags
);
800 // initially change into the state we are already in
801 tempDesire
= priv
->deviceDesire
;
802 priv
->deviceDesire
= pm_vars
->theControllingDriver
->initialPowerStateForDomainState(pm_vars
->parentsCurrentPowerFlags
);
803 computeDesiredState();
805 // put this back like before
806 priv
->deviceDesire
= tempDesire
;
809 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr2
,(unsigned long)numberOfStates
,0);
812 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr4
,0,0);
817 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr5
,(unsigned long)numberOfStates
,0);
822 //*********************************************************************************
823 // registerInterestedDriver
825 // Add the caller to our list of interested drivers and return our current
826 // power state. If we don't have a power-controlling driver yet, we will
827 // call this interested driver again later when we do get a driver and find
828 // out what the current power state of the device is.
829 //*********************************************************************************
831 IOPMPowerFlags
IOService::registerInterestedDriver ( IOService
* theDriver
)
833 IOPMinformee
*newInformee
;
834 IOPMPowerFlags futureCapability
;
836 if (theDriver
== NULL
) {
840 // make new driver node
841 newInformee
= new IOPMinformee
;
842 newInformee
->initialize(theDriver
);
843 // add it to list of drivers
844 priv
->interestedDrivers
->addToList(newInformee
);
846 if ( (pm_vars
->theControllingDriver
== NULL
) ||
847 !(inPlane(gIOPowerPlane
)) ||
848 !(pm_vars
->parentsKnowState
) )
850 // can't tell it a state yet
851 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInterestedDriver
,IOPMNotPowerManaged
,0);
852 return IOPMNotPowerManaged
;
855 // can we notify new driver of a change in progress?
856 switch (priv
->machine_state
) {
857 case kIOPM_OurChangeSetPowerState
:
858 case kIOPM_OurChangeFinish
:
859 case kIOPM_ParentDownSetPowerState_Delayed
:
860 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
861 case kIOPM_ParentUpSetPowerState_Delayed
:
862 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
863 // yes, remember what we tell it
864 futureCapability
= priv
->head_note_capabilityFlags
;
865 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInterestedDriver
,(unsigned long)futureCapability
,1);
867 add_driver_to_active_change(newInformee
);
868 // and return the same thing
869 return futureCapability
;
872 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInterestedDriver
,
873 (unsigned long) pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
,2);
875 // no, return current capability
876 return pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
;
880 //*********************************************************************************
881 // deRegisterInterestedDriver
883 //*********************************************************************************
884 IOReturn
IOService::deRegisterInterestedDriver ( IOService
* theDriver
)
886 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRemoveDriver
,0,0);
888 // remove the departing driver
889 priv
->interestedDrivers
->removeFromList(theDriver
);
895 //*********************************************************************************
896 // acknowledgePowerChange
898 // After we notified one of the interested drivers or a power-domain child
899 // of an impending change in power, it has called to say it is now
900 // prepared for the change. If this object is the last to
901 // acknowledge this change, we take whatever action we have been waiting
903 // That may include acknowledging to our parent. In this case, we do it
904 // last of all to insure that this doesn't cause the parent to call us some-
905 // where else and alter data we are relying on here (like the very existance
906 // of a "current change note".)
907 //*********************************************************************************
909 IOReturn
IOService::acknowledgePowerChange ( IOService
* whichObject
)
911 IOPMinformee
*ackingObject
;
912 unsigned long childPower
= kIOPMUnknown
;
915 // one of our interested drivers?
916 ackingObject
= priv
->interestedDrivers
->findItem(whichObject
);
917 if ( ackingObject
== NULL
)
919 if ( ! isChild(whichObject
,gIOPowerPlane
) )
921 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr1
,0,0);
922 //kprintf("errant driver: %s\n",whichObject->getName());
926 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChildAcknowledge
,priv
->head_note_pendingAcks
,0);
929 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogDriverAcknowledge
,priv
->head_note_pendingAcks
,0);
932 if (! acquire_lock() )
937 if (priv
->head_note_pendingAcks
!= 0 )
939 // yes, make sure we're expecting acks
940 if ( ackingObject
!= NULL
)
942 // it's an interested driver
943 // make sure we're expecting this ack
944 if ( ackingObject
->timer
!= 0 )
947 ackingObject
->timer
= 0;
948 // that's one fewer to worry about
949 priv
->head_note_pendingAcks
-= 1;
951 if ( priv
->head_note_pendingAcks
== 0 )
953 // yes, stop the timer
955 IOUnlock(priv
->our_lock
);
956 // and now we can continue
961 // this driver has already acked
962 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr2
,0,0);
963 //kprintf("errant driver: %s\n",whichObject->getName());
967 // make sure we're expecting this ack
968 if ( ((IOPowerConnection
*)whichObject
)->getAwaitingAck() )
970 // that's one fewer to worry about
971 priv
->head_note_pendingAcks
-= 1;
972 ((IOPowerConnection
*)whichObject
)->setAwaitingAck(false);
973 theChild
= (IOService
*)whichObject
->copyChildEntry(gIOPowerPlane
);
976 childPower
= theChild
->currentPowerConsumption();
979 if ( childPower
== kIOPMUnknown
)
981 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
= kIOPMUnknown
;
983 if ( pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
!= kIOPMUnknown
)
985 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
+= childPower
;
989 if ( priv
->head_note_pendingAcks
== 0 ) {
990 // yes, stop the timer
992 IOUnlock(priv
->our_lock
);
993 // and now we can continue
1000 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr3
,0,0); // not expecting anybody to ack
1001 //kprintf("errant driver: %s\n",whichObject->getName());
1003 IOUnlock(priv
->our_lock
);
1007 //*********************************************************************************
1008 // acknowledgeSetPowerState
1010 // After we instructed our controlling driver to change power states,
1011 // it has called to say it has finished doing so.
1012 // We continue to process the power state change.
1013 //*********************************************************************************
1015 IOReturn
IOService::acknowledgeSetPowerState ( void )
1017 if (!acquire_lock())
1020 IOReturn timer
= priv
->driver_timer
;
1021 if ( timer
== -1 ) {
1022 // driver is acking instead of using return code
1023 OUR_PMLog(kPMLogDriverAcknowledgeSet
, (UInt32
) this, timer
);
1024 priv
->driver_timer
= 0;
1026 else if ( timer
> 0 ) { // are we expecting this?
1027 // yes, stop the timer
1029 priv
->driver_timer
= 0;
1030 OUR_PMLog(kPMLogDriverAcknowledgeSet
, (UInt32
) this, timer
);
1031 IOUnlock(priv
->our_lock
);
1035 // not expecting this
1036 OUR_PMLog(kPMLogAcknowledgeErr4
, (UInt32
) this, 0);
1039 IOUnlock(priv
->our_lock
);
1044 //*********************************************************************************
1047 // Either the controlling driver has called acknowledgeSetPowerState
1048 // or the acknowledgement timer has expired while waiting for that.
1049 // We carry on processing the current change note.
1050 //*********************************************************************************
1052 void IOService::driver_acked ( void )
1054 switch (priv
->machine_state
) {
1055 case kIOPM_OurChangeWaitForPowerSettle
:
1056 OurChangeWaitForPowerSettle();
1058 case kIOPM_ParentDownWaitForPowerSettle_Delayed
:
1059 ParentDownWaitForPowerSettle_Delayed();
1061 case kIOPM_ParentUpWaitForSettleTime_Delayed
:
1062 ParentUpWaitForSettleTime_Delayed();
1068 //*********************************************************************************
1069 // powerDomainWillChangeTo
1071 // Called by the power-hierarchy parent notifying of a new power state
1072 // in the power domain.
1073 // We enqueue a parent power-change to our queue of power changes.
1074 // This may or may not cause us to change power, depending on what
1075 // kind of change is occuring in the domain.
1076 //*********************************************************************************
1078 IOReturn
IOService::powerDomainWillChangeTo ( IOPMPowerFlags newPowerStateFlags
, IOPowerConnection
* whichParent
)
1082 IOPowerConnection
*connection
;
1083 unsigned long newStateNumber
;
1084 IOPMPowerFlags combinedPowerFlags
;
1086 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogWillChange
,(unsigned long)newPowerStateFlags
,0);
1088 if ( ! inPlane(gIOPowerPlane
) )
1091 return IOPMAckImplied
;
1094 IOLockLock(pm_vars
->parentLock
);
1096 if ( (pm_vars
->PMworkloop
== NULL
) || (pm_vars
->PMcommandGate
== NULL
) )
1098 // we have a path to the root
1100 // so find out the workloop
1101 if ( pm_vars
->PMworkloop
!= NULL
)
1103 // and make our command gate
1104 if ( pm_vars
->PMcommandGate
== NULL
)
1106 pm_vars
->PMcommandGate
= IOCommandGate::commandGate((OSObject
*)this);
1107 if ( pm_vars
->PMcommandGate
!= NULL
)
1109 pm_vars
->PMworkloop
->addEventSource(pm_vars
->PMcommandGate
);
1115 IOLockUnlock(pm_vars
->parentLock
);
1117 // combine parents' power states
1118 // to determine our maximum state within the new power domain
1119 combinedPowerFlags
= 0;
1121 iter
= getParentIterator(gIOPowerPlane
);
1125 while ( (next
= iter
->getNextObject()) )
1127 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1129 if ( connection
== whichParent
){
1130 combinedPowerFlags
|= newPowerStateFlags
;
1132 combinedPowerFlags
|= connection
->parentCurrentPowerFlags();
1139 if ( pm_vars
->theControllingDriver
== NULL
)
1141 // we can't take any more action
1142 return IOPMAckImplied
;
1144 newStateNumber
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(combinedPowerFlags
);
1146 return enqueuePowerChange(IOPMParentInitiated
| IOPMDomainWillChange
,
1147 newStateNumber
,combinedPowerFlags
,whichParent
,newPowerStateFlags
);
1151 //*********************************************************************************
1152 // powerDomainDidChangeTo
1154 // Called by the power-hierarchy parent after the power state of the power domain
1155 // has settled at a new level.
1156 // We enqueue a parent power-change to our queue of power changes.
1157 // This may or may not cause us to change power, depending on what
1158 // kind of change is occuring in the domain.
1159 //*********************************************************************************
1161 IOReturn
IOService::powerDomainDidChangeTo ( IOPMPowerFlags newPowerStateFlags
, IOPowerConnection
* whichParent
)
1163 unsigned long newStateNumber
;
1165 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogDidChange
,newPowerStateFlags
,0);
1167 setParentInfo(newPowerStateFlags
,whichParent
);
1169 if ( pm_vars
->theControllingDriver
== NULL
) {
1170 return IOPMAckImplied
;
1173 newStateNumber
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(pm_vars
->parentsCurrentPowerFlags
);
1174 // tell interested parties about it
1175 return enqueuePowerChange(IOPMParentInitiated
| IOPMDomainDidChange
,
1176 newStateNumber
,pm_vars
->parentsCurrentPowerFlags
,whichParent
,0);
1180 //*********************************************************************************
1183 // Set our connection data for one specific parent, and then combine all the parent
1185 //*********************************************************************************
1187 void IOService::setParentInfo ( IOPMPowerFlags newPowerStateFlags
, IOPowerConnection
* whichParent
)
1191 IOPowerConnection
*connection
;
1193 // set our connection data
1194 whichParent
->setParentCurrentPowerFlags(newPowerStateFlags
);
1195 whichParent
->setParentKnowsState(true);
1197 IOLockLock(pm_vars
->parentLock
);
1199 // recompute our parent info
1200 pm_vars
->parentsCurrentPowerFlags
= 0;
1201 pm_vars
->parentsKnowState
= true;
1203 iter
= getParentIterator(gIOPowerPlane
);
1207 while ( (next
= iter
->getNextObject()) )
1209 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1211 pm_vars
->parentsKnowState
&= connection
->parentKnowsState();
1212 pm_vars
->parentsCurrentPowerFlags
|= connection
->parentCurrentPowerFlags();
1217 IOLockUnlock(pm_vars
->parentLock
);
1220 //*********************************************************************************
1221 // rebuildChildClampBits
1223 // The ChildClamp bits (kIOPMChildClamp & kIOPMChildClamp2) in our capabilityFlags
1224 // indicate that one of our children (or grandchildren or great-grandchildren or ...)
1225 // doesn't support idle or system sleep in its current state. Since we don't track the
1226 // origin of each bit, every time any child changes state we have to clear these bits
1227 // and rebuild them.
1228 //*********************************************************************************
1230 void IOService::rebuildChildClampBits(void)
1235 IOPowerConnection
*connection
;
1238 // A child's desires has changed. We need to rebuild the child-clamp bits in our
1239 // power state array. Start by clearing the bits in each power state.
1241 for ( i
= 0; i
< pm_vars
->theNumberOfPowerStates
; i
++ )
1243 pm_vars
->thePowerStates
[i
].capabilityFlags
&= ~(kIOPMChildClamp
| kIOPMChildClamp2
);
1246 // Now loop through the children. When we encounter the calling child, save
1247 // the computed state as this child's desire. And while we're at it, set the ChildClamp bits
1248 // in any of our states that some child has requested with clamp on.
1250 iter
= getChildIterator(gIOPowerPlane
);
1254 while ( (next
= iter
->getNextObject()) )
1256 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1258 if ( connection
->getPreventIdleSleepFlag() )
1259 pm_vars
->thePowerStates
[connection
->getDesiredDomainState()].capabilityFlags
|= kIOPMChildClamp
;
1260 if ( connection
->getPreventSystemSleepFlag() )
1261 pm_vars
->thePowerStates
[connection
->getDesiredDomainState()].capabilityFlags
|= kIOPMChildClamp2
;
1270 //*********************************************************************************
1271 // requestPowerDomainState
1273 // The kIOPMPreventIdleSleep and/or kIOPMPreventIdleSleep bits may be be set in the parameter.
1274 // It is not considered part of the state specification.
1275 //*********************************************************************************
1276 IOReturn
IOService::requestPowerDomainState ( IOPMPowerFlags desiredState
, IOPowerConnection
* whichChild
, unsigned long specification
)
1279 unsigned long computedState
;
1280 unsigned long theDesiredState
= desiredState
& ~(kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
1283 IOPowerConnection
*connection
;
1285 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRequestDomain
,
1286 (unsigned long)desiredState
,(unsigned long)specification
);
1288 if ( pm_vars
->theControllingDriver
== NULL
)
1290 return IOPMNotYetInitialized
;
1293 switch (specification
) {
1294 case IOPMLowestState
:
1296 while ( i
< pm_vars
->theNumberOfPowerStates
)
1298 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1304 if ( i
>= pm_vars
->theNumberOfPowerStates
)
1306 return IOPMNoSuchState
;
1310 case IOPMNextLowerState
:
1311 i
= pm_vars
->myCurrentState
- 1;
1312 while ( (int) i
>= 0 )
1314 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1322 return IOPMNoSuchState
;
1326 case IOPMHighestState
:
1327 i
= pm_vars
->theNumberOfPowerStates
;
1328 while ( (int) i
>= 0 )
1331 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1338 return IOPMNoSuchState
;
1342 case IOPMNextHigherState
:
1343 i
= pm_vars
->myCurrentState
+ 1;
1344 while ( i
< pm_vars
->theNumberOfPowerStates
)
1346 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1352 if ( i
== pm_vars
->theNumberOfPowerStates
)
1354 return IOPMNoSuchState
;
1359 return IOPMBadSpecification
;
1364 IOLockLock(pm_vars
->childLock
);
1366 // Now loop through the children. When we encounter the calling child, save
1367 // the computed state as this child's desire.
1368 iter
= getChildIterator(gIOPowerPlane
);
1372 while ( (next
= iter
->getNextObject()) )
1374 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1376 if ( connection
== whichChild
)
1378 connection
->setDesiredDomainState(computedState
);
1379 connection
->setPreventIdleSleepFlag(desiredState
& kIOPMPreventIdleSleep
);
1380 connection
->setPreventSystemSleepFlag(desiredState
& kIOPMPreventSystemSleep
);
1381 connection
->setChildHasRequestedPower();
1388 // Since a child's power requirements may have changed, clear and rebuild
1389 // kIOPMChildClamp and kIOPMChildClamp2 (idle and system sleep clamps)
1390 rebuildChildClampBits();
1392 IOLockUnlock(pm_vars
->childLock
);
1394 // this may be different now
1395 computeDesiredState();
1397 if ( inPlane(gIOPowerPlane
) &&
1398 (pm_vars
->parentsKnowState
) ) {
1399 // change state if all children can now tolerate lower power
1403 // are we clamped on, waiting for this child?
1404 if ( priv
->clampOn
) {
1405 // yes, remove the clamp
1406 priv
->clampOn
= false;
1407 changePowerStateToPriv(0);
1414 //*********************************************************************************
1415 // temporaryPowerClampOn
1417 // A power domain wants to clamp its power on till it has children which
1418 // will thendetermine the power domain state.
1420 // We enter the highest state until addPowerChild is called.
1421 //*********************************************************************************
1423 IOReturn
IOService::temporaryPowerClampOn ( void )
1425 priv
->clampOn
= true;
1431 //*********************************************************************************
1434 // Some client of our device is asking that we become usable. Although
1435 // this has not come from a subclassed device object, treat it exactly
1436 // as if it had. In this way, subsequent requests for lower power from
1437 // a subclassed device object will pre-empt this request.
1439 // We treat this as a subclass object request to switch to the
1440 // highest power state.
1441 //*********************************************************************************
1443 IOReturn
IOService::makeUsable ( void )
1445 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogMakeUsable
,0,0);
1447 if ( pm_vars
->theControllingDriver
== NULL
)
1449 priv
->need_to_become_usable
= true;
1452 priv
->deviceDesire
= pm_vars
->theNumberOfPowerStates
- 1;
1453 computeDesiredState();
1454 if ( inPlane(gIOPowerPlane
) && (pm_vars
->parentsKnowState
) )
1456 return changeState();
1462 //*********************************************************************************
1463 // currentCapability
1465 //*********************************************************************************
1467 IOPMPowerFlags
IOService::currentCapability ( void )
1469 if ( pm_vars
->theControllingDriver
== NULL
)
1473 return pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
;
1478 //*********************************************************************************
1479 // changePowerStateTo
1481 // For some reason, our power-controlling driver has decided it needs to change
1482 // power state. We enqueue the power change so that appropriate parties
1483 // will be notified, and then we will instruct the driver to make the change.
1484 //*********************************************************************************
1486 IOReturn
IOService::changePowerStateTo ( unsigned long ordinal
)
1488 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeStateTo
,ordinal
,0);
1490 if ( ordinal
>= pm_vars
->theNumberOfPowerStates
)
1492 return IOPMParameterError
;
1494 priv
->driverDesire
= ordinal
;
1495 computeDesiredState();
1496 if ( inPlane(gIOPowerPlane
) && (pm_vars
->parentsKnowState
) )
1498 return changeState();
1504 //*********************************************************************************
1505 // changePowerStateToPriv
1507 // For some reason, a subclassed device object has decided it needs to change
1508 // power state. We enqueue the power change so that appropriate parties
1509 // will be notified, and then we will instruct the driver to make the change.
1510 //*********************************************************************************
1512 IOReturn
IOService::changePowerStateToPriv ( unsigned long ordinal
)
1514 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeStateToPriv
,ordinal
,0);
1516 if ( pm_vars
->theControllingDriver
== NULL
)
1518 return IOPMNotYetInitialized
;
1520 if ( ordinal
>= pm_vars
->theNumberOfPowerStates
)
1522 return IOPMParameterError
;
1524 priv
->deviceDesire
= ordinal
;
1525 computeDesiredState();
1526 if ( inPlane(gIOPowerPlane
) && (pm_vars
->parentsKnowState
) )
1528 return changeState();
1535 //*********************************************************************************
1536 // computeDesiredState
1538 //*********************************************************************************
1540 void IOService::computeDesiredState ( void )
1544 IOPowerConnection
*connection
;
1545 unsigned long newDesiredState
= 0;
1547 // Compute the maximum of our children's desires, our controlling driver's desire, and the subclass device's desire.
1548 if ( ! priv
->device_overrides
)
1550 iter
= getChildIterator(gIOPowerPlane
);
1554 while ( (next
= iter
->getNextObject()) )
1556 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1558 if ( connection
->getDesiredDomainState() > newDesiredState
)
1560 newDesiredState
= connection
->getDesiredDomainState();
1567 if ( priv
->driverDesire
> newDesiredState
)
1569 newDesiredState
= priv
->driverDesire
;
1573 if ( priv
->deviceDesire
> newDesiredState
)
1575 newDesiredState
= priv
->deviceDesire
;
1578 priv
->ourDesiredPowerState
= newDesiredState
;
1582 //*********************************************************************************
1585 // A subclass object, our controlling driver, or a power domain child
1586 // has asked for a different power state. Here we compute what new
1587 // state we should enter and enqueue the change (or start it).
1588 //*********************************************************************************
1590 IOReturn
IOService::changeState ( void )
1592 // if not fully initialized
1593 if ( (pm_vars
->theControllingDriver
== NULL
) ||
1594 !(inPlane(gIOPowerPlane
)) ||
1595 !(pm_vars
->parentsKnowState
) )
1597 // we can do no more
1601 return enqueuePowerChange(IOPMWeInitiated
,priv
->ourDesiredPowerState
,0,0,0);
1605 //*********************************************************************************
1606 // currentPowerConsumption
1608 //*********************************************************************************
1610 unsigned long IOService::currentPowerConsumption ( void )
1612 if ( pm_vars
->theControllingDriver
== NULL
)
1614 return kIOPMUnknown
;
1616 if ( pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
& kIOPMStaticPowerValid
)
1618 return pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].staticPower
;
1620 return kIOPMUnknown
;
1623 //*********************************************************************************
1626 // The activity tickle with parameter kIOPMSubclassPolicyis not handled
1627 // here and should have been intercepted by the subclass.
1628 // The tickle with parameter kIOPMSuperclassPolicy1 causes the activity
1629 // flag to be set, and the device state checked. If the device has been
1630 // powered down, it is powered up again.
1631 //*********************************************************************************
1633 bool IOService::activityTickle ( unsigned long type
, unsigned long stateNumber
)
1635 IOPMrootDomain
*pmRootDomain
;
1636 AbsoluteTime uptime
;
1638 if ( type
== kIOPMSuperclassPolicy1
)
1640 if ( pm_vars
->theControllingDriver
== NULL
)
1645 if( priv
->activityLock
== NULL
)
1647 priv
->activityLock
= IOLockAlloc();
1650 IOTakeLock(priv
->activityLock
);
1651 priv
->device_active
= true;
1653 clock_get_uptime(&uptime
);
1654 priv
->device_active_timestamp
= uptime
;
1656 if ( pm_vars
->myCurrentState
>= stateNumber
)
1658 IOUnlock(priv
->activityLock
);
1661 IOUnlock(priv
->activityLock
);
1663 // Transfer execution to the PM workloop
1664 if( (pmRootDomain
= getPMRootDomain()) )
1665 pmRootDomain
->unIdleDevice(this, stateNumber
);
1672 //*********************************************************************************
1675 // A child is calling to get a pointer to the Power Management workloop.
1676 // We got it or get it from one of our parents.
1677 //*********************************************************************************
1679 IOWorkLoop
* IOService::getPMworkloop ( void )
1684 if ( ! inPlane(gIOPowerPlane
) )
1688 // we have no workloop yet
1689 if ( pm_vars
->PMworkloop
== NULL
)
1691 nub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
1694 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
1696 // ask one of our parents for the workloop
1699 pm_vars
->PMworkloop
= parent
->getPMworkloop();
1704 return pm_vars
->PMworkloop
;
1708 //*********************************************************************************
1709 // setIdleTimerPeriod
1711 // A subclass policy-maker is going to use our standard idleness
1712 // detection service. Make a command queue and an idle timer and
1713 // connect them to the power management workloop. Finally,
1715 //*********************************************************************************
1717 IOReturn
IOService::setIdleTimerPeriod ( unsigned long period
)
1719 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMsetIdleTimerPeriod
,period
, 0);
1721 priv
->idle_timer_period
= period
;
1725 if ( getPMworkloop() == NULL
)
1727 return kIOReturnError
;
1730 // make the timer event
1731 if ( priv
->timerEventSrc
== NULL
)
1733 priv
->timerEventSrc
= IOTimerEventSource::timerEventSource(this,
1734 PM_idle_timer_expired
);
1735 if ((!priv
->timerEventSrc
) ||
1736 (pm_vars
->PMworkloop
->addEventSource(priv
->timerEventSrc
) != kIOReturnSuccess
) )
1738 return kIOReturnError
;
1742 if ( priv
->activityLock
== NULL
)
1744 priv
->activityLock
= IOLockAlloc();
1747 start_PM_idle_timer();
1752 //******************************************************************************
1755 // Returns how many "seconds from now" the device should idle into its
1756 // next lowest power state.
1757 //******************************************************************************
1758 SInt32
IOService::nextIdleTimeout(
1759 AbsoluteTime currentTime
,
1760 AbsoluteTime lastActivity
,
1761 unsigned int powerState
)
1768 // Calculate time difference using funky macro from clock.h.
1769 delta
= currentTime
;
1770 SUB_ABSOLUTETIME(&delta
, &lastActivity
);
1772 // Figure it in seconds.
1773 absolutetime_to_nanoseconds(delta
, &delta_ns
);
1774 delta_secs
= (SInt32
)(delta_ns
/ NSEC_PER_SEC
);
1776 // Be paranoid about delta somehow exceeding timer period.
1777 if (delta_secs
< (int) priv
->idle_timer_period
)
1778 delay_secs
= (int) priv
->idle_timer_period
- delta_secs
;
1780 delay_secs
= (int) priv
->idle_timer_period
;
1782 return (SInt32
)delay_secs
;
1785 //******************************************************************************
1786 // start_PM_idle_timer
1788 // The parameter is a pointer to us. Use it to call our timeout method.
1789 //******************************************************************************
1790 void IOService::start_PM_idle_timer ( void )
1792 static const int maxTimeout
= 100000;
1793 static const int minTimeout
= 1;
1794 AbsoluteTime uptime
;
1797 IOLockLock(priv
->activityLock
);
1799 clock_get_uptime(&uptime
);
1801 // Subclasses may modify idle sleep algorithm
1802 idle_in
= nextIdleTimeout(uptime
,
1803 priv
->device_active_timestamp
,
1804 pm_vars
->myCurrentState
);
1806 // Check for out-of range responses
1807 if(idle_in
> maxTimeout
)
1809 // use standard implementation
1810 idle_in
= IOService::nextIdleTimeout(uptime
,
1811 priv
->device_active_timestamp
,
1812 pm_vars
->myCurrentState
);
1813 } else if(idle_in
< minTimeout
) {
1818 priv
->timerEventSrc
->setTimeout(idle_in
, NSEC_PER_SEC
);
1820 IOLockUnlock(priv
->activityLock
);
1825 //*********************************************************************************
1826 // PM_idle_timer_expired
1828 // The parameter is a pointer to us. Use it to call our timeout method.
1829 //*********************************************************************************
1831 void PM_idle_timer_expired(OSObject
* ourSelves
, IOTimerEventSource
*)
1833 ((IOService
*)ourSelves
)->PM_idle_timer_expiration();
1837 //*********************************************************************************
1838 // PM_idle_timer_expiration
1840 // The idle timer has expired. If there has been activity since the last
1841 // expiration, just restart the timer and return. If there has not been
1842 // activity, switch to the next lower power state and restart the timer.
1843 //*********************************************************************************
1845 void IOService::PM_idle_timer_expiration ( void )
1847 if ( ! initialized
)
1853 if ( priv
->idle_timer_period
> 0 )
1855 IOTakeLock(priv
->activityLock
);
1856 if ( priv
->device_active
)
1858 priv
->device_active
= false;
1859 IOUnlock(priv
->activityLock
);
1860 start_PM_idle_timer();
1863 if ( pm_vars
->myCurrentState
> 0 )
1865 IOUnlock(priv
->activityLock
);
1866 changePowerStateToPriv(pm_vars
->myCurrentState
- 1);
1867 start_PM_idle_timer();
1870 IOUnlock(priv
->activityLock
);
1871 start_PM_idle_timer();
1876 // **********************************************************************************
1879 // We are un-idling a device due to its activity tickle. This routine runs on the
1880 // PM workloop, and is initiated by IOService::activityTickle.
1881 // We process all activityTickle state requests on the list.
1882 // **********************************************************************************
1883 void IOService::command_received ( void *statePtr
, void *, void * , void * )
1885 unsigned long stateNumber
;
1887 stateNumber
= (unsigned long)statePtr
;
1889 // If not initialized, we're unloading
1890 if ( ! initialized
) return;
1892 if ( (pm_vars
->myCurrentState
< stateNumber
) &&
1893 (priv
->imminentState
< stateNumber
) )
1895 changePowerStateToPriv(stateNumber
);
1897 // After we raise our state, re-schedule the idle timer.
1898 if(priv
->timerEventSrc
)
1899 start_PM_idle_timer();
1904 //*********************************************************************************
1905 // setAggressiveness
1907 // Pass on the input parameters to all power domain children. All those which are
1908 // power domains will pass it on to their children, etc.
1909 //*********************************************************************************
1911 IOReturn
IOService::setAggressiveness ( unsigned long type
, unsigned long newLevel
)
1915 IOPowerConnection
*connection
;
1918 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogSetAggressiveness
,type
, newLevel
);
1920 if ( type
<= kMaxType
)
1922 pm_vars
->current_aggressiveness_values
[type
] = newLevel
;
1923 pm_vars
->current_aggressiveness_valid
[type
] = true;
1926 iter
= getChildIterator(gIOPowerPlane
);
1930 while ( (next
= iter
->getNextObject()) )
1932 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1934 child
= ((IOService
*)(connection
->copyChildEntry(gIOPowerPlane
)));
1937 child
->setAggressiveness(type
, newLevel
);
1948 //*********************************************************************************
1949 // getAggressiveness
1951 // Called by the user client.
1952 //*********************************************************************************
1954 IOReturn
IOService::getAggressiveness ( unsigned long type
, unsigned long * currentLevel
)
1956 if ( type
> kMaxType
)
1957 return kIOReturnBadArgument
;
1959 if ( !pm_vars
->current_aggressiveness_valid
[type
] )
1960 return kIOReturnInvalid
;
1962 *currentLevel
= pm_vars
->current_aggressiveness_values
[type
];
1964 return kIOReturnSuccess
;
1967 //*********************************************************************************
1970 // Pass this to all power domain children. All those which are
1971 // power domains will pass it on to their children, etc.
1972 //*********************************************************************************
1974 IOReturn
IOService::systemWake ( void )
1978 IOPowerConnection
*connection
;
1979 IOService
*theChild
;
1981 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogSystemWake
,0, 0);
1983 iter
= getChildIterator(gIOPowerPlane
);
1987 while ( (next
= iter
->getNextObject()) )
1989 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1991 theChild
= (IOService
*)connection
->copyChildEntry(gIOPowerPlane
);
1994 theChild
->systemWake();
1995 theChild
->release();
2002 if ( pm_vars
->theControllingDriver
!= NULL
)
2004 if ( pm_vars
->theControllingDriver
->didYouWakeSystem() )
2014 //*********************************************************************************
2015 // temperatureCriticalForZone
2017 //*********************************************************************************
2019 IOReturn
IOService::temperatureCriticalForZone ( IOService
* whichZone
)
2021 IOService
*theParent
;
2024 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogCriticalTemp
,0,0);
2026 if ( inPlane(gIOPowerPlane
) && !(priv
->we_are_root
) )
2028 theNub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
2031 theParent
= (IOService
*)theNub
->copyParentEntry(gIOPowerPlane
);
2035 theParent
->temperatureCriticalForZone(whichZone
);
2036 theParent
->release();
2044 //*********************************************************************************
2045 // powerOverrideOnPriv
2047 //*********************************************************************************
2050 IOReturn
IOService::powerOverrideOnPriv ( void )
2052 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogOverrideOn
,0,0);
2054 // turn on the override
2055 priv
->device_overrides
= true;
2056 computeDesiredState();
2058 // change state if that changed something
2059 return changeState();
2063 //*********************************************************************************
2064 // powerOverrideOffPriv
2066 //*********************************************************************************
2067 IOReturn
IOService::powerOverrideOffPriv ( void )
2069 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogOverrideOff
,0,0);
2071 // turn off the override
2072 priv
->device_overrides
= false;
2073 computeDesiredState();
2076 return makeUsable();
2078 // change state if that changed something
2079 return changeState();
2084 //*********************************************************************************
2085 // enqueuePowerChange
2087 // Allocate a new state change notification, initialize it with fields from the
2088 // caller, and add it to the tail of the list of pending power changes.
2090 // If it is early enough in the list, and almost all the time it is the only one in
2091 // the list, start the power change.
2093 // In rare instances, this change will preempt the previous change in the list.
2094 // If the previous change is un-actioned in any way (because we are still
2095 // processing an even earlier power change), and if both the previous change
2096 // in the list and this change are initiated by us (not the parent), then we
2097 // needn't perform the previous change, so we collapse the list a little.
2098 //*********************************************************************************
2100 IOReturn
IOService::enqueuePowerChange ( unsigned long flags
, unsigned long whatStateOrdinal
, unsigned long domainState
, IOPowerConnection
* whichParent
, unsigned long singleParentState
)
2105 // Create and initialize the new change note
2107 IOLockLock(priv
->queue_lock
);
2108 newNote
= priv
->changeList
->createChangeNote();
2109 if ( newNote
== -1 ) {
2110 // uh-oh, our list is full
2111 IOLockUnlock(priv
->queue_lock
);
2112 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogEnqueueErr
,0,0);
2113 return IOPMAckImplied
;
2116 priv
->changeList
->changeNote
[newNote
].newStateNumber
= whatStateOrdinal
;
2117 priv
->changeList
->changeNote
[newNote
].outputPowerCharacter
= pm_vars
->thePowerStates
[whatStateOrdinal
].outputPowerCharacter
;
2118 priv
->changeList
->changeNote
[newNote
].inputPowerRequirement
= pm_vars
->thePowerStates
[whatStateOrdinal
].inputPowerRequirement
;
2119 priv
->changeList
->changeNote
[newNote
].capabilityFlags
= pm_vars
->thePowerStates
[whatStateOrdinal
].capabilityFlags
;
2120 priv
->changeList
->changeNote
[newNote
].flags
= flags
;
2121 priv
->changeList
->changeNote
[newNote
].parent
= NULL
;
2122 if (flags
& IOPMParentInitiated
)
2124 priv
->changeList
->changeNote
[newNote
].domainState
= domainState
;
2125 priv
->changeList
->changeNote
[newNote
].parent
= whichParent
;
2126 whichParent
->retain();
2127 priv
->changeList
->changeNote
[newNote
].singleParentState
= singleParentState
;
2130 previousNote
= priv
->changeList
->previousChangeNote(newNote
);
2132 if ( previousNote
== -1 )
2135 // Queue is empty, we can start this change.
2137 if (flags
& IOPMWeInitiated
)
2139 IOLockUnlock(priv
->queue_lock
);
2140 start_our_change(newNote
);
2143 IOLockUnlock(priv
->queue_lock
);
2144 return start_parent_change(newNote
);
2148 // The queue is not empty. Try to collapse this new change and the previous one in queue into one change.
2149 // This is possible only if both changes are initiated by us, and neither has been started yet.
2150 // Do this more than once if possible.
2152 // (A change is started iff it is at the head of the queue)
2154 while ( (previousNote
!= priv
->head_note
) && (previousNote
!= -1) &&
2155 (priv
->changeList
->changeNote
[newNote
].flags
& priv
->changeList
->changeNote
[previousNote
].flags
& IOPMWeInitiated
) )
2157 priv
->changeList
->changeNote
[previousNote
].outputPowerCharacter
= priv
->changeList
->changeNote
[newNote
].outputPowerCharacter
;
2158 priv
->changeList
->changeNote
[previousNote
].inputPowerRequirement
= priv
->changeList
->changeNote
[newNote
].inputPowerRequirement
;
2159 priv
->changeList
->changeNote
[previousNote
].capabilityFlags
=priv
-> changeList
->changeNote
[newNote
].capabilityFlags
;
2160 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogCollapseQueue
,priv
->changeList
->changeNote
[newNote
].newStateNumber
,
2161 priv
->changeList
->changeNote
[previousNote
].newStateNumber
);
2162 priv
->changeList
->changeNote
[previousNote
].newStateNumber
= priv
->changeList
->changeNote
[newNote
].newStateNumber
;
2163 priv
->changeList
->releaseTailChangeNote();
2164 newNote
= previousNote
;
2165 previousNote
= priv
->changeList
->previousChangeNote(newNote
);
2167 IOLockUnlock(priv
->queue_lock
);
2168 // in any case, we can't start yet
2169 return IOPMWillAckLater
;
2172 //*********************************************************************************
2175 // Notify all interested parties either that a change is impending or that the
2176 // previously-notified change is done and power has settled.
2177 // The parameter identifies whether this is the
2178 // pre-change notification or the post-change notification.
2180 //*********************************************************************************
2182 IOReturn
IOService::notifyAll ( bool is_prechange
)
2184 IOPMinformee
* nextObject
;
2187 IOPowerConnection
* connection
;
2189 // To prevent acknowledgePowerChange from finishing the change note and removing it from the queue if
2190 // some driver calls it, we inflate the number of pending acks so it cannot become zero. We'll fix it later.
2192 priv
->head_note_pendingAcks
=1;
2194 // OK, we will go through the lists of interested drivers and power domain children
2195 // and notify each one of this change.
2197 nextObject
= priv
->interestedDrivers
->firstInList();
2198 while ( nextObject
!= NULL
) {
2199 priv
->head_note_pendingAcks
+=1;
2200 if (! inform(nextObject
, is_prechange
) )
2203 nextObject
= priv
->interestedDrivers
->nextInList(nextObject
);
2206 if (! acquire_lock() ) {
2209 // did they all ack?
2210 if ( priv
->head_note_pendingAcks
> 1 ) {
2212 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2216 IOUnlock(priv
->our_lock
);
2219 iter
= getChildIterator(gIOPowerPlane
);
2220 // summing their power consumption
2221 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
= 0;
2225 while ( (next
= iter
->getNextObject()) )
2227 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
2229 priv
->head_note_pendingAcks
+=1;
2230 notifyChild(connection
, is_prechange
);
2236 if (! acquire_lock() ) {
2239 // now make this real
2240 priv
->head_note_pendingAcks
-= 1;
2242 if (priv
->head_note_pendingAcks
== 0 ) {
2244 IOUnlock(priv
->our_lock
);
2245 // return ack to parent
2246 return IOPMAckImplied
;
2250 IOUnlock(priv
->our_lock
);
2251 return IOPMWillAckLater
;
2255 //*********************************************************************************
2258 // Notify a power domain child of an upcoming power change.
2260 // If the object acknowledges the current change, we return TRUE.
2261 //*********************************************************************************
2263 bool IOService::notifyChild ( IOPowerConnection
* theNub
, bool is_prechange
)
2265 IOReturn k
= IOPMAckImplied
;
2266 unsigned long childPower
;
2267 IOService
*theChild
= (IOService
*)(theNub
->copyChildEntry(gIOPowerPlane
));
2269 theNub
->setAwaitingAck(true); // in case they don't ack
2278 k
= theChild
->powerDomainWillChangeTo(priv
->head_note_outputFlags
,theNub
);
2280 k
= theChild
->powerDomainDidChangeTo(priv
->head_note_outputFlags
,theNub
);
2283 // did the return code ack?
2284 if ( k
== IOPMAckImplied
)
2287 priv
->head_note_pendingAcks
-=1;
2288 theNub
->setAwaitingAck(false);
2289 childPower
= theChild
->currentPowerConsumption();
2290 if ( childPower
== kIOPMUnknown
)
2292 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
= kIOPMUnknown
;
2294 if ( pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
!= kIOPMUnknown
)
2296 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
+= childPower
;
2299 theChild
->release();
2302 theChild
->release();
2307 //*********************************************************************************
2310 // Notify an interested driver of an upcoming power change.
2312 // If the object acknowledges the current change, we return TRUE.
2313 //*********************************************************************************
2315 bool IOService::inform ( IOPMinformee
* nextObject
, bool is_prechange
)
2317 IOReturn k
= IOPMAckImplied
;
2320 nextObject
->timer
= -1;
2324 pm_vars
->thePlatform
->PMLog (pm_vars
->ourName
,PMlogInformDriverPreChange
,
2325 (unsigned long)priv
->head_note_capabilityFlags
,(unsigned long)priv
->head_note_state
);
2326 k
= nextObject
->whatObject
->powerStateWillChangeTo( priv
->head_note_capabilityFlags
,priv
->head_note_state
,this);
2328 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInformDriverPostChange
,
2329 (unsigned long)priv
->head_note_capabilityFlags
,(unsigned long)priv
->head_note_state
);
2330 k
= nextObject
->whatObject
->powerStateDidChangeTo(priv
->head_note_capabilityFlags
,priv
->head_note_state
,this);
2333 // did it ack behind our back?
2334 if ( nextObject
->timer
== 0 )
2340 // no, did the return code ack?
2341 if ( k
==IOPMAckImplied
)
2344 nextObject
->timer
= 0;
2345 priv
->head_note_pendingAcks
-= 1;
2351 nextObject
->timer
= 0;
2352 priv
-> head_note_pendingAcks
-= 1;
2357 nextObject
->timer
= (k
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
2363 //*********************************************************************************
2364 // OurChangeTellClientsPowerDown
2366 // All registered applications and kernel clients have positively acknowledged our
2367 // intention of lowering power. Here we notify them all that we will definitely
2368 // lower the power. If we don't have to wait for any of them to acknowledge, we
2369 // carry on by notifying interested drivers. Otherwise, we do wait.
2370 //*********************************************************************************
2372 void IOService::OurChangeTellClientsPowerDown ( void )
2375 priv
->machine_state
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
2377 // are we waiting for responses?
2378 if ( tellChangeDown1(priv
->head_note_state
) )
2380 // no, notify priority clients
2381 OurChangeTellPriorityClientsPowerDown();
2383 // If we are waiting for responses, execution will resume via
2384 // allowCancelCommon() or ack timeout
2388 //*********************************************************************************
2389 // OurChangeTellPriorityClientsPowerDown
2391 // All registered applications and kernel clients have positively acknowledged our
2392 // intention of lowering power. Here we notify "priority" clients that we are
2393 // lowering power. If we don't have to wait for any of them to acknowledge, we
2394 // carry on by notifying interested drivers. Otherwise, we do wait.
2395 //*********************************************************************************
2397 void IOService::OurChangeTellPriorityClientsPowerDown ( void )
2400 priv
->machine_state
= kIOPM_OurChangeNotifyInterestedDriversWillChange
;
2401 // are we waiting for responses?
2402 if ( tellChangeDown2(priv
->head_note_state
) )
2404 // no, notify interested drivers
2405 return OurChangeNotifyInterestedDriversWillChange();
2407 // If we are waiting for responses, execution will resume via
2408 // allowCancelCommon() or ack timeout
2412 //*********************************************************************************
2413 // OurChangeNotifyInterestedDriversWillChange
2415 // All registered applications and kernel clients have acknowledged our notification
2416 // that we are lowering power. Here we notify interested drivers. If we don't have
2417 // to wait for any of them to acknowledge, we instruct our power driver to make the change.
2418 // Otherwise, we do wait.
2419 //*********************************************************************************
2421 void IOService::OurChangeNotifyInterestedDriversWillChange ( void )
2423 // no, in case they don't all ack
2424 priv
->machine_state
= kIOPM_OurChangeSetPowerState
;
2425 if ( notifyAll(true) == IOPMAckImplied
)
2427 // not waiting for responses
2428 OurChangeSetPowerState();
2430 // If we are waiting for responses, execution will resume via
2431 // all_acked() or ack timeout
2435 //*********************************************************************************
2436 // OurChangeSetPowerState
2438 // All interested drivers have acknowledged our pre-change notification of a power
2439 // change we initiated. Here we instruct our controlling driver to make
2440 // the change to the hardware. If it does so, we continue processing
2441 // (waiting for settle and notifying interested parties post-change.)
2442 // If it doesn't, we have to wait for it to acknowledge and then continue.
2443 //*********************************************************************************
2445 void IOService::OurChangeSetPowerState ( void )
2447 priv
->machine_state
= kIOPM_OurChangeWaitForPowerSettle
;
2449 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2451 // it's done, carry on
2452 OurChangeWaitForPowerSettle();
2454 // it's not, wait for it
2455 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2457 // execution will resume via ack_timer_ticked()
2462 //*********************************************************************************
2463 // OurChangeWaitForPowerSettle
2465 // Our controlling driver has changed power state on the hardware
2466 // during a power change we initiated. Here we see if we need to wait
2467 // for power to settle before continuing. If not, we continue processing
2468 // (notifying interested parties post-change). If so, we wait and
2470 //*********************************************************************************
2472 void IOService::OurChangeWaitForPowerSettle ( void )
2474 priv
->settle_time
= compute_settle_time();
2475 if ( priv
->settle_time
== 0 )
2477 OurChangeNotifyInterestedDriversDidChange();
2479 priv
->machine_state
= kIOPM_OurChangeNotifyInterestedDriversDidChange
;
2480 startSettleTimer(priv
->settle_time
);
2485 //*********************************************************************************
2486 // OurChangeNotifyInterestedDriversDidChange
2488 // Power has settled on a power change we initiated. Here we notify
2489 // all our interested parties post-change. If they all acknowledge, we're
2490 // done with this change note, and we can start on the next one.
2491 // Otherwise we have to wait for acknowledgements and finish up later.
2492 //*********************************************************************************
2494 void IOService::OurChangeNotifyInterestedDriversDidChange ( void )
2496 // in case they don't all ack
2497 priv
->machine_state
= kIOPM_OurChangeFinish
;
2498 if ( notifyAll(false) == IOPMAckImplied
)
2500 // not waiting for responses
2503 // If we are waiting for responses, execution will resume via
2504 // all_acked() or ack timeout
2508 //*********************************************************************************
2511 // Power has settled on a power change we initiated, and
2512 // all our interested parties have acknowledged. We're
2513 // done with this change note, and we can start on the next one.
2514 //*********************************************************************************
2516 void IOService::OurChangeFinish ( void )
2522 //*********************************************************************************
2523 // ParentDownTellPriorityClientsPowerDown_Immediate
2525 // All applications and kernel clients have been notified of a power lowering
2526 // initiated by the parent and we didn't have to wait for any responses. Here
2527 // we notify any priority clients. If they all ack, we continue with the power change.
2528 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2529 //*********************************************************************************
2531 IOReturn
IOService::ParentDownTellPriorityClientsPowerDown_Immediate ( void )
2533 // in case they don't all ack
2534 priv
->machine_state
= kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
;
2535 // are we waiting for responses?
2536 if ( tellChangeDown2(priv
->head_note_state
) )
2538 // no, notify interested drivers
2539 return ParentDownNotifyInterestedDriversWillChange_Immediate();
2541 // If we are waiting for responses, execution will resume via
2542 // allowCancelCommon() or ack timeout
2543 return IOPMWillAckLater
;
2547 //*********************************************************************************
2548 // ParentDownTellPriorityClientsPowerDown_Immediate2
2550 // All priority kernel clients have been notified of a power lowering
2551 // initiated by the parent and we didn't have to wait for any responses. Here
2552 // we notify any interested drivers and power domain children. If they all ack,
2553 // we continue with the power change.
2554 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2555 //*********************************************************************************
2557 IOReturn
IOService::ParentDownNotifyInterestedDriversWillChange_Immediate ( void )
2559 // in case they don't all ack
2560 priv
->machine_state
= kIOPM_ParentDownSetPowerState_Delayed
;
2561 if ( notifyAll(true) == IOPMAckImplied
)
2564 return ParentDownSetPowerState_Immediate();
2566 // If we are waiting for responses, execution will resume via
2567 // all_acked() or ack timeout
2568 return IOPMWillAckLater
;
2572 //*********************************************************************************
2573 // ParentDownTellPriorityClientsPowerDown_Immediate4
2575 // All applications and kernel clients have been notified of a power lowering
2576 // initiated by the parent and we had to wait for responses. Here
2577 // we notify any priority clients. If they all ack, we continue with the power change.
2578 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2579 //*********************************************************************************
2581 void IOService::ParentDownTellPriorityClientsPowerDown_Delayed ( void )
2583 // in case they don't all ack
2584 priv
->machine_state
= kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
;
2586 // are we waiting for responses?
2587 if ( tellChangeDown2(priv
->head_note_state
) )
2589 // no, notify interested drivers
2590 ParentDownNotifyInterestedDriversWillChange_Delayed();
2592 // If we are waiting for responses, execution will resume via
2593 // allowCancelCommon() or ack timeout
2597 //*********************************************************************************
2598 // ParentDownTellPriorityClientsPowerDown_Immediate5
2600 // All applications and kernel clients have been notified of a power lowering
2601 // initiated by the parent and we had to wait for their responses. Here we notify
2602 // any interested drivers and power domain children. If they all ack, we continue
2603 // with the power change.
2604 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2605 //*********************************************************************************
2607 void IOService::ParentDownNotifyInterestedDriversWillChange_Delayed ( void )
2609 // in case they don't all ack
2610 priv
->machine_state
= kIOPM_ParentDownSetPowerState_Delayed
;
2611 if ( notifyAll(true) == IOPMAckImplied
)
2614 ParentDownSetPowerState_Delayed();
2616 // If we are waiting for responses, execution will resume via
2617 // all_acked() or ack timeout
2621 //*********************************************************************************
2622 // ParentDownSetPowerState_Immediate
2624 // All parties have acknowledged our pre-change notification of a power
2625 // lowering initiated by the parent. Here we instruct our controlling driver
2626 // to put the hardware in the state it needs to be in when the domain is
2627 // lowered. If it does so, we continue processing
2628 // (waiting for settle and acknowledging the parent.)
2629 // If it doesn't, we have to wait for it to acknowledge and then continue.
2630 //*********************************************************************************
2632 IOReturn
IOService::ParentDownSetPowerState_Immediate ( void )
2634 priv
->machine_state
= kIOPM_ParentDownWaitForPowerSettle_Delayed
;
2636 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2638 // it's done, carry on
2639 return ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate();
2641 // it's not, wait for it
2642 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2644 return IOPMWillAckLater
;
2648 //*********************************************************************************
2649 // ParentDownSetPowerState_Delayed
2651 // We had to wait for it, but all parties have acknowledged our pre-change
2652 // notification of a power lowering initiated by the parent.
2653 // Here we instruct our controlling driver
2654 // to put the hardware in the state it needs to be in when the domain is
2655 // lowered. If it does so, we continue processing
2656 // (waiting for settle and acknowledging the parent.)
2657 // If it doesn't, we have to wait for it to acknowledge and then continue.
2658 //*********************************************************************************
2660 void IOService::ParentDownSetPowerState_Delayed ( void )
2662 priv
-> machine_state
= kIOPM_ParentDownWaitForPowerSettle_Delayed
;
2664 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2666 // it's done, carry on
2667 ParentDownWaitForPowerSettle_Delayed();
2669 // it's not, wait for it
2670 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2676 //*********************************************************************************
2677 // ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate
2679 // Our controlling driver has changed power state on the hardware
2680 // during a power change initiated by our parent. Here we see if we need
2681 // to wait for power to settle before continuing. If not, we continue
2682 // processing (acknowledging our preparedness to the parent).
2683 // If so, we wait and continue later.
2684 //*********************************************************************************
2686 IOReturn
IOService::ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate ( void )
2690 priv
->settle_time
= compute_settle_time();
2691 if ( priv
->settle_time
== 0 )
2693 // store current state in case they don't all ack
2694 priv
->machine_state
= kIOPM_ParentDownAcknowledgeChange_Delayed
;
2695 if ( notifyAll(false) == IOPMAckImplied
)
2697 // not waiting for responses
2698 nub
= priv
->head_note_parent
;
2702 return IOPMAckImplied
;
2704 // If we are waiting for responses, execution will resume via
2705 // all_acked() or ack timeout
2706 return IOPMWillAckLater
;
2708 // let settle time elapse, then notify interest drivers of our power state change in ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
2709 priv
->machine_state
= kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
;
2710 startSettleTimer(priv
->settle_time
);
2711 return IOPMWillAckLater
;
2716 //*********************************************************************************
2717 // ParentDownWaitForPowerSettle_Delayed
2719 // Our controlling driver has changed power state on the hardware
2720 // during a power change initiated by our parent. We have had to wait
2721 // for acknowledgement from interested parties, or we have had to wait
2722 // for the controlling driver to change the state. Here we see if we need
2723 // to wait for power to settle before continuing. If not, we continue
2724 // processing (acknowledging our preparedness to the parent).
2725 // If so, we wait and continue later.
2726 //*********************************************************************************
2728 void IOService::ParentDownWaitForPowerSettle_Delayed ( void )
2730 priv
->settle_time
= compute_settle_time();
2731 if ( priv
->settle_time
== 0 )
2733 ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed();
2735 priv
->machine_state
= kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
;
2736 startSettleTimer(priv
->settle_time
);
2741 //*********************************************************************************
2742 // ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
2744 // Power has settled on a power change initiated by our parent. Here we
2745 // notify interested parties.
2746 //*********************************************************************************
2748 void IOService::ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed ( void )
2750 IORegistryEntry
*nub
;
2753 // in case they don't all ack
2754 priv
->machine_state
= kIOPM_ParentDownAcknowledgeChange_Delayed
;
2755 if ( notifyAll(false) == IOPMAckImplied
) {
2756 nub
= priv
->head_note_parent
;
2759 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
2761 parent
->acknowledgePowerChange((IOService
*)nub
);
2766 // If we are waiting for responses, execution will resume via
2767 // all_acked() or ack timeout in ParentDownAcknowledgeChange_Delayed.
2768 // Notice the duplication of code just above and in ParentDownAcknowledgeChange_Delayed.
2772 //*********************************************************************************
2773 // ParentDownAcknowledgeChange_Delayed
2775 // We had to wait for it, but all parties have acknowledged our post-change
2776 // notification of a power lowering initiated by the parent.
2777 // Here we acknowledge the parent.
2778 // We are done with this change note, and we can start on the next one.
2779 //*********************************************************************************
2781 void IOService::ParentDownAcknowledgeChange_Delayed ( void )
2783 IORegistryEntry
*nub
;
2786 nub
= priv
->head_note_parent
;
2789 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
2792 parent
->acknowledgePowerChange((IOService
*)nub
);
2799 //*********************************************************************************
2800 // ParentUpSetPowerState_Delayed
2802 // Our parent has informed us via powerStateDidChange that it has
2803 // raised the power in our power domain, and we have had to wait
2804 // for some interested party to acknowledge our notification.
2805 // Here we instruct our controlling
2806 // driver to program the hardware to take advantage of the higher domain
2807 // power. If it does so, we continue processing
2808 // (waiting for settle and notifying interested parties post-change.)
2809 // If it doesn't, we have to wait for it to acknowledge and then continue.
2810 //*********************************************************************************
2812 void IOService::ParentUpSetPowerState_Delayed ( void )
2814 priv
->machine_state
= kIOPM_ParentUpWaitForSettleTime_Delayed
;
2816 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2818 // it did it, carry on
2819 ParentUpWaitForSettleTime_Delayed();
2821 // it didn't, wait for it
2822 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2828 //*********************************************************************************
2829 // ParentUpSetPowerState_Immediate
2831 // Our parent has informed us via powerStateDidChange that it has
2832 // raised the power in our power domain. Here we instruct our controlling
2833 // driver to program the hardware to take advantage of the higher domain
2834 // power. If it does so, we continue processing
2835 // (waiting for settle and notifying interested parties post-change.)
2836 // If it doesn't, we have to wait for it to acknowledge and then continue.
2837 //*********************************************************************************
2839 IOReturn
IOService::ParentUpSetPowerState_Immediate ( void )
2841 priv
->machine_state
= kIOPM_ParentUpWaitForSettleTime_Delayed
;
2843 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2845 // it did it, carry on
2846 return ParentUpWaitForSettleTime_Immediate();
2849 // it didn't, wait for it
2850 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2852 return IOPMWillAckLater
;
2857 //*********************************************************************************
2858 // ParentUpWaitForSettleTime_Immediate
2860 // Our controlling driver has changed power state on the hardware
2861 // during a power raise initiated by the parent. Here we see if we need to wait
2862 // for power to settle before continuing. If not, we continue processing
2863 // (notifying interested parties post-change). If so, we wait and
2865 //*********************************************************************************
2867 IOReturn
IOService::ParentUpWaitForSettleTime_Immediate ( void )
2869 priv
->settle_time
= compute_settle_time();
2870 if ( priv
->settle_time
== 0 )
2872 return ParentUpNotifyInterestedDriversDidChange_Immediate();
2874 priv
->machine_state
= kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed
;
2875 startSettleTimer(priv
->settle_time
);
2876 return IOPMWillAckLater
;
2881 //*********************************************************************************
2882 // ParentUpWaitForSettleTime_Delayed
2884 // Our controlling driver has changed power state on the hardware
2885 // during a power raise initiated by the parent, but we had to wait for it.
2886 // Here we see if we need to wait for power to settle before continuing.
2887 // If not, we continue processing (notifying interested parties post-change).
2888 // If so, we wait and continue later.
2889 //*********************************************************************************
2891 void IOService::ParentUpWaitForSettleTime_Delayed ( void )
2893 priv
->settle_time
= compute_settle_time();
2894 if ( priv
->settle_time
== 0 )
2896 ParentUpNotifyInterestedDriversDidChange_Delayed();
2898 priv
->machine_state
= kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed
;
2899 startSettleTimer(priv
->settle_time
);
2904 //*********************************************************************************
2905 // ParentUpNotifyInterestedDriversDidChange_Immediate
2907 // No power settling was required on a power raise initiated by the parent.
2908 // Here we notify all our interested parties post-change. If they all acknowledge,
2909 // we're done with this change note, and we can start on the next one.
2910 // Otherwise we have to wait for acknowledgements and finish up later.
2911 //*********************************************************************************
2913 IOReturn
IOService::ParentUpNotifyInterestedDriversDidChange_Immediate ( void )
2917 // in case they don't all ack
2918 priv
->machine_state
= kIOPM_ParentUpAcknowledgePowerChange_Delayed
;
2919 if ( notifyAll(false) == IOPMAckImplied
)
2921 nub
= priv
->head_note_parent
;
2925 return IOPMAckImplied
;
2927 // If we are waiting for responses, execution will resume via
2928 // all_acked() or ack timeout in ParentUpAcknowledgePowerChange_Delayed.
2929 return IOPMWillAckLater
;
2933 //*********************************************************************************
2934 // ParentUpNotifyInterestedDriversDidChange_Delayed
2936 // Power has settled on a power raise initiated by the parent.
2937 // Here we notify all our interested parties post-change. If they all acknowledge,
2938 // we're done with this change note, and we can start on the next one.
2939 // Otherwise we have to wait for acknowledgements and finish up later.
2940 //*********************************************************************************
2942 void IOService::ParentUpNotifyInterestedDriversDidChange_Delayed ( void )
2944 // in case they don't all ack
2945 priv
->machine_state
= kIOPM_ParentUpAcknowledgePowerChange_Delayed
;
2946 if ( notifyAll(false) == IOPMAckImplied
)
2948 ParentUpAcknowledgePowerChange_Delayed();
2950 // If we are waiting for responses, execution will resume via
2951 // all_acked() or ack timeout in ParentUpAcknowledgePowerChange_Delayed.
2955 //*********************************************************************************
2956 // ParentUpAcknowledgePowerChange_Delayed
2958 // All parties have acknowledged our post-change notification of a power
2959 // raising initiated by the parent. Here we acknowledge the parent.
2960 // We are done with this change note, and we can start on the next one.
2961 //*********************************************************************************
2963 void IOService::ParentUpAcknowledgePowerChange_Delayed ( void )
2965 IORegistryEntry
*nub
;
2968 nub
= priv
->head_note_parent
;
2971 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
2974 parent
->acknowledgePowerChange((IOService
*)nub
);
2981 //*********************************************************************************
2984 // A power change is complete, and the used post-change note is at
2985 // the head of the queue. Remove it and set myCurrentState to the result
2986 // of the change. Start up the next change in queue.
2987 //*********************************************************************************
2989 void IOService::all_done ( void )
2991 unsigned long previous_state
;
2992 IORegistryEntry
*nub
;
2995 priv
->machine_state
= kIOPM_Finished
;
2998 if ( priv
->head_note_flags
& IOPMWeInitiated
)
3000 // could our driver switch to the new state?
3001 if ( !( priv
->head_note_flags
& IOPMNotDone
) )
3003 // yes, did power raise?
3004 if ( pm_vars
->myCurrentState
< priv
->head_note_state
)
3006 // yes, inform clients and apps
3007 tellChangeUp (priv
->head_note_state
);
3009 // no, if this lowers our
3010 if ( ! priv
->we_are_root
)
3012 // power requirements, tell the parent
3013 ask_parent(priv
->head_note_state
);
3016 previous_state
= pm_vars
->myCurrentState
;
3018 pm_vars
->myCurrentState
= priv
->head_note_state
;
3019 priv
->imminentState
= pm_vars
->myCurrentState
;
3020 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeDone
,(unsigned long)pm_vars
->myCurrentState
,0);
3021 // inform subclass policy-maker
3022 powerChangeDone(previous_state
);
3026 // parent's power change
3027 if ( priv
->head_note_flags
& IOPMParentInitiated
)
3029 if ( ((priv
->head_note_flags
& IOPMDomainWillChange
) && (pm_vars
->myCurrentState
>= priv
->head_note_state
)) ||
3030 ((priv
->head_note_flags
& IOPMDomainDidChange
) && (pm_vars
->myCurrentState
< priv
->head_note_state
)) )
3033 if ( pm_vars
->myCurrentState
< priv
->head_note_state
)
3035 // yes, inform clients and apps
3036 tellChangeUp (priv
->head_note_state
);
3039 previous_state
= pm_vars
->myCurrentState
;
3040 pm_vars
->myCurrentState
= priv
->head_note_state
;
3041 priv
->imminentState
= pm_vars
->myCurrentState
;
3042 pm_vars
->maxCapability
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(priv
->head_note_domainState
);
3044 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeDone
,(unsigned long)pm_vars
->myCurrentState
,0);
3045 // inform subclass policy-maker
3046 powerChangeDone(previous_state
);
3050 IOLockLock(priv
->queue_lock
);
3051 // we're done with this
3052 priv
->changeList
->releaseHeadChangeNote();
3054 // start next one in queue
3055 priv
->head_note
= priv
->changeList
->currentChange();
3056 if ( priv
->head_note
!= -1 )
3059 IOLockUnlock(priv
->queue_lock
);
3060 if (priv
->changeList
->changeNote
[priv
->head_note
].flags
& IOPMWeInitiated
)
3062 start_our_change(priv
->head_note
);
3064 nub
= priv
->changeList
->changeNote
[priv
->head_note
].parent
;
3065 if ( start_parent_change(priv
->head_note
) == IOPMAckImplied
)
3067 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
3070 parent
->acknowledgePowerChange((IOService
*)nub
);
3076 IOLockUnlock(priv
->queue_lock
);
3082 //*********************************************************************************
3085 // A driver or child has acknowledged our notification of an upcoming power
3086 // change, and this acknowledgement is the last one pending
3087 // before we change power or after changing power.
3089 //*********************************************************************************
3091 void IOService::all_acked ( void )
3093 switch (priv
->machine_state
) {
3094 case kIOPM_OurChangeSetPowerState
:
3095 OurChangeSetPowerState();
3097 case kIOPM_OurChangeFinish
:
3100 case kIOPM_ParentDownSetPowerState_Delayed
:
3101 ParentDownSetPowerState_Delayed();
3103 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3104 ParentDownAcknowledgeChange_Delayed();
3106 case kIOPM_ParentUpSetPowerState_Delayed
:
3107 ParentUpSetPowerState_Delayed();
3109 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3110 ParentUpAcknowledgePowerChange_Delayed();
3115 //*********************************************************************************
3116 // settleTimerExpired
3118 // Power has settled after our last change. Notify interested parties that
3119 // there is a new power state.
3120 //*********************************************************************************
3122 void IOService::settleTimerExpired ( void )
3124 if ( ! initialized
)
3130 switch (priv
->machine_state
) {
3131 case kIOPM_OurChangeNotifyInterestedDriversDidChange
:
3132 OurChangeNotifyInterestedDriversDidChange();
3134 case kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
:
3135 ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed();
3137 case kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed
:
3138 ParentUpNotifyInterestedDriversDidChange_Delayed();
3144 //*********************************************************************************
3145 // compute_settle_time
3147 // Compute the power-settling delay in microseconds for the
3148 // change from myCurrentState to head_note_state.
3149 //*********************************************************************************
3151 unsigned long IOService::compute_settle_time ( void )
3153 unsigned long totalTime
;
3156 // compute total time to attain the new state
3158 i
= pm_vars
->myCurrentState
;
3160 // we're lowering power
3161 if ( priv
->head_note_state
< pm_vars
->myCurrentState
)
3163 while ( i
> priv
->head_note_state
)
3165 totalTime
+= pm_vars
->thePowerStates
[i
].settleDownTime
;
3170 // we're raising power
3171 if ( priv
->head_note_state
> pm_vars
->myCurrentState
)
3173 while ( i
< priv
->head_note_state
)
3175 totalTime
+= pm_vars
->thePowerStates
[i
+1].settleUpTime
;
3184 //*********************************************************************************
3187 // Enter with a power-settling delay in microseconds and start a nano-second
3188 // timer for that delay.
3189 //*********************************************************************************
3191 IOReturn
IOService::startSettleTimer ( unsigned long delay
)
3193 AbsoluteTime deadline
;
3195 clock_interval_to_deadline(delay
, kMicrosecondScale
, &deadline
);
3197 thread_call_enter_delayed(priv
->settleTimer
, deadline
);
3202 //*********************************************************************************
3205 // The acknowledgement timeout periodic timer has ticked.
3206 // If we are awaiting acks for a power change notification,
3207 // we decrement the timer word of each interested driver which hasn't acked.
3208 // If a timer word becomes zero, we pretend the driver aknowledged.
3209 // If we are waiting for the controlling driver to change the power
3210 // state of the hardware, we decrement its timer word, and if it becomes
3211 // zero, we pretend the driver acknowledged.
3212 //*********************************************************************************
3214 void IOService::ack_timer_ticked ( void )
3216 IOPMinformee
* nextObject
;
3218 if ( ! initialized
)
3224 if (! acquire_lock() )
3229 switch (priv
->machine_state
) {
3230 case kIOPM_OurChangeWaitForPowerSettle
:
3231 case kIOPM_ParentDownWaitForPowerSettle_Delayed
:
3232 case kIOPM_ParentUpWaitForSettleTime_Delayed
:
3233 // are we waiting for our driver to make its change?
3234 if ( priv
->driver_timer
!= 0 ) {
3236 priv
->driver_timer
-= 1;
3237 // it's tardy, we'll go on without it
3238 if ( priv
->driver_timer
== 0 )
3240 IOUnlock(priv
->our_lock
);
3241 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogCtrlDriverTardy
,0,0);
3244 // still waiting, set timer again
3246 IOUnlock(priv
->our_lock
);
3250 IOUnlock(priv
->our_lock
);
3254 case kIOPM_OurChangeSetPowerState
:
3255 case kIOPM_OurChangeFinish
:
3256 case kIOPM_ParentDownSetPowerState_Delayed
:
3257 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3258 case kIOPM_ParentUpSetPowerState_Delayed
:
3259 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3260 // are we waiting for interested parties to acknowledge?
3261 if (priv
->head_note_pendingAcks
!= 0 )
3263 // yes, go through the list of interested drivers
3264 nextObject
= priv
->interestedDrivers
->firstInList();
3265 // and check each one
3266 while ( nextObject
!= NULL
)
3268 if ( nextObject
->timer
> 0 )
3270 nextObject
->timer
-= 1;
3271 // this one should have acked by now
3272 if ( nextObject
->timer
== 0 )
3274 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogIntDriverTardy
,0,0);
3275 //kprintf("interested driver tardy: %s\n",nextObject->whatObject->getName());
3276 priv
->head_note_pendingAcks
-= 1;
3279 nextObject
= priv
->interestedDrivers
->nextInList(nextObject
);
3282 // is that the last?
3283 if ( priv
->head_note_pendingAcks
== 0 )
3285 IOUnlock(priv
->our_lock
);
3286 // yes, we can continue
3289 // no, set timer again
3291 IOUnlock(priv
->our_lock
);
3294 IOUnlock(priv
->our_lock
);
3298 // apps didn't respond to parent-down notification
3299 case kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate
:
3300 IOUnlock(priv
->our_lock
);
3301 IOLockLock(priv
->flags_lock
);
3302 if (pm_vars
->responseFlags
)
3304 // get rid of this stuff
3305 pm_vars
->responseFlags
->release();
3306 pm_vars
->responseFlags
= NULL
;
3308 IOLockUnlock(priv
->flags_lock
);
3309 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,5);
3310 // carry on with the change
3311 ParentDownTellPriorityClientsPowerDown_Delayed();
3314 case kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
:
3315 IOUnlock(priv
->our_lock
);
3316 IOLockLock(priv
->flags_lock
);
3317 if (pm_vars
->responseFlags
)
3319 // get rid of this stuff
3320 pm_vars
->responseFlags
->release();
3321 pm_vars
->responseFlags
= NULL
;
3323 IOLockUnlock(priv
->flags_lock
);
3324 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,1);
3325 // carry on with the change
3326 ParentDownNotifyInterestedDriversWillChange_Delayed();
3329 case kIOPM_OurChangeTellClientsPowerDown
:
3330 // apps didn't respond to our power-down request
3331 IOUnlock(priv
->our_lock
);
3332 IOLockLock(priv
->flags_lock
);
3333 if (pm_vars
->responseFlags
)
3335 // get rid of this stuff
3336 pm_vars
->responseFlags
->release();
3337 pm_vars
->responseFlags
= NULL
;
3339 IOLockUnlock(priv
->flags_lock
);
3340 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,2);
3341 // rescind the request
3342 tellNoChangeDown(priv
->head_note_state
);
3343 // mark the change note un-actioned
3344 priv
->head_note_flags
|= IOPMNotDone
;
3349 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
3350 // clients didn't respond to our power-down note
3351 IOUnlock(priv
->our_lock
);
3352 IOLockLock(priv
->flags_lock
);
3353 if (pm_vars
->responseFlags
)
3355 // get rid of this stuff
3356 pm_vars
->responseFlags
->release();
3357 pm_vars
->responseFlags
= NULL
;
3359 IOLockUnlock(priv
->flags_lock
);
3360 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,4);
3361 // carry on with the change
3362 OurChangeTellPriorityClientsPowerDown();
3365 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
3366 // apps didn't respond to our power-down notification
3367 IOUnlock(priv
->our_lock
);
3368 IOLockLock(priv
->flags_lock
);
3369 if (pm_vars
->responseFlags
)
3371 // get rid of this stuff
3372 pm_vars
->responseFlags
->release();
3373 pm_vars
->responseFlags
= NULL
;
3375 IOLockUnlock(priv
->flags_lock
);
3376 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,3);
3377 // carry on with the change
3378 OurChangeNotifyInterestedDriversWillChange();
3382 // not waiting for acks
3383 IOUnlock(priv
->our_lock
);
3389 //*********************************************************************************
3392 //*********************************************************************************
3394 void IOService::start_ack_timer ( void )
3396 AbsoluteTime deadline
;
3398 clock_interval_to_deadline(ACK_TIMER_PERIOD
, kNanosecondScale
, &deadline
);
3400 thread_call_enter_delayed(priv
->ackTimer
, deadline
);
3404 //*********************************************************************************
3407 //*********************************************************************************
3409 void IOService::stop_ack_timer ( void )
3411 thread_call_cancel(priv
->ackTimer
);
3415 //*********************************************************************************
3416 // c-language timer expiration functions
3418 //*********************************************************************************
3420 static void ack_timer_expired ( thread_call_param_t us
)
3422 ((IOService
*)us
)->ack_timer_ticked();
3426 static void settle_timer_expired ( thread_call_param_t us
)
3428 ((IOService
*)us
)->settleTimerExpired();
3432 //*********************************************************************************
3433 // add_child_to_active_change
3435 // A child has just registered with us. If there is
3436 // currently a change in progress, get the new party involved: if we
3437 // have notified all parties and are waiting for acks, notify the new
3439 //*********************************************************************************
3441 IOReturn
IOService::add_child_to_active_change ( IOPowerConnection
* newObject
)
3443 if (! acquire_lock() )
3448 switch (priv
->machine_state
)
3450 case kIOPM_OurChangeSetPowerState
:
3451 case kIOPM_ParentDownSetPowerState_Delayed
:
3452 case kIOPM_ParentUpSetPowerState_Delayed
:
3453 // one for this child and one to prevent
3454 priv
->head_note_pendingAcks
+= 2;
3455 // incoming acks from changing our state
3456 IOUnlock(priv
->our_lock
);
3457 notifyChild(newObject
, true);
3458 if (! acquire_lock() )
3461 --priv
->head_note_pendingAcks
;
3464 // are we still waiting for acks?
3465 if ( --priv
->head_note_pendingAcks
== 0 )
3467 // no, stop the timer
3469 IOUnlock(priv
->our_lock
);
3471 // and now we can continue
3476 case kIOPM_OurChangeFinish
:
3477 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3478 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3479 // one for this child and one to prevent
3480 priv
->head_note_pendingAcks
+= 2;
3481 // incoming acks from changing our state
3482 IOUnlock(priv
->our_lock
);
3483 notifyChild(newObject
, false);
3484 if (! acquire_lock() )
3487 --priv
->head_note_pendingAcks
;
3490 // are we still waiting for acks?
3491 if ( --priv
->head_note_pendingAcks
== 0 )
3493 // no, stop the timer
3495 IOUnlock(priv
->our_lock
);
3497 // and now we can continue
3503 IOUnlock(priv
->our_lock
);
3508 //*********************************************************************************
3509 // add_driver_to_active_change
3511 // An interested driver has just registered with us. If there is
3512 // currently a change in progress, get the new party involved: if we
3513 // have notified all parties and are waiting for acks, notify the new
3515 //*********************************************************************************
3517 IOReturn
IOService::add_driver_to_active_change ( IOPMinformee
* newObject
)
3519 if (! acquire_lock() )
3524 switch (priv
->machine_state
) {
3525 case kIOPM_OurChangeSetPowerState
:
3526 case kIOPM_ParentDownSetPowerState_Delayed
:
3527 case kIOPM_ParentUpSetPowerState_Delayed
:
3528 // one for this driver and one to prevent
3529 priv
->head_note_pendingAcks
+= 2;
3530 // incoming acks from changing our state
3531 IOUnlock(priv
->our_lock
);
3532 // inform the driver
3533 inform(newObject
, true);
3534 if (! acquire_lock() )
3537 --priv
->head_note_pendingAcks
;
3540 // are we still waiting for acks?
3541 if ( --priv
->head_note_pendingAcks
== 0 )
3543 // no, stop the timer
3545 IOUnlock(priv
->our_lock
);
3547 // and now we can continue
3552 case kIOPM_OurChangeFinish
:
3553 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3554 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3555 // one for this driver and one to prevent
3556 priv
->head_note_pendingAcks
+= 2;
3557 // incoming acks from changing our state
3558 IOUnlock(priv
->our_lock
);
3559 // inform the driver
3560 inform(newObject
, false);
3561 if (! acquire_lock() ) {
3563 --priv
->head_note_pendingAcks
;
3566 // are we still waiting for acks?
3567 if ( --priv
->head_note_pendingAcks
== 0 ) {
3568 // no, stop the timer
3570 IOUnlock(priv
->our_lock
);
3572 // and now we can continue
3578 IOUnlock(priv
->our_lock
);
3583 //*********************************************************************************
3584 // start_parent_change
3586 // Here we begin the processing of a change note initiated by our parent
3587 // which is at the head of the queue.
3589 // It is possible for the change to be processed to completion and removed from the queue.
3590 // There are several possible interruptions to the processing, though, and they are:
3591 // we may have to wait for interested parties to acknowledge our pre-change notification,
3592 // we may have to wait for our controlling driver to change the hardware power state,
3593 // there may be a settling time after changing the hardware power state,
3594 // we may have to wait for interested parties to acknowledge our post-change notification,
3595 // we may have to wait for the acknowledgement timer expiration to substitute for the
3596 // acknowledgement from a failing driver.
3597 //*********************************************************************************
3599 IOReturn
IOService::start_parent_change ( unsigned long queue_head
)
3601 priv
->head_note
= queue_head
;
3602 priv
->head_note_flags
= priv
-> changeList
->changeNote
[priv
->head_note
].flags
;
3603 priv
->head_note_state
= priv
->changeList
->changeNote
[priv
->head_note
].newStateNumber
;
3604 priv
->imminentState
= priv
->head_note_state
;
3605 priv
->head_note_outputFlags
= priv
->changeList
->changeNote
[priv
->head_note
].outputPowerCharacter
;
3606 priv
->head_note_domainState
= priv
->changeList
->changeNote
[priv
->head_note
].domainState
;
3607 priv
->head_note_parent
= priv
->changeList
->changeNote
[priv
->head_note
].parent
;
3608 priv
->head_note_capabilityFlags
= priv
->changeList
->changeNote
[priv
->head_note
].capabilityFlags
;
3610 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartParentChange
,
3611 (unsigned long)priv
->head_note_state
,(unsigned long)pm_vars
->myCurrentState
);
3613 // if we need something and haven't told the parent, do so
3614 ask_parent( priv
->ourDesiredPowerState
);
3616 // power domain is lowering
3617 if ( priv
->head_note_state
< pm_vars
->myCurrentState
)
3619 setParentInfo(priv
->changeList
->changeNote
[priv
->head_note
].singleParentState
,priv
->head_note_parent
);
3620 priv
->initial_change
= false;
3621 // tell apps and kernel clients
3622 priv
->machine_state
= kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate
;
3624 // are we waiting for responses?
3625 if ( tellChangeDown1(priv
->head_note_state
) )
3627 // no, notify priority clients
3628 return ParentDownTellPriorityClientsPowerDown_Immediate();
3631 return IOPMWillAckLater
;
3634 // parent is raising power, we may or may not
3635 if ( priv
->head_note_state
> pm_vars
->myCurrentState
)
3637 if ( priv
->ourDesiredPowerState
> pm_vars
->myCurrentState
)
3639 if ( priv
->ourDesiredPowerState
< priv
->head_note_state
)
3641 // we do, but not all the way
3642 priv
->head_note_state
= priv
->ourDesiredPowerState
;
3643 priv
->imminentState
= priv
->head_note_state
;
3644 priv
->head_note_outputFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].outputPowerCharacter
;
3645 priv
->head_note_capabilityFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].capabilityFlags
;
3646 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAmendParentChange
,(unsigned long)priv
->head_note_state
,0);
3650 priv
->head_note_state
= pm_vars
->myCurrentState
;
3651 priv
->imminentState
= priv
->head_note_state
;
3652 priv
->head_note_outputFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].outputPowerCharacter
;
3653 priv
->head_note_capabilityFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].capabilityFlags
;
3654 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAmendParentChange
,(unsigned long)priv
->head_note_state
,0);
3658 if ( (priv
->head_note_state
> pm_vars
->myCurrentState
) &&
3659 (priv
->head_note_flags
& IOPMDomainDidChange
) )
3662 priv
->initial_change
= false;
3663 priv
->machine_state
= kIOPM_ParentUpSetPowerState_Delayed
;
3664 if ( notifyAll(true) == IOPMAckImplied
) {
3665 return ParentUpSetPowerState_Immediate();
3667 // they didn't all ack
3668 return IOPMWillAckLater
;
3672 // a null change or power will go up
3673 return IOPMAckImplied
;
3677 //*********************************************************************************
3680 // Here we begin the processing of a change note initiated by us
3681 // which is at the head of the queue.
3683 // It is possible for the change to be processed to completion and removed from the queue.
3684 // There are several possible interruptions to the processing, though, and they are:
3685 // we may have to wait for interested parties to acknowledge our pre-change notification,
3686 // changes initiated by the parent will wait in the middle for powerStateDidChange,
3687 // we may have to wait for our controlling driver to change the hardware power state,
3688 // there may be a settling time after changing the hardware power state,
3689 // we may have to wait for interested parties to acknowledge our post-change notification,
3690 // we may have to wait for the acknowledgement timer expiration to substitute for the
3691 // acknowledgement from a failing driver.
3692 //*********************************************************************************
3694 void IOService::start_our_change ( unsigned long queue_head
)
3696 priv
->head_note
= queue_head
;
3697 priv
->head_note_flags
= priv
->changeList
->changeNote
[priv
->head_note
].flags
;
3698 priv
->head_note_state
= priv
->changeList
->changeNote
[priv
->head_note
].newStateNumber
;
3699 priv
->imminentState
= priv
->head_note_state
;
3700 priv
->head_note_outputFlags
= priv
->changeList
->changeNote
[priv
->head_note
].outputPowerCharacter
;
3701 priv
->head_note_capabilityFlags
= priv
->changeList
->changeNote
[priv
->head_note
].capabilityFlags
;
3703 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartDeviceChange
,
3704 (unsigned long)priv
->head_note_state
,(unsigned long)pm_vars
->myCurrentState
);
3706 // can our driver switch to the new state?
3707 if ( priv
->head_note_capabilityFlags
& IOPMNotAttainable
)
3709 // no, ask the parent to do it then
3710 if ( ! priv
->we_are_root
)
3712 ask_parent(priv
->head_note_state
);
3714 // mark the change note un-actioned
3715 priv
-> head_note_flags
|= IOPMNotDone
;
3721 // is there enough power in the domain?
3722 if ( (pm_vars
->maxCapability
< priv
->head_note_state
) && (! priv
->we_are_root
) )
3724 // no, ask the parent to raise it
3725 if ( ! priv
->we_are_root
)
3727 ask_parent(priv
->head_note_state
);
3729 // no, mark the change note un-actioned
3730 priv
->head_note_flags
|= IOPMNotDone
;
3732 // till the parent raises power
3737 if ( ! priv
->initial_change
)
3739 if ( priv
->head_note_state
== pm_vars
->myCurrentState
)
3741 // we initiated a null change; forget it
3746 priv
->initial_change
= false;
3749 if ( priv
->head_note_state
< pm_vars
->myCurrentState
)
3751 // yes, in case we have to wait for acks
3752 priv
->machine_state
= kIOPM_OurChangeTellClientsPowerDown
;
3753 pm_vars
->doNotPowerDown
= false;
3755 // ask apps and kernel clients if we can drop power
3756 pm_vars
->outofbandparameter
= kNotifyApps
;
3757 if ( askChangeDown(priv
->head_note_state
) )
3759 // don't have to wait, did any clients veto?
3760 if ( pm_vars
->doNotPowerDown
)
3762 // yes, rescind the warning
3763 tellNoChangeDown(priv
->head_note_state
);
3764 // mark the change note un-actioned
3765 priv
-> head_note_flags
|= IOPMNotDone
;
3769 // no, tell'em we're dropping power
3770 OurChangeTellClientsPowerDown();
3774 // we are raising power
3775 if ( ! priv
->we_are_root
)
3777 // if this changes our power requirement, tell the parent
3778 ask_parent(priv
->head_note_state
);
3780 // in case they don't all ack
3781 priv
->machine_state
= kIOPM_OurChangeSetPowerState
;
3783 // notify interested drivers and children
3784 if ( notifyAll(true) == IOPMAckImplied
)
3786 OurChangeSetPowerState();
3792 //*********************************************************************************
3795 // Call the power domain parent to ask for a higher power state in the domain
3796 // or to suggest a lower power state.
3797 //*********************************************************************************
3799 IOReturn
IOService::ask_parent ( unsigned long requestedState
)
3803 IOPowerConnection
*connection
;
3805 unsigned long ourRequest
= pm_vars
->thePowerStates
[requestedState
].inputPowerRequirement
;
3807 if ( pm_vars
->thePowerStates
[requestedState
].capabilityFlags
& (kIOPMChildClamp
| kIOPMPreventIdleSleep
) )
3809 ourRequest
|= kIOPMPreventIdleSleep
;
3811 if ( pm_vars
->thePowerStates
[requestedState
].capabilityFlags
& (kIOPMChildClamp2
| kIOPMPreventSystemSleep
) )
3813 ourRequest
|= kIOPMPreventSystemSleep
;
3816 // is this a new desire?
3817 if ( priv
->previousRequest
== ourRequest
)
3819 // no, the parent knows already, just return
3823 if ( priv
->we_are_root
)
3827 priv
->previousRequest
= ourRequest
;
3829 iter
= getParentIterator(gIOPowerPlane
);
3833 while ( (next
= iter
->getNextObject()) )
3835 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
3837 parent
= (IOService
*)connection
->copyParentEntry(gIOPowerPlane
);
3839 if ( parent
->requestPowerDomainState(ourRequest
,connection
,IOPMLowestState
)!= IOPMNoErr
)
3841 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRequestDenied
,
3842 (unsigned long)priv
->previousRequest
,0);
3855 //*********************************************************************************
3858 // Call the controlling driver and have it change the power state of the
3859 // hardware. If it returns IOPMAckImplied, the change is complete, and
3860 // we return IOPMAckImplied. Otherwise, it will ack when the change
3861 // is done; we return IOPMWillAckLater.
3862 //*********************************************************************************
3863 IOReturn
IOService::instruct_driver ( unsigned long newState
)
3867 // can our driver switch to the desired state?
3868 if ( pm_vars
->thePowerStates
[newState
].capabilityFlags
& IOPMNotAttainable
)
3871 return IOPMAckImplied
;
3874 priv
->driver_timer
= -1;
3877 OUR_PMLog( kPMLogProgramHardware
, (UInt32
) this, newState
);
3878 delay
= pm_vars
->theControllingDriver
->setPowerState( newState
,this );
3879 OUR_PMLog((UInt32
) -kPMLogProgramHardware
, (UInt32
) this, (UInt32
) delay
);
3882 if ( delay
== IOPMAckImplied
)
3884 priv
->driver_timer
= 0;
3885 return IOPMAckImplied
;
3888 // it acked behind our back
3889 if ( priv
->driver_timer
== 0 )
3891 return IOPMAckImplied
;
3897 return IOPMAckImplied
;
3901 priv
->driver_timer
= (delay
/ ( ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
3902 return IOPMWillAckLater
;
3906 //*********************************************************************************
3909 // We are acquiring the lock we use to protect our queue head from
3910 // simutaneous access by a thread which calls acknowledgePowerStateChange
3911 // or acknowledgeSetPowerState and the ack timer expiration thread.
3912 // Return TRUE if we acquire the lock, and the queue head didn't change
3913 // while we were acquiring the lock (and maybe blocked).
3914 // If there is no queue head, or it changes while we are blocked,
3915 // return FALSE with the lock unlocked.
3916 //*********************************************************************************
3918 bool IOService::acquire_lock ( void )
3920 long current_change_note
;
3922 current_change_note
= priv
->head_note
;
3923 if ( current_change_note
== -1 ) {
3927 IOTakeLock(priv
->our_lock
);
3928 if ( current_change_note
== priv
->head_note
)
3932 // we blocked and something changed radically
3933 // so there's nothing to do any more
3934 IOUnlock(priv
->our_lock
);
3940 //*********************************************************************************
3943 // Ask registered applications and kernel clients if we can change to a lower
3946 // Subclass can override this to send a different message type. Parameter is
3947 // the destination state number.
3949 // Return true if we don't have to wait for acknowledgements
3950 //*********************************************************************************
3952 bool IOService::askChangeDown ( unsigned long stateNum
)
3954 return tellClientsWithResponse(kIOMessageCanDevicePowerOff
);
3958 //*********************************************************************************
3961 // Notify registered applications and kernel clients that we are definitely
3964 // Return true if we don't have to wait for acknowledgements
3965 //*********************************************************************************
3967 bool IOService::tellChangeDown1 ( unsigned long stateNum
)
3969 pm_vars
->outofbandparameter
= kNotifyApps
;
3970 return tellChangeDown(stateNum
);
3974 //*********************************************************************************
3977 // Notify priority clients that we are definitely dropping power.
3979 // Return true if we don't have to wait for acknowledgements
3980 //*********************************************************************************
3982 bool IOService::tellChangeDown2 ( unsigned long stateNum
)
3984 pm_vars
->outofbandparameter
= kNotifyPriority
;
3985 return tellChangeDown(stateNum
);
3989 //*********************************************************************************
3992 // Notify registered applications and kernel clients that we are definitely
3995 // Subclass can override this to send a different message type. Parameter is
3996 // the destination state number.
3998 // Return true if we don't have to wait for acknowledgements
3999 //*********************************************************************************
4001 bool IOService::tellChangeDown ( unsigned long stateNum
)
4003 return tellClientsWithResponse(kIOMessageDeviceWillPowerOff
);
4007 //*********************************************************************************
4008 // tellClientsWithResponse
4010 // Notify registered applications and kernel clients that we are definitely
4013 // Return true if we don't have to wait for acknowledgements
4014 //*********************************************************************************
4016 bool IOService::tellClientsWithResponse ( int messageType
)
4018 struct context theContext
;
4019 AbsoluteTime deadline
;
4022 pm_vars
->responseFlags
= OSArray::withCapacity( 1 );
4023 pm_vars
->serialNumber
+= 1;
4025 theContext
.responseFlags
= pm_vars
->responseFlags
;
4026 theContext
.serialNumber
= pm_vars
->serialNumber
;
4027 theContext
.flags_lock
= priv
->flags_lock
;
4028 theContext
.counter
= 1;
4029 theContext
.msgType
= messageType
;
4030 theContext
.us
= this;
4031 theContext
.maxTimeRequested
= 0;
4032 theContext
.stateNumber
= priv
->head_note_state
;
4033 theContext
.stateFlags
= priv
->head_note_capabilityFlags
;
4035 IOLockLock(priv
->flags_lock
);
4037 // position zero is false to
4038 // prevent allowCancelCommon from succeeding
4039 aBool
= OSBoolean::withBoolean(false);
4040 theContext
.responseFlags
->setObject(0,aBool
);
4042 IOLockUnlock(priv
->flags_lock
);
4044 switch ( pm_vars
->outofbandparameter
) {
4046 applyToInterested(gIOAppPowerStateInterest
,tellAppWithResponse
,(void *)&theContext
);
4047 applyToInterested(gIOGeneralInterest
,tellClientWithResponse
,(void *)&theContext
);
4049 case kNotifyPriority
:
4050 applyToInterested(gIOPriorityPowerStateInterest
,tellClientWithResponse
,(void *)&theContext
);
4054 if (! acquire_lock() )
4058 IOLockLock(priv
->flags_lock
);
4059 // now fix position zero
4060 aBool
= OSBoolean::withBoolean(true);
4061 theContext
.responseFlags
->replaceObject(0,aBool
);
4063 IOLockUnlock(priv
->flags_lock
);
4065 // do we have to wait for somebody?
4066 if ( ! checkForDone() )
4068 // yes, start the ackTimer
4069 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,theContext
.maxTimeRequested
,0);
4070 clock_interval_to_deadline(theContext
.maxTimeRequested
/ 1000, kMillisecondScale
, &deadline
);
4072 thread_call_enter_delayed(priv
->ackTimer
, deadline
);
4074 IOUnlock(priv
->our_lock
);
4078 IOUnlock(priv
->our_lock
);
4079 IOLockLock(priv
->flags_lock
);
4081 // everybody responded
4082 pm_vars
->responseFlags
->release();
4083 pm_vars
->responseFlags
= NULL
;
4084 IOLockUnlock(priv
->flags_lock
);
4090 //*********************************************************************************
4091 // tellAppWithResponse
4093 // We send a message to an application, and we expect a response, so we compute a
4094 // cookie we can identify the response with.
4095 //*********************************************************************************
4096 void tellAppWithResponse ( OSObject
* object
, void * context
)
4098 struct context
*theContext
= (struct context
*)context
;
4100 IOPMprot
*pm_vars
= theContext
->us
->pm_vars
;
4102 if( OSDynamicCast( IOService
, object
) )
4104 // Automatically 'ack' in kernel clients
4105 IOLockLock(theContext
->flags_lock
);
4106 aBool
= OSBoolean::withBoolean(true);
4107 theContext
->responseFlags
->setObject(theContext
->counter
,aBool
);
4109 IOLockUnlock(theContext
->flags_lock
);
4111 const char *who
= ((IOService
*) object
)->getName();
4112 pm_vars
->thePlatform
->PMLog(who
,
4113 kPMLogClientAcknowledge
, theContext
->msgType
, * (UInt32
*) object
);
4115 UInt32 refcon
= ((theContext
->serialNumber
& 0xFFFF)<<16)
4116 + (theContext
->counter
& 0xFFFF);
4117 IOLockLock(theContext
->flags_lock
);
4118 aBool
= OSBoolean::withBoolean(false);
4119 theContext
->responseFlags
->setObject(theContext
->counter
,aBool
);
4121 IOLockUnlock(theContext
->flags_lock
);
4123 OUR_PMLog(kPMLogAppNotify
, theContext
->msgType
, refcon
);
4124 theContext
->us
->messageClient(theContext
->msgType
,object
,(void *)refcon
);
4125 if ( theContext
->maxTimeRequested
< k30seconds
)
4127 theContext
->maxTimeRequested
= k30seconds
;
4130 theContext
->counter
+= 1;
4133 //*********************************************************************************
4134 // tellClientWithResponse
4136 // We send a message to an in-kernel client, and we expect a response, so we compute a
4137 // cookie we can identify the response with.
4138 // If it doesn't understand the notification (it is not power-management savvy)
4139 // we won't wait for it to prepare for sleep. If it tells us via a return code
4140 // in the passed struct that it is currently ready, we won't wait for it to prepare.
4141 // If it tells us via the return code in the struct that it does need time, we will chill.
4142 //*********************************************************************************
4143 void tellClientWithResponse ( OSObject
* object
, void * context
)
4145 struct context
*theContext
= (struct context
*)context
;
4146 IOPowerStateChangeNotification notify
;
4152 refcon
= ((theContext
->serialNumber
& 0xFFFF)<<16) + (theContext
->counter
& 0xFFFF);
4153 IOLockLock(theContext
->flags_lock
);
4154 aBool
= OSBoolean::withBoolean(false);
4155 theContext
->responseFlags
->setObject(theContext
->counter
,aBool
);
4157 IOLockUnlock(theContext
->flags_lock
);
4159 IOPMprot
*pm_vars
= theContext
->us
->pm_vars
;
4160 if (gIOKitDebug
& kIOLogPower
) {
4161 OUR_PMLog(kPMLogClientNotify
, refcon
, (UInt32
) theContext
->msgType
);
4162 if (OSDynamicCast(IOService
, object
)) {
4163 const char *who
= ((IOService
*) object
)->getName();
4164 pm_vars
->thePlatform
->PMLog(who
,
4165 kPMLogClientNotify
, * (UInt32
*) object
, (UInt32
) object
);
4166 } else if (OSDynamicCast(_IOServiceInterestNotifier
, object
)) {
4167 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
4168 OUR_PMLog(kPMLogClientNotify
, (UInt32
) n
->handler
, 0);
4172 notify
.powerRef
= (void *)refcon
;
4173 notify
.returnValue
= 0;
4174 notify
.stateNumber
= theContext
->stateNumber
;
4175 notify
.stateFlags
= theContext
->stateFlags
;
4176 retCode
= theContext
->us
->messageClient(theContext
->msgType
,object
,(void *)¬ify
);
4177 if ( retCode
== kIOReturnSuccess
)
4179 if ( notify
.returnValue
== 0 )
4181 // client doesn't want time to respond
4182 IOLockLock(theContext
->flags_lock
);
4183 aBool
= OSBoolean::withBoolean(true);
4184 // so set its flag true
4185 theContext
->responseFlags
->replaceObject(theContext
->counter
,aBool
);
4187 IOLockUnlock(theContext
->flags_lock
);
4188 OUR_PMLog(kPMLogClientAcknowledge
, refcon
, (UInt32
) object
);
4190 IOLockLock(theContext
->flags_lock
);
4192 // it does want time, and it hasn't responded yet
4193 theFlag
= theContext
->responseFlags
->getObject(theContext
->counter
);
4196 if ( ((OSBoolean
*)theFlag
)->isFalse() )
4198 // so note its time requirement
4199 if ( theContext
->maxTimeRequested
< notify
.returnValue
)
4201 theContext
->maxTimeRequested
= notify
.returnValue
;
4205 IOLockUnlock(theContext
->flags_lock
);
4208 OUR_PMLog(kPMLogClientAcknowledge
, refcon
, 0);
4209 // not a client of ours
4210 IOLockLock(theContext
->flags_lock
);
4211 // so we won't be waiting for response
4212 aBool
= OSBoolean::withBoolean(true);
4213 theContext
->responseFlags
->replaceObject(theContext
->counter
,aBool
);
4215 IOLockUnlock(theContext
->flags_lock
);
4217 theContext
->counter
+= 1;
4221 //*********************************************************************************
4224 // Notify registered applications and kernel clients that we are not
4227 // Subclass can override this to send a different message type. Parameter is
4228 // the aborted destination state number.
4229 //*********************************************************************************
4231 void IOService::tellNoChangeDown ( unsigned long )
4233 return tellClients(kIOMessageDeviceWillNotPowerOff
);
4237 //*********************************************************************************
4240 // Notify registered applications and kernel clients that we are raising power.
4242 // Subclass can override this to send a different message type. Parameter is
4243 // the aborted destination state number.
4244 //*********************************************************************************
4246 void IOService::tellChangeUp ( unsigned long )
4248 return tellClients(kIOMessageDeviceHasPoweredOn
);
4252 //*********************************************************************************
4255 // Notify registered applications and kernel clients of something.
4256 //*********************************************************************************
4258 void IOService::tellClients ( int messageType
)
4260 struct context theContext
;
4262 theContext
.msgType
= messageType
;
4263 theContext
.us
= this;
4264 theContext
.stateNumber
= priv
->head_note_state
;
4265 theContext
.stateFlags
= priv
->head_note_capabilityFlags
;
4267 applyToInterested(gIOAppPowerStateInterest
,tellClient
,(void *)&theContext
);
4268 applyToInterested(gIOGeneralInterest
,tellClient
,(void *)&theContext
);
4272 //*********************************************************************************
4275 // Notify a registered application or kernel client of something.
4276 //*********************************************************************************
4277 void tellClient ( OSObject
* object
, void * context
)
4279 struct context
*theContext
= (struct context
*)context
;
4280 IOPowerStateChangeNotification notify
;
4282 notify
.powerRef
= (void *) 0;
4283 notify
.returnValue
= 0;
4284 notify
.stateNumber
= theContext
->stateNumber
;
4285 notify
.stateFlags
= theContext
->stateFlags
;
4287 theContext
->us
->messageClient(theContext
->msgType
,object
, ¬ify
);
4291 // **********************************************************************************
4294 // **********************************************************************************
4295 bool IOService::checkForDone ( void )
4300 IOLockLock(priv
->flags_lock
);
4301 if ( pm_vars
->responseFlags
== NULL
)
4303 IOLockUnlock(priv
->flags_lock
);
4307 for ( i
= 0; ; i
++ )
4309 theFlag
= pm_vars
->responseFlags
->getObject(i
);
4310 if ( theFlag
== NULL
)
4314 if ( ((OSBoolean
*)theFlag
)->isFalse() )
4316 IOLockUnlock(priv
->flags_lock
);
4320 IOLockUnlock(priv
->flags_lock
);
4325 // **********************************************************************************
4328 // **********************************************************************************
4329 bool IOService::responseValid ( unsigned long x
)
4331 UInt16 serialComponent
;
4332 UInt16 ordinalComponent
;
4334 unsigned long refcon
= (unsigned long)x
;
4337 serialComponent
= (refcon
>>16) & 0xFFFF;
4338 ordinalComponent
= refcon
& 0xFFFF;
4340 if ( serialComponent
!= pm_vars
->serialNumber
)
4345 IOLockLock(priv
->flags_lock
);
4346 if ( pm_vars
->responseFlags
== NULL
)
4348 IOLockUnlock(priv
->flags_lock
);
4352 theFlag
= pm_vars
->responseFlags
->getObject(ordinalComponent
);
4356 IOLockUnlock(priv
->flags_lock
);
4360 if ( ((OSBoolean
*)theFlag
)->isFalse() )
4362 aBool
= OSBoolean::withBoolean(true);
4363 pm_vars
->responseFlags
->replaceObject(ordinalComponent
,aBool
);
4367 IOLockUnlock(priv
->flags_lock
);
4372 // **********************************************************************************
4375 // Our power state is about to lower, and we have notified applications
4376 // and kernel clients, and one of them has acknowledged. If this is the last to do
4377 // so, and all acknowledgements are positive, we continue with the power change.
4379 // We serialize this processing with timer expiration with a command gate on the
4380 // power management workloop, which the timer expiration is command gated to as well.
4381 // **********************************************************************************
4382 IOReturn
IOService::allowPowerChange ( unsigned long refcon
)
4384 if ( ! initialized
)
4387 return kIOReturnSuccess
;
4390 return pm_vars
->PMcommandGate
->runAction(serializedAllowPowerChange
,(void *)refcon
);
4394 IOReturn
serializedAllowPowerChange ( OSObject
*owner
, void * refcon
, void *, void *, void *)
4396 return ((IOService
*)owner
)->serializedAllowPowerChange2((unsigned long)refcon
);
4399 IOReturn
IOService::serializedAllowPowerChange2 ( unsigned long refcon
)
4402 if ( ! responseValid(refcon
) )
4404 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr5
,refcon
,0);
4406 return kIOReturnSuccess
;
4408 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientAcknowledge
,refcon
,0);
4410 return allowCancelCommon();
4414 // **********************************************************************************
4415 // cancelPowerChange
4417 // Our power state is about to lower, and we have notified applications
4418 // and kernel clients, and one of them has vetoed the change. If this is the last
4419 // client to respond, we abandon the power change.
4421 // We serialize this processing with timer expiration with a command gate on the
4422 // power management workloop, which the timer expiration is command gated to as well.
4423 // **********************************************************************************
4424 IOReturn
IOService::cancelPowerChange ( unsigned long refcon
)
4426 if ( ! initialized
)
4429 return kIOReturnSuccess
;
4432 return pm_vars
->PMcommandGate
->runAction(serializedCancelPowerChange
,(void *)refcon
);
4436 IOReturn
serializedCancelPowerChange ( OSObject
*owner
, void * refcon
, void *, void *, void *)
4438 return ((IOService
*)owner
)->serializedCancelPowerChange2((unsigned long)refcon
);
4441 IOReturn
IOService::serializedCancelPowerChange2 ( unsigned long refcon
)
4444 if ( ! responseValid(refcon
) )
4446 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr5
,refcon
,0);
4448 return kIOReturnSuccess
;
4450 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientCancel
,refcon
,0);
4452 pm_vars
->doNotPowerDown
= true;
4454 return allowCancelCommon();
4458 // **********************************************************************************
4459 // allowCancelCommon
4461 // **********************************************************************************
4462 IOReturn
IOService::allowCancelCommon ( void )
4464 if (! acquire_lock() )
4466 return kIOReturnSuccess
;
4469 // is this the last response?
4470 if ( checkForDone() )
4472 // yes, stop the timer
4474 IOUnlock(priv
->our_lock
);
4475 IOLockLock(priv
->flags_lock
);
4476 if ( pm_vars
->responseFlags
)
4478 pm_vars
->responseFlags
->release();
4479 pm_vars
->responseFlags
= NULL
;
4481 IOLockUnlock(priv
->flags_lock
);
4482 switch (priv
->machine_state
) {
4483 case kIOPM_OurChangeTellClientsPowerDown
:
4484 // our change, was it vetoed?
4485 if ( ! pm_vars
->doNotPowerDown
)
4487 // no, we can continue
4488 OurChangeTellClientsPowerDown();
4490 // yes, rescind the warning
4491 tellNoChangeDown(priv
->head_note_state
);
4492 // mark the change note un-actioned
4493 priv
->head_note_flags
|= IOPMNotDone
;
4499 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
4500 OurChangeTellPriorityClientsPowerDown();
4502 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
4503 // our change, continue
4504 OurChangeNotifyInterestedDriversWillChange();
4506 case kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate
:
4507 // parent change, continue
4508 ParentDownTellPriorityClientsPowerDown_Delayed();
4510 case kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
:
4511 // parent change, continue
4512 ParentDownNotifyInterestedDriversWillChange_Delayed();
4517 IOUnlock(priv
->our_lock
);
4520 return kIOReturnSuccess
;
4525 //*********************************************************************************
4526 // c_PM_clamp_Timer_Expired (C Func)
4528 // Called when our clamp timer expires...we will call the object method.
4529 //*********************************************************************************
4531 static void c_PM_Clamp_Timer_Expired (OSObject
* client
, IOTimerEventSource
*)
4534 ((IOService
*)client
)->PM_Clamp_Timer_Expired ();
4539 //*********************************************************************************
4540 // PM_Clamp_Timer_Expired
4542 // called when clamp timer expires...set power state to 0.
4543 //*********************************************************************************
4545 void IOService::PM_Clamp_Timer_Expired (void)
4548 if ( ! initialized
)
4554 changePowerStateToPriv (0);
4558 //******************************************************************************
4561 // Set to highest available power state for a minimum of duration milliseconds
4562 //******************************************************************************
4564 #define kFiveMinutesInNanoSeconds (300 * NSEC_PER_SEC)
4566 void IOService::clampPowerOn (unsigned long duration
)
4569 changePowerStateToPriv (pm_vars
->theNumberOfPowerStates
-1);
4571 if ( priv
->clampTimerEventSrc
== NULL
) {
4572 priv
->clampTimerEventSrc
= IOTimerEventSource::timerEventSource(this,
4573 c_PM_Clamp_Timer_Expired
);
4575 IOWorkLoop
* workLoop
= getPMworkloop ();
4577 if ( !priv
->clampTimerEventSrc
|| !workLoop
||
4578 ( workLoop
->addEventSource( priv
->clampTimerEventSrc
) != kIOReturnSuccess
) ) {
4583 priv
->clampTimerEventSrc
->setTimeout(300*USEC_PER_SEC
, USEC_PER_SEC
);
4587 //*********************************************************************************
4590 // Does nothing here. This should be implemented in a subclass driver.
4591 //*********************************************************************************
4593 IOReturn
IOService::setPowerState ( unsigned long powerStateOrdinal
, IOService
* whatDevice
)
4599 //*********************************************************************************
4600 // maxCapabilityForDomainState
4602 // Finds the highest power state in the array whose input power
4603 // requirement is equal to the input parameter. Where a more intelligent
4604 // decision is possible, override this in the subclassed driver.
4605 //*********************************************************************************
4607 unsigned long IOService::maxCapabilityForDomainState ( IOPMPowerFlags domainState
)
4611 if (pm_vars
->theNumberOfPowerStates
== 0 )
4615 for ( i
= (pm_vars
->theNumberOfPowerStates
)-1; i
>= 0; i
-- )
4617 if ( (domainState
& pm_vars
->thePowerStates
[i
].inputPowerRequirement
) == pm_vars
->thePowerStates
[i
].inputPowerRequirement
)
4626 //*********************************************************************************
4627 // initialPowerStateForDomainState
4629 // Finds the highest power state in the array whose input power
4630 // requirement is equal to the input parameter. Where a more intelligent
4631 // decision is possible, override this in the subclassed driver.
4632 //*********************************************************************************
4634 unsigned long IOService::initialPowerStateForDomainState ( IOPMPowerFlags domainState
)
4638 if (pm_vars
->theNumberOfPowerStates
== 0 )
4642 for ( i
= (pm_vars
->theNumberOfPowerStates
)-1; i
>= 0; i
-- )
4644 if ( (domainState
& pm_vars
->thePowerStates
[i
].inputPowerRequirement
) == pm_vars
->thePowerStates
[i
].inputPowerRequirement
)
4653 //*********************************************************************************
4654 // powerStateForDomainState
4656 // Finds the highest power state in the array whose input power
4657 // requirement is equal to the input parameter. Where a more intelligent
4658 // decision is possible, override this in the subclassed driver.
4659 //*********************************************************************************
4661 unsigned long IOService::powerStateForDomainState ( IOPMPowerFlags domainState
)
4665 if (pm_vars
->theNumberOfPowerStates
== 0 )
4669 for ( i
= (pm_vars
->theNumberOfPowerStates
)-1; i
>= 0; i
-- )
4671 if ( (domainState
& pm_vars
->thePowerStates
[i
].inputPowerRequirement
) == pm_vars
->thePowerStates
[i
].inputPowerRequirement
)
4680 //*********************************************************************************
4683 // Does nothing here. This should be implemented in a subclass driver.
4684 //*********************************************************************************
4686 bool IOService::didYouWakeSystem ( void )
4692 //*********************************************************************************
4693 // powerStateWillChangeTo
4695 // Does nothing here. This should be implemented in a subclass driver.
4696 //*********************************************************************************
4698 IOReturn
IOService::powerStateWillChangeTo ( IOPMPowerFlags
, unsigned long, IOService
*)
4704 //*********************************************************************************
4705 // powerStateDidChangeTo
4707 // Does nothing here. This should be implemented in a subclass driver.
4708 //*********************************************************************************
4710 IOReturn
IOService::powerStateDidChangeTo ( IOPMPowerFlags
, unsigned long, IOService
*)
4716 //*********************************************************************************
4719 // Does nothing here. This should be implemented in a subclass policy-maker.
4720 //*********************************************************************************
4722 void IOService::powerChangeDone ( unsigned long )
4727 //*********************************************************************************
4730 // Does nothing here. This should be implemented in a subclass driver.
4731 //*********************************************************************************
4733 IOReturn
IOService::newTemperature ( long currentTemp
, IOService
* whichZone
)
4741 #define super OSObject
4743 OSDefineMetaClassAndStructors(IOPMprot
, OSObject
)
4744 //*********************************************************************************
4747 // Serialize protected instance variables for debug output.
4748 //*********************************************************************************
4749 bool IOPMprot::serialize(OSSerialize
*s
) const
4751 OSString
* theOSString
;
4758 // estimate how many bytes we need to present all power states
4759 buf_size
= 150 // beginning and end of string
4760 + (275 * (int)theNumberOfPowerStates
) // size per state
4761 + 100; // extra room just for kicks
4763 buffer
= ptr
= IONew(char, buf_size
);
4767 ptr
+= sprintf(ptr
,"{ theNumberOfPowerStates = %d, ",(unsigned int)theNumberOfPowerStates
);
4769 if ( theNumberOfPowerStates
!= 0 ) {
4770 ptr
+= sprintf(ptr
,"version %d, ",(unsigned int)thePowerStates
[0].version
);
4773 if ( theNumberOfPowerStates
!= 0 ) {
4774 for ( i
= 0; i
< (int)theNumberOfPowerStates
; i
++ ) {
4775 ptr
+= sprintf(ptr
, "power state %d = { ",i
);
4776 ptr
+= sprintf(ptr
,"capabilityFlags %08x, ",(unsigned int)thePowerStates
[i
].capabilityFlags
);
4777 ptr
+= sprintf(ptr
,"outputPowerCharacter %08x, ",(unsigned int)thePowerStates
[i
].outputPowerCharacter
);
4778 ptr
+= sprintf(ptr
,"inputPowerRequirement %08x, ",(unsigned int)thePowerStates
[i
].inputPowerRequirement
);
4779 ptr
+= sprintf(ptr
,"staticPower %d, ",(unsigned int)thePowerStates
[i
].staticPower
);
4780 ptr
+= sprintf(ptr
,"unbudgetedPower %d, ",(unsigned int)thePowerStates
[i
].unbudgetedPower
);
4781 ptr
+= sprintf(ptr
,"powerToAttain %d, ",(unsigned int)thePowerStates
[i
].powerToAttain
);
4782 ptr
+= sprintf(ptr
,"timeToAttain %d, ",(unsigned int)thePowerStates
[i
].timeToAttain
);
4783 ptr
+= sprintf(ptr
,"settleUpTime %d, ",(unsigned int)thePowerStates
[i
].settleUpTime
);
4784 ptr
+= sprintf(ptr
,"timeToLower %d, ",(unsigned int)thePowerStates
[i
].timeToLower
);
4785 ptr
+= sprintf(ptr
,"settleDownTime %d, ",(unsigned int)thePowerStates
[i
].settleDownTime
);
4786 ptr
+= sprintf(ptr
,"powerDomainBudget %d }, ",(unsigned int)thePowerStates
[i
].powerDomainBudget
);
4790 ptr
+= sprintf(ptr
,"aggressiveness = %d, ",(unsigned int)aggressiveness
);
4791 ptr
+= sprintf(ptr
,"myCurrentState = %d, ",(unsigned int)myCurrentState
);
4792 ptr
+= sprintf(ptr
,"parentsCurrentPowerFlags = %08x, ",(unsigned int)parentsCurrentPowerFlags
);
4793 ptr
+= sprintf(ptr
,"maxCapability = %d }",(unsigned int)maxCapability
);
4795 theOSString
= OSString::withCString(buffer
);
4796 rtn_code
= theOSString
->serialize(s
);
4797 theOSString
->release();
4798 IODelete(buffer
, char, buf_size
);
4805 #define super OSObject
4807 OSDefineMetaClassAndStructors(IOPMpriv
, OSObject
)
4808 //*********************************************************************************
4811 // Serialize private instance variables for debug output.
4812 //*********************************************************************************
4813 bool IOPMpriv::serialize(OSSerialize
*s
) const
4815 OSString
* theOSString
;
4819 IOPMinformee
* nextObject
;
4821 buffer
= ptr
= IONew(char, 2000);
4825 ptr
+= sprintf(ptr
,"{ this object = %08x",(unsigned int)owner
);
4826 if ( we_are_root
) {
4827 ptr
+= sprintf(ptr
," (root)");
4829 ptr
+= sprintf(ptr
,", ");
4831 nextObject
= interestedDrivers
->firstInList(); // display interested drivers
4832 while ( nextObject
!= NULL
) {
4833 ptr
+= sprintf(ptr
,"interested driver = %08x, ",(unsigned int)nextObject
->whatObject
);
4834 nextObject
= interestedDrivers
->nextInList(nextObject
);
4837 if ( machine_state
!= kIOPM_Finished
) {
4838 ptr
+= sprintf(ptr
,"machine_state = %d, ",(unsigned int)machine_state
);
4839 ptr
+= sprintf(ptr
,"driver_timer = %d, ",(unsigned int)driver_timer
);
4840 ptr
+= sprintf(ptr
,"settle_time = %d, ",(unsigned int)settle_time
);
4841 ptr
+= sprintf(ptr
,"head_note_flags = %08x, ",(unsigned int)head_note_flags
);
4842 ptr
+= sprintf(ptr
,"head_note_state = %d, ",(unsigned int)head_note_state
);
4843 ptr
+= sprintf(ptr
,"head_note_outputFlags = %08x, ",(unsigned int)head_note_outputFlags
);
4844 ptr
+= sprintf(ptr
,"head_note_domainState = %08x, ",(unsigned int)head_note_domainState
);
4845 ptr
+= sprintf(ptr
,"head_note_capabilityFlags = %08x, ",(unsigned int)head_note_capabilityFlags
);
4846 ptr
+= sprintf(ptr
,"head_note_pendingAcks = %d, ",(unsigned int)head_note_pendingAcks
);
4849 if ( device_overrides
) {
4850 ptr
+= sprintf(ptr
,"device overrides, ");
4852 ptr
+= sprintf(ptr
,"driverDesire = %d, ",(unsigned int)driverDesire
);
4853 ptr
+= sprintf(ptr
,"deviceDesire = %d, ",(unsigned int)deviceDesire
);
4854 ptr
+= sprintf(ptr
,"ourDesiredPowerState = %d, ",(unsigned int)ourDesiredPowerState
);
4855 ptr
+= sprintf(ptr
,"previousRequest = %d }",(unsigned int)previousRequest
);
4857 theOSString
= OSString::withCString(buffer
);
4858 rtn_code
= theOSString
->serialize(s
);
4859 theOSString
->release();
4860 IODelete(buffer
, char, 2000);