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>
42 // Required for notification instrumentation
43 #include "IOServicePrivate.h"
45 #define super IORegistryEntry
47 #define OUR_PMLog(t, a, b) \
48 do { pm_vars->thePlatform->PMLog(pm_vars->ourName, t, a, b); } while(0)
50 static void ack_timer_expired(thread_call_param_t
);
51 static void settle_timer_expired(thread_call_param_t
);
52 static void PM_idle_timer_expired(OSObject
*, IOTimerEventSource
*);
53 void tellAppWithResponse ( OSObject
* object
, void * context
);
54 void tellClientWithResponse ( OSObject
* object
, void * context
);
55 void tellClient ( OSObject
* object
, void * context
);
56 IOReturn
serializedAllowPowerChange ( OSObject
*, void *, void *, void *, void *);
57 IOReturn
serializedCancelPowerChange ( OSObject
*, void *, void *, void *, void *);
59 extern const IORegistryPlane
* gIOPowerPlane
;
62 // and there's 1000 nanoseconds in a microsecond:
63 #define ns_per_us 1000
66 // The current change note is processed by a state machine.
67 // Inputs are acks from interested parties, ack from the controlling driver,
68 // ack timeouts, settle timeout, and powerStateDidChange from the parent.
69 // These are the states:
71 kIOPM_OurChangeTellClientsPowerDown
= 1,
72 kIOPM_OurChangeTellPriorityClientsPowerDown
,
73 kIOPM_OurChangeNotifyInterestedDriversWillChange
,
74 kIOPM_OurChangeSetPowerState
,
75 kIOPM_OurChangeWaitForPowerSettle
,
76 kIOPM_OurChangeNotifyInterestedDriversDidChange
,
77 kIOPM_OurChangeFinish
,
78 kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate
,
79 kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
,
80 kIOPM_ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate
,
81 kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
,
82 kIOPM_ParentDownSetPowerState_Delayed
,
83 kIOPM_ParentDownWaitForPowerSettle_Delayed
,
84 kIOPM_ParentDownAcknowledgeChange_Delayed
,
85 kIOPM_ParentUpSetPowerState_Delayed
,
86 kIOPM_ParentUpSetPowerState_Immediate
,
87 kIOPM_ParentUpWaitForSettleTime_Delayed
,
88 kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed
,
89 kIOPM_ParentUpAcknowledgePowerChange_Delayed
,
93 // values of outofbandparameter
100 // used for applyToInterested
102 OSArray
* responseFlags
;
105 UInt32 maxTimeRequested
;
109 unsigned long stateNumber
;
110 IOPMPowerFlags stateFlags
;
113 // five minutes in microseconds
114 #define FIVE_MINUTES 5*60*1000000
115 #define k30seconds 30*1000000
118 There are two different kinds of power state changes. One is initiated by a subclassed device object which has either
119 decided to change power state, or its controlling driver has suggested it, or some other driver wants to use the
120 idle device and has asked it to become usable. The second kind of power state change is initiated by the power
121 domain parent. The two are handled slightly differently.
123 There is a queue of so-called change notifications, or change notes for short. Usually the queue is empty, and when
124 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
125 at one time, a queue is implemented. Example: the subclass device decides it's idle and initiates a change to a lower
126 power state. This causes interested parties to be notified, but they don't all acknowledge right away. This causes the
127 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
128 wants to raise power back up again. This change can't be started, however, because the previous one isn't complete yet,
129 so the second one waits in the queue. During this time, the parent decides to lower or raise the power state of the entire
130 power domain and notifies the device, and that notification goes into the queue, too, and can't be actioned until the
133 This is how a power change initiated by the subclass device is handled:
134 First, all interested parties are notified of the change via their powerStateWillChangeTo method. If they all don't
135 acknowledge via return code, then we have to wait. If they do, or when they finally all acknowledge via our
136 acknowledgePowerChange method, then we can continue. We call the controlling driver, instructing it to change to
137 the new state. Then we wait for power to settle. If there is no settling-time, or after it has passed, we notify
138 interested parties again, this time via their powerStateDidChangeTo methods. When they have all acked, we're done.
139 If we lowered power and don't need the power domain to be in its current power state, we suggest to the parent that
140 it lower the power domain state.
142 This is how a change to a lower power domain state initiated by the parent is handled:
143 First, we figure out what power state we will be in when the new domain state is reached. Then all interested parties are
144 notified that we are moving to that new state. When they have acknowledged, we call the controlling driver to assume
145 that state and we wait for power to settle. Then we acknowledge our preparedness to our parent. When all its interested
146 parties have acknowledged, it lowers power and then notifies its interested parties again. When we get this call, we notify
147 our interested parties that the power state has changed, and when they have all acknowledged, we're done.
149 This is how a change to a higher power domain state initiated by the parent is handled:
150 We figure out what power state we will be in when the new domain state is reached. If it is different from our current
151 state we acknowledge the parent. When all the parent's interested parties have acknowledged, it raises power in the
152 domain and waits for power to settle. Then it notifies everyone that the new state has been reached. When we get this call,
153 we call the controlling driver, instructing it to assume the new state, and wait for power to settle. Then we notify our interested
154 parties. When they all acknowledge we are done.
156 In either of the two cases above, it is possible that we will not be changing state even though the domain is. Examples:
157 A change to a lower domain state may not affect us because we are already in a low enough state, and
158 We will not take advantage of a change to a higher domain state, because we have no need of the higher power.
159 In such a case, there is nothing to do but acknowledge the parent. So when the parent calls our powerDomainWillChange
160 method, and we decide that we will not be changing state, we merely acknowledge the parent, via return code, and wait.
161 When the parent subsequently calls powerStateDidChange, we acknowledge again via return code, and the change is complete.
163 Power state changes are processed in a state machine, and since there are four varieties of power state changes, there are
164 four major paths through the state machine:
166 The fourth is nearly trivial. In this path, the parent is changing the domain state, but we are not changing the device state.
167 The change starts when the parent calls powerDomainWillChange. All we do is acknowledge the parent.
168 When the parent calls powerStateDidChange, we acknowledge the parent again, and we're done.
170 The first is fairly simple. It starts when a power domain child calls requestPowerDomainState and we decide to change power states
171 to accomodate the child, or if our power-controlling driver calls changePowerStateTo, or if some other driver which is using our
172 device calls makeUsable, or if a subclassed object calls changePowerStateToPriv. These are all power changes initiated by us, not
173 forced upon us by the parent. We start by notifying interested parties. If they all acknowledge via return code, we can go
174 on to state "OurChangeSetPowerState". Otherwise, we start the ack timer and wait for the stragglers to acknowlege by calling
175 acknowledgePowerChange. We move on to state "OurChangeSetPowerState" when all the stragglers have acknowledged,
176 or when the ack timer expires on all those which didn't acknowledge. In "OurChangeSetPowerState" we call the power-controlling
177 driver to change the power state of the hardware. If it returns saying it has done so, we go on to state "OurChangeWaitForPowerSettle".
178 Otherwise, we have to wait for it, so we set the ack timer and wait. When it calls acknowledgeSetPowerState, or when the
179 ack timer expires, we go on. In "OurChangeWaitForPowerSettle", we look in the power state array to see if there is any settle time required
180 when changing from our current state to the new state. If not, we go right away to "OurChangeNotifyInterestedDriversDidChange". Otherwise, we
181 set the settle timer and wait. When it expires, we move on. In "OurChangeNotifyInterestedDriversDidChange" state, we notify all our interested parties
182 via their powerStateDidChange methods that we have finished changing power state. If they all acknowledge via return
183 code, we move on to "OurChangeFinish". Otherwise we set the ack timer and wait. When they have all acknowledged, or
184 when the ack timer has expired for those that didn't, we move on to "OurChangeFinish", where we remove the used
185 change note from the head of the queue and start the next one if one exists.
187 Parent-initiated changes are more complex in the state machine. First, power going up and power going down are handled
188 differently, so they have different paths throught the state machine. Second, we can acknowledge the parent's notification
189 in two different ways, so each of the parent paths is really two.
191 When the parent calls our powerDomainWillChange method, notifying us that it will lower power in the domain, we decide
192 what state that will put our device in. Then we embark on the state machine path "IOPMParentDownSetPowerState_Immediate"
193 and "kIOPM_ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate", in which we notify interested parties of the upcoming change, instruct our driver to make
194 the change, check for settle time, and notify interested parties of the completed change. If we get to the end of this path without
195 stalling due to an interested party which didn't acknowledge via return code, due to the controlling driver not able to change
196 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.
197 If we do stall in any of those states, we return IOPMWillAckLater to the parent and enter the parallel path "kIOPM_ParentDownSetPowerState_Delayed"
198 "kIOPM_ParentDownWaitForPowerSettle_Delayed", and "kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed", where we continue with the same processing, except that at the end we
199 acknowledge the parent explicitly via acknowledgePowerChange, and we're done with the change.
200 Then when the parent calls us at powerStateDidChange we acknowledging via return code, because we have already made
201 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.
203 The case of the parent raising power in the domain is handled similarly in that there are parallel paths, one for no-stall
204 that ends in implicit acknowleging the parent, and one that has stalled at least once that ends in explicit acknowledging
205 the parent. This case is different, though in that our device changes state in the second half, after the parent calls
206 powerStateDidChange rather than before, as in the power-lowering case.
208 When the parent calls our powerDomainWillChange method, notifying us that it will raise power in the domain, we acknowledge
209 via return code, because there's really nothing we can do until the power is actually raised in the domain.
210 When the parent calls us at powerStateDidChange, we start by notifying our interested parties. If they all acknowledge via return code,
211 we go on to" kIOPM_ParentUpSetPowerState_Immediate" to instruct the driver to raise its power level. After that, we check for any
212 necessary settling time in "IOPMParentUpWaitForSettleTime_Immediate", and we notify all interested parties that power has changed
213 in "IOPMParentUpNotifyInterestedDriversDidChange_Immediate". If none of these operations stall, we acknowledge the parent via return code, release
214 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",
215 "kIOPM_ParentUpWaitForSettleTime_Delayed", "kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed", and "kIOPM_ParentUpAcknowledgePowerChange_Delayed", which ends with
216 our explicit acknowledgement to the parent.
221 const char priv_key
[ ] = "Power Management private data";
222 const char prot_key
[ ] = "Power Management protected data";
225 void IOService::PMinit ( void )
227 if ( ! initialized
) {
229 // make space for our variables
230 pm_vars
= new IOPMprot
;
236 // add pm_vars & priv to the properties
237 setProperty(prot_key
, (OSObject
*) pm_vars
);
238 setProperty(priv_key
, (OSObject
*) priv
);
240 // then initialize them
242 pm_vars
->theNumberOfPowerStates
= 0;
243 priv
->we_are_root
= false;
244 pm_vars
->theControllingDriver
= NULL
;
245 priv
->our_lock
= IOLockAlloc();
246 priv
->flags_lock
= IOLockAlloc();
247 priv
->queue_lock
= IOLockAlloc();
248 pm_vars
->childLock
= IOLockAlloc();
249 pm_vars
->parentLock
= IOLockAlloc();
250 priv
->interestedDrivers
= new IOPMinformeeList
;
251 priv
->interestedDrivers
->initialize();
252 priv
->changeList
= new IOPMchangeNoteList
;
253 priv
->changeList
->initialize();
254 pm_vars
->aggressiveness
= 0;
255 for (unsigned int i
= 0; i
<= kMaxType
; i
++)
257 pm_vars
->current_aggressiveness_values
[i
] = 0;
258 pm_vars
->current_aggressiveness_valid
[i
] = false;
260 pm_vars
->myCurrentState
= 0;
261 priv
->imminentState
= 0;
262 priv
->ourDesiredPowerState
= 0;
263 pm_vars
->parentsCurrentPowerFlags
= 0;
264 pm_vars
->maxCapability
= 0;
265 priv
->driverDesire
= 0;
266 priv
->deviceDesire
= 0;
267 priv
->initial_change
= true;
268 priv
->need_to_become_usable
= false;
269 priv
->previousRequest
= 0;
270 priv
->device_overrides
= false;
271 priv
->machine_state
= kIOPM_Finished
;
272 priv
->timerEventSrc
= NULL
;
273 priv
->clampTimerEventSrc
= NULL
;
274 pm_vars
->PMworkloop
= NULL
;
275 priv
->activityLock
= NULL
;
276 pm_vars
->ourName
= getName();
277 pm_vars
->thePlatform
= getPlatform();
278 pm_vars
->parentsKnowState
= false;
279 assert( pm_vars
->thePlatform
!= 0 );
280 priv
->clampOn
= false;
281 pm_vars
->serialNumber
= 0;
282 pm_vars
->responseFlags
= NULL
;
283 pm_vars
->doNotPowerDown
= true;
284 pm_vars
->PMcommandGate
= NULL
;
285 priv
->ackTimer
= thread_call_allocate(
286 (thread_call_func_t
)ack_timer_expired
,
287 (thread_call_param_t
)this);
288 priv
->settleTimer
= thread_call_allocate(
289 (thread_call_func_t
)settle_timer_expired
,
290 (thread_call_param_t
)this);
297 //*********************************************************************************
300 // Free up the data created in PMinit, if it exists.
301 //*********************************************************************************
302 void IOService::PMfree ( void )
305 if ( priv
->clampTimerEventSrc
!= NULL
) {
306 getPMworkloop()->removeEventSource(priv
->clampTimerEventSrc
);
307 priv
->clampTimerEventSrc
->release();
308 priv
->clampTimerEventSrc
= NULL
;
310 if ( priv
->timerEventSrc
!= NULL
) {
311 pm_vars
->PMworkloop
->removeEventSource(priv
->timerEventSrc
);
312 priv
->timerEventSrc
->release();
313 priv
->timerEventSrc
= NULL
;
315 if ( priv
->settleTimer
) {
316 thread_call_cancel(priv
->settleTimer
);
317 thread_call_free(priv
->settleTimer
);
318 priv
->settleTimer
= NULL
;
320 if ( priv
->ackTimer
) {
321 thread_call_cancel(priv
->ackTimer
);
322 thread_call_free(priv
->ackTimer
);
323 priv
->ackTimer
= NULL
;
325 if ( priv
->our_lock
) {
326 IOLockFree(priv
->our_lock
);
327 priv
->our_lock
= NULL
;
329 if ( priv
->flags_lock
) {
330 IOLockFree(priv
->flags_lock
);
331 priv
->flags_lock
= NULL
;
333 if ( priv
->activityLock
) {
334 IOLockFree(priv
->activityLock
);
335 priv
->activityLock
= NULL
;
337 priv
->interestedDrivers
->release();
338 priv
->changeList
->release();
339 // remove instance variables
344 if ( pm_vars
->PMcommandGate
) {
345 if(pm_vars
->PMworkloop
)
346 pm_vars
->PMworkloop
->removeEventSource(pm_vars
->PMcommandGate
);
347 pm_vars
->PMcommandGate
->release();
348 pm_vars
->PMcommandGate
= NULL
;
350 if ( pm_vars
->PMworkloop
) {
351 // The work loop object returned from getPMworkLoop() is
352 // never retained, therefore it should not be released.
353 // pm_vars->PMworkloop->release();
354 pm_vars
->PMworkloop
= NULL
;
356 if ( pm_vars
->responseFlags
) {
357 pm_vars
->responseFlags
->release();
358 pm_vars
->responseFlags
= NULL
;
360 // remove instance variables
366 //*********************************************************************************
369 // Disconnect the node from its parents and children in the Power Plane.
370 //*********************************************************************************
371 void IOService::PMstop ( void )
375 IOPowerConnection
* connection
;
376 IOService
* theChild
;
377 IOService
* theParent
;
379 // remove the properties
380 removeProperty(prot_key
);
381 removeProperty(priv_key
);
384 iter
= getParentIterator(gIOPowerPlane
);
388 while ( (next
= iter
->getNextObject()) )
390 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
392 theParent
= (IOService
*)connection
->copyParentEntry(gIOPowerPlane
);
395 theParent
->removePowerChild(connection
);
396 theParent
->release();
403 // detach IOConnections
404 detachAbove( gIOPowerPlane
);
408 // no more power state changes
409 pm_vars
->parentsKnowState
= false;
413 iter
= getChildIterator(gIOPowerPlane
);
417 while ( (next
= iter
->getNextObject()) )
419 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
421 theChild
= ((IOService
*)(connection
->copyChildEntry(gIOPowerPlane
)));
424 // detach nub from child
425 connection
->detachFromChild(theChild
,gIOPowerPlane
);
428 // detach us from nub
429 detachFromChild(connection
,gIOPowerPlane
);
435 // Remove all interested drivers from the list, including the power
436 // controlling driver.
438 // Usually, the controlling driver and the policy-maker functionality
439 // are implemented by the same object, and without the deregistration,
440 // the object will be holding an extra retain on itself, and cannot
443 if ( priv
&& priv
->interestedDrivers
)
445 IOPMinformee
* informee
;
447 while (( informee
= priv
->interestedDrivers
->firstInList() ))
448 deRegisterInterestedDriver( informee
->whatObject
);
453 //*********************************************************************************
456 // A policy-maker calls its nub here when initializing, to be attached into
457 // the power management hierarchy. The default function is to call the
458 // platform expert, which knows how to do it. This method is overridden
459 // by a nub subclass which may either know how to do it, or may need
460 // to take other action.
462 // This may be the only "power management" method used in a nub,
463 // meaning it may not be initialized for power management.
464 //*********************************************************************************
465 void IOService::joinPMtree ( IOService
* driver
)
467 IOPlatformExpert
* thePlatform
;
469 thePlatform
= getPlatform();
470 assert(thePlatform
!= 0 );
471 thePlatform
->PMRegisterDevice(this,driver
);
475 //*********************************************************************************
478 // Power Managment is informing us that we are the root power domain.
479 // The only difference between us and any other power domain is that
480 // we have no parent and therefore never call it.
481 //*********************************************************************************
482 IOReturn
IOService::youAreRoot ( void )
484 priv
-> we_are_root
= true;
485 pm_vars
->parentsKnowState
= true;
486 attachToParent( getRegistryRoot(),gIOPowerPlane
);
492 //*********************************************************************************
495 // Power Management is informing us who our parent is.
496 // If we have a controlling driver, find out, given our newly-informed
497 // power domain state, what state it would be in, and then tell it
498 // to assume that state.
499 //*********************************************************************************
500 IOReturn
IOService::setPowerParent ( IOPowerConnection
* theParent
, bool stateKnown
, IOPMPowerFlags currentState
)
504 IOPowerConnection
* connection
;
505 unsigned long tempDesire
;
507 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogSetParent
,stateKnown
,currentState
);
509 IOLockLock(pm_vars
->parentLock
);
511 if ( stateKnown
&& ((pm_vars
->PMworkloop
== NULL
) || (pm_vars
->PMcommandGate
== NULL
)) )
513 // we have a path to the root
514 // find out the workloop
516 if ( pm_vars
->PMworkloop
!= NULL
)
518 if ( pm_vars
->PMcommandGate
== NULL
)
520 // and make our command gate
521 pm_vars
->PMcommandGate
= IOCommandGate::commandGate((OSObject
*)this);
522 if ( pm_vars
->PMcommandGate
!= NULL
)
524 pm_vars
->PMworkloop
->addEventSource(pm_vars
->PMcommandGate
);
530 IOLockUnlock(pm_vars
->parentLock
);
532 // set our connection data
533 theParent
->setParentCurrentPowerFlags(currentState
);
534 theParent
->setParentKnowsState(stateKnown
);
536 // combine parent knowledge
537 pm_vars
->parentsKnowState
= true;
538 pm_vars
->parentsCurrentPowerFlags
= 0;
540 iter
= getParentIterator(gIOPowerPlane
);
544 while ( (next
= iter
->getNextObject()) )
546 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
548 pm_vars
->parentsKnowState
&= connection
->parentKnowsState();
549 pm_vars
->parentsCurrentPowerFlags
|= connection
->parentCurrentPowerFlags();
555 if ( (pm_vars
->theControllingDriver
!= NULL
) &&
556 (pm_vars
->parentsKnowState
) )
558 pm_vars
->maxCapability
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(pm_vars
->parentsCurrentPowerFlags
);
559 // initially change into the state we are already in
560 tempDesire
= priv
->deviceDesire
;
561 priv
->deviceDesire
= pm_vars
->theControllingDriver
->initialPowerStateForDomainState(pm_vars
->parentsCurrentPowerFlags
);
562 computeDesiredState();
563 priv
->previousRequest
= 0xffffffff;
565 // put this back like before
566 priv
->deviceDesire
= tempDesire
;
573 //*********************************************************************************
576 // Power Management is informing us who our children are.
577 //*********************************************************************************
578 IOReturn
IOService::addPowerChild ( IOService
* theChild
)
580 IOPowerConnection
*connection
;
585 // we're not a power-managed IOService
586 return IOPMNotYetInitialized
;
589 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAddChild
,0,0);
591 // Put ourselves into a usable power state.
592 // We must be in an "on" power state, as our children must be able to access
593 // our hardware after joining the power plane.
594 temporaryMakeUsable();
597 connection
= new IOPowerConnection
;
600 connection
->start(this);
601 connection
->setAwaitingAck(false);
604 attachToChild( connection
,gIOPowerPlane
);
605 connection
->attachToChild( theChild
,gIOPowerPlane
);
606 connection
->release();
608 // tell it the current state of the power domain
609 if ( (pm_vars
->theControllingDriver
== NULL
) ||
610 ! (inPlane(gIOPowerPlane
)) ||
611 ! (pm_vars
->parentsKnowState
) )
613 theChild
->setPowerParent(connection
,false,0);
614 if ( inPlane(gIOPowerPlane
) )
616 for (i
= 0; i
<= kMaxType
; i
++) {
617 if ( pm_vars
->current_aggressiveness_valid
[i
] )
619 theChild
->setAggressiveness (i
, pm_vars
->current_aggressiveness_values
[i
]);
624 theChild
->setPowerParent(connection
,true,pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].outputPowerCharacter
);
625 for (i
= 0; i
<= kMaxType
; i
++)
627 if ( pm_vars
->current_aggressiveness_valid
[i
] )
629 theChild
->setAggressiveness (i
, pm_vars
->current_aggressiveness_values
[i
]);
632 // catch it up if change is in progress
633 add_child_to_active_change(connection
);
640 //******************************************************************************
643 //******************************************************************************
644 IOReturn
IOService::removePowerChild ( IOPowerConnection
* theNub
)
646 IORegistryEntry
*theChild
;
648 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRemoveChild
,0,0);
652 // detach nub from child
653 theChild
= theNub
->copyChildEntry(gIOPowerPlane
);
656 theNub
->detachFromChild(theChild
, gIOPowerPlane
);
659 // detach from the nub
660 detachFromChild(theNub
,gIOPowerPlane
);
662 // are we awaiting an ack from this child?
663 if ( theNub
->getAwaitingAck() )
665 // yes, pretend we got one
666 theNub
->setAwaitingAck(false);
667 if ( acquire_lock() )
669 if (priv
->head_note_pendingAcks
!= 0 )
671 // that's one fewer ack to worry about
672 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
674 if ( priv
->head_note_pendingAcks
== 0 )
676 // yes, stop the timer
678 IOUnlock(priv
->our_lock
);
679 // and now we can continue our power change
682 IOUnlock(priv
->our_lock
);
685 IOUnlock(priv
->our_lock
);
692 // if not fully initialized
693 if ( (pm_vars
->theControllingDriver
== NULL
) ||
694 !(inPlane(gIOPowerPlane
)) ||
695 !(pm_vars
->parentsKnowState
) )
701 // Perhaps the departing child was holding up idle or system sleep - we
702 // need to re-evaluate our childrens' requests.
703 // Clear and re-calculate our kIOPMChildClamp and kIOPMChildClamp2 bits.
704 rebuildChildClampBits();
706 // Change state if we can now tolerate lower power
707 computeDesiredState();
714 //*********************************************************************************
715 // registerPowerDriver
717 // A driver has called us volunteering to control power to our device.
718 // If the power state array it provides is richer than the one we already
719 // know about (supplied by an earlier volunteer), then accept the offer.
720 // Notify all interested parties of our power state, which we now know.
721 //*********************************************************************************
723 IOReturn
IOService::registerPowerDriver ( IOService
* controllingDriver
, IOPMPowerState
* powerStates
, unsigned long numberOfStates
)
726 unsigned long tempDesire
;
728 if ( (numberOfStates
> pm_vars
->theNumberOfPowerStates
)
729 && (numberOfStates
> 1) )
731 if ( priv
->changeList
->currentChange() == -1 )
733 if ( controllingDriver
!= NULL
)
735 if ( numberOfStates
<= IOPMMaxPowerStates
)
737 switch ( powerStates
[0].version
)
740 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriver
,
741 (unsigned long)numberOfStates
, (unsigned long)powerStates
[0].version
);
742 for ( i
= 0; i
< numberOfStates
; i
++ )
744 pm_vars
->thePowerStates
[i
] = powerStates
[i
];
748 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriver
,
749 (unsigned long) numberOfStates
,(unsigned long) powerStates
[0].version
);
750 for ( i
= 0; i
< numberOfStates
; i
++ )
752 pm_vars
->thePowerStates
[i
].version
= powerStates
[i
].version
;
753 pm_vars
->thePowerStates
[i
].capabilityFlags
= powerStates
[i
].capabilityFlags
;
754 pm_vars
->thePowerStates
[i
].outputPowerCharacter
= powerStates
[i
].outputPowerCharacter
;
755 pm_vars
->thePowerStates
[i
].inputPowerRequirement
= powerStates
[i
].inputPowerRequirement
;
756 pm_vars
->thePowerStates
[i
].staticPower
= powerStates
[i
].staticPower
;
757 pm_vars
->thePowerStates
[i
].unbudgetedPower
= powerStates
[i
].unbudgetedPower
;
758 pm_vars
->thePowerStates
[i
].powerToAttain
= powerStates
[i
].powerToAttain
;
759 pm_vars
->thePowerStates
[i
].timeToAttain
= powerStates
[i
].timeToAttain
;
760 pm_vars
->thePowerStates
[i
].settleUpTime
= powerStates
[i
].settleUpTime
;
761 pm_vars
->thePowerStates
[i
].timeToLower
= powerStates
[i
].timeToLower
;
762 pm_vars
->thePowerStates
[i
].settleDownTime
= powerStates
[i
].settleDownTime
;
763 pm_vars
->thePowerStates
[i
].powerDomainBudget
= powerStates
[i
].powerDomainBudget
;
767 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr1
,
768 (unsigned long)powerStates
[0].version
,0);
772 // make a mask of all the character bits we know about
773 pm_vars
->myCharacterFlags
= 0;
774 for ( i
= 0; i
< numberOfStates
; i
++ ) {
775 pm_vars
->myCharacterFlags
|= pm_vars
->thePowerStates
[i
].outputPowerCharacter
;
778 pm_vars
->theNumberOfPowerStates
= numberOfStates
;
779 pm_vars
->theControllingDriver
= controllingDriver
;
780 if ( priv
->interestedDrivers
->findItem(controllingDriver
) == NULL
)
782 // register it as interested, unless already done
783 registerInterestedDriver (controllingDriver
);
785 if ( priv
->need_to_become_usable
) {
786 priv
->need_to_become_usable
= false;
787 priv
->deviceDesire
= pm_vars
->theNumberOfPowerStates
- 1;
790 if ( inPlane(gIOPowerPlane
) &&
791 (pm_vars
->parentsKnowState
) ) {
792 pm_vars
->maxCapability
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(pm_vars
->parentsCurrentPowerFlags
);
793 // initially change into the state we are already in
794 tempDesire
= priv
->deviceDesire
;
795 priv
->deviceDesire
= pm_vars
->theControllingDriver
->initialPowerStateForDomainState(pm_vars
->parentsCurrentPowerFlags
);
796 computeDesiredState();
798 // put this back like before
799 priv
->deviceDesire
= tempDesire
;
802 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr2
,(unsigned long)numberOfStates
,0);
805 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr4
,0,0);
810 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr5
,(unsigned long)numberOfStates
,0);
815 //*********************************************************************************
816 // registerInterestedDriver
818 // Add the caller to our list of interested drivers and return our current
819 // power state. If we don't have a power-controlling driver yet, we will
820 // call this interested driver again later when we do get a driver and find
821 // out what the current power state of the device is.
822 //*********************************************************************************
824 IOPMPowerFlags
IOService::registerInterestedDriver ( IOService
* theDriver
)
826 IOPMinformee
*newInformee
;
827 IOPMPowerFlags futureCapability
;
829 if (theDriver
== NULL
) {
833 // make new driver node
834 newInformee
= new IOPMinformee
;
835 newInformee
->initialize(theDriver
);
836 // add it to list of drivers
837 priv
->interestedDrivers
->addToList(newInformee
);
839 if ( (pm_vars
->theControllingDriver
== NULL
) ||
840 !(inPlane(gIOPowerPlane
)) ||
841 !(pm_vars
->parentsKnowState
) )
843 // can't tell it a state yet
844 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInterestedDriver
,IOPMNotPowerManaged
,0);
845 return IOPMNotPowerManaged
;
848 // can we notify new driver of a change in progress?
849 switch (priv
->machine_state
) {
850 case kIOPM_OurChangeSetPowerState
:
851 case kIOPM_OurChangeFinish
:
852 case kIOPM_ParentDownSetPowerState_Delayed
:
853 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
854 case kIOPM_ParentUpSetPowerState_Delayed
:
855 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
856 // yes, remember what we tell it
857 futureCapability
= priv
->head_note_capabilityFlags
;
858 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInterestedDriver
,(unsigned long)futureCapability
,1);
860 add_driver_to_active_change(newInformee
);
861 // and return the same thing
862 return futureCapability
;
865 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInterestedDriver
,
866 (unsigned long) pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
,2);
868 // no, return current capability
869 return pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
;
873 //*********************************************************************************
874 // deRegisterInterestedDriver
876 //*********************************************************************************
877 IOReturn
IOService::deRegisterInterestedDriver ( IOService
* theDriver
)
879 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRemoveDriver
,0,0);
881 // remove the departing driver
882 priv
->interestedDrivers
->removeFromList(theDriver
);
888 //*********************************************************************************
889 // acknowledgePowerChange
891 // After we notified one of the interested drivers or a power-domain child
892 // of an impending change in power, it has called to say it is now
893 // prepared for the change. If this object is the last to
894 // acknowledge this change, we take whatever action we have been waiting
896 // That may include acknowledging to our parent. In this case, we do it
897 // last of all to insure that this doesn't cause the parent to call us some-
898 // where else and alter data we are relying on here (like the very existance
899 // of a "current change note".)
900 //*********************************************************************************
902 IOReturn
IOService::acknowledgePowerChange ( IOService
* whichObject
)
904 IOPMinformee
*ackingObject
;
905 unsigned long childPower
= kIOPMUnknown
;
908 // one of our interested drivers?
909 ackingObject
= priv
->interestedDrivers
->findItem(whichObject
);
910 if ( ackingObject
== NULL
)
912 if ( ! isChild(whichObject
,gIOPowerPlane
) )
914 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr1
,0,0);
915 //kprintf("errant driver: %s\n",whichObject->getName());
919 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChildAcknowledge
,priv
->head_note_pendingAcks
,0);
922 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogDriverAcknowledge
,priv
->head_note_pendingAcks
,0);
925 if (! acquire_lock() )
930 if (priv
->head_note_pendingAcks
!= 0 )
932 // yes, make sure we're expecting acks
933 if ( ackingObject
!= NULL
)
935 // it's an interested driver
936 // make sure we're expecting this ack
937 if ( ackingObject
->timer
!= 0 )
940 ackingObject
->timer
= 0;
941 // that's one fewer to worry about
942 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
944 if ( priv
->head_note_pendingAcks
== 0 )
946 // yes, stop the timer
948 IOUnlock(priv
->our_lock
);
949 // and now we can continue
954 // this driver has already acked
955 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr2
,0,0);
956 //kprintf("errant driver: %s\n",whichObject->getName());
960 // make sure we're expecting this ack
961 if ( ((IOPowerConnection
*)whichObject
)->getAwaitingAck() )
963 // that's one fewer to worry about
964 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
965 ((IOPowerConnection
*)whichObject
)->setAwaitingAck(false);
966 theChild
= (IOService
*)whichObject
->copyChildEntry(gIOPowerPlane
);
969 childPower
= theChild
->currentPowerConsumption();
972 if ( childPower
== kIOPMUnknown
)
974 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
= kIOPMUnknown
;
976 if ( pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
!= kIOPMUnknown
)
978 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
+= childPower
;
982 if ( priv
->head_note_pendingAcks
== 0 ) {
983 // yes, stop the timer
985 IOUnlock(priv
->our_lock
);
986 // and now we can continue
993 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr3
,0,0); // not expecting anybody to ack
994 //kprintf("errant driver: %s\n",whichObject->getName());
996 IOUnlock(priv
->our_lock
);
1000 //*********************************************************************************
1001 // acknowledgeSetPowerState
1003 // After we instructed our controlling driver to change power states,
1004 // it has called to say it has finished doing so.
1005 // We continue to process the power state change.
1006 //*********************************************************************************
1008 IOReturn
IOService::acknowledgeSetPowerState ( void )
1010 if (!acquire_lock())
1013 IOReturn timer
= priv
->driver_timer
;
1014 if ( timer
== -1 ) {
1015 // driver is acking instead of using return code
1016 OUR_PMLog(kPMLogDriverAcknowledgeSet
, (UInt32
) this, timer
);
1017 priv
->driver_timer
= 0;
1019 else if ( timer
> 0 ) { // are we expecting this?
1020 // yes, stop the timer
1022 priv
->driver_timer
= 0;
1023 OUR_PMLog(kPMLogDriverAcknowledgeSet
, (UInt32
) this, timer
);
1024 IOUnlock(priv
->our_lock
);
1028 // not expecting this
1029 OUR_PMLog(kPMLogAcknowledgeErr4
, (UInt32
) this, 0);
1032 IOUnlock(priv
->our_lock
);
1037 //*********************************************************************************
1040 // Either the controlling driver has called acknowledgeSetPowerState
1041 // or the acknowledgement timer has expired while waiting for that.
1042 // We carry on processing the current change note.
1043 //*********************************************************************************
1045 void IOService::driver_acked ( void )
1048 switch (priv
->machine_state
) {
1049 case kIOPM_OurChangeWaitForPowerSettle
:
1050 OurChangeWaitForPowerSettle();
1052 case kIOPM_ParentDownWaitForPowerSettle_Delayed
:
1053 ParentDownWaitForPowerSettle_Delayed();
1055 case kIOPM_ParentUpWaitForSettleTime_Delayed
:
1056 ParentUpWaitForSettleTime_Delayed();
1062 //*********************************************************************************
1063 // powerDomainWillChangeTo
1065 // Called by the power-hierarchy parent notifying of a new power state
1066 // in the power domain.
1067 // We enqueue a parent power-change to our queue of power changes.
1068 // This may or may not cause us to change power, depending on what
1069 // kind of change is occuring in the domain.
1070 //*********************************************************************************
1072 IOReturn
IOService::powerDomainWillChangeTo ( IOPMPowerFlags newPowerStateFlags
, IOPowerConnection
* whichParent
)
1076 IOPowerConnection
*connection
;
1077 unsigned long newStateNumber
;
1078 IOPMPowerFlags combinedPowerFlags
;
1080 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogWillChange
,(unsigned long)newPowerStateFlags
,0);
1082 if ( ! inPlane(gIOPowerPlane
) )
1085 return IOPMAckImplied
;
1088 IOLockLock(pm_vars
->parentLock
);
1090 if ( (pm_vars
->PMworkloop
== NULL
) || (pm_vars
->PMcommandGate
== NULL
) )
1092 // we have a path to the root
1094 // so find out the workloop
1095 if ( pm_vars
->PMworkloop
!= NULL
)
1097 // and make our command gate
1098 if ( pm_vars
->PMcommandGate
== NULL
)
1100 pm_vars
->PMcommandGate
= IOCommandGate::commandGate((OSObject
*)this);
1101 if ( pm_vars
->PMcommandGate
!= NULL
)
1103 pm_vars
->PMworkloop
->addEventSource(pm_vars
->PMcommandGate
);
1109 IOLockUnlock(pm_vars
->parentLock
);
1111 // combine parents' power states
1112 // to determine our maximum state within the new power domain
1113 combinedPowerFlags
= 0;
1115 iter
= getParentIterator(gIOPowerPlane
);
1119 while ( (next
= iter
->getNextObject()) )
1121 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1123 if ( connection
== whichParent
){
1124 combinedPowerFlags
|= newPowerStateFlags
;
1126 combinedPowerFlags
|= connection
->parentCurrentPowerFlags();
1133 if ( pm_vars
->theControllingDriver
== NULL
)
1135 // we can't take any more action
1136 return IOPMAckImplied
;
1138 newStateNumber
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(combinedPowerFlags
);
1140 return enqueuePowerChange(IOPMParentInitiated
| IOPMDomainWillChange
,
1141 newStateNumber
,combinedPowerFlags
,whichParent
,newPowerStateFlags
);
1145 //*********************************************************************************
1146 // powerDomainDidChangeTo
1148 // Called by the power-hierarchy parent after the power state of the power domain
1149 // has settled at a new level.
1150 // We enqueue a parent power-change to our queue of power changes.
1151 // This may or may not cause us to change power, depending on what
1152 // kind of change is occuring in the domain.
1153 //*********************************************************************************
1155 IOReturn
IOService::powerDomainDidChangeTo ( IOPMPowerFlags newPowerStateFlags
, IOPowerConnection
* whichParent
)
1157 unsigned long newStateNumber
;
1159 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogDidChange
,newPowerStateFlags
,0);
1161 setParentInfo(newPowerStateFlags
,whichParent
);
1163 if ( pm_vars
->theControllingDriver
== NULL
) {
1164 return IOPMAckImplied
;
1167 newStateNumber
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(pm_vars
->parentsCurrentPowerFlags
);
1168 // tell interested parties about it
1169 return enqueuePowerChange(IOPMParentInitiated
| IOPMDomainDidChange
,
1170 newStateNumber
,pm_vars
->parentsCurrentPowerFlags
,whichParent
,0);
1174 //*********************************************************************************
1177 // Set our connection data for one specific parent, and then combine all the parent
1179 //*********************************************************************************
1181 void IOService::setParentInfo ( IOPMPowerFlags newPowerStateFlags
, IOPowerConnection
* whichParent
)
1185 IOPowerConnection
*connection
;
1187 // set our connection data
1188 whichParent
->setParentCurrentPowerFlags(newPowerStateFlags
);
1189 whichParent
->setParentKnowsState(true);
1191 IOLockLock(pm_vars
->parentLock
);
1193 // recompute our parent info
1194 pm_vars
->parentsCurrentPowerFlags
= 0;
1195 pm_vars
->parentsKnowState
= true;
1197 iter
= getParentIterator(gIOPowerPlane
);
1201 while ( (next
= iter
->getNextObject()) )
1203 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1205 pm_vars
->parentsKnowState
&= connection
->parentKnowsState();
1206 pm_vars
->parentsCurrentPowerFlags
|= connection
->parentCurrentPowerFlags();
1211 IOLockUnlock(pm_vars
->parentLock
);
1214 //*********************************************************************************
1215 // rebuildChildClampBits
1217 // The ChildClamp bits (kIOPMChildClamp & kIOPMChildClamp2) in our capabilityFlags
1218 // indicate that one of our children (or grandchildren or great-grandchildren or ...)
1219 // doesn't support idle or system sleep in its current state. Since we don't track the
1220 // origin of each bit, every time any child changes state we have to clear these bits
1221 // and rebuild them.
1222 //*********************************************************************************
1224 void IOService::rebuildChildClampBits(void)
1229 IOPowerConnection
*connection
;
1232 // A child's desires has changed. We need to rebuild the child-clamp bits in our
1233 // power state array. Start by clearing the bits in each power state.
1235 for ( i
= 0; i
< pm_vars
->theNumberOfPowerStates
; i
++ )
1237 pm_vars
->thePowerStates
[i
].capabilityFlags
&= ~(kIOPMChildClamp
| kIOPMChildClamp2
);
1240 // Now loop through the children. When we encounter the calling child, save
1241 // the computed state as this child's desire. And while we're at it, set the ChildClamp bits
1242 // in any of our states that some child has requested with clamp on.
1244 iter
= getChildIterator(gIOPowerPlane
);
1248 while ( (next
= iter
->getNextObject()) )
1250 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1252 if ( connection
->getPreventIdleSleepFlag() )
1253 pm_vars
->thePowerStates
[connection
->getDesiredDomainState()].capabilityFlags
|= kIOPMChildClamp
;
1254 if ( connection
->getPreventSystemSleepFlag() )
1255 pm_vars
->thePowerStates
[connection
->getDesiredDomainState()].capabilityFlags
|= kIOPMChildClamp2
;
1264 //*********************************************************************************
1265 // requestPowerDomainState
1267 // The kIOPMPreventIdleSleep and/or kIOPMPreventIdleSleep bits may be be set in the parameter.
1268 // It is not considered part of the state specification.
1269 //*********************************************************************************
1270 IOReturn
IOService::requestPowerDomainState ( IOPMPowerFlags desiredState
, IOPowerConnection
* whichChild
, unsigned long specification
)
1273 unsigned long computedState
;
1274 unsigned long theDesiredState
= desiredState
& ~(kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
1277 IOPowerConnection
*connection
;
1279 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRequestDomain
,
1280 (unsigned long)desiredState
,(unsigned long)specification
);
1282 if ( pm_vars
->theControllingDriver
== NULL
)
1284 return IOPMNotYetInitialized
;
1287 switch (specification
) {
1288 case IOPMLowestState
:
1290 while ( i
< pm_vars
->theNumberOfPowerStates
)
1292 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1298 if ( i
>= pm_vars
->theNumberOfPowerStates
)
1300 return IOPMNoSuchState
;
1304 case IOPMNextLowerState
:
1305 i
= pm_vars
->myCurrentState
- 1;
1306 while ( (int) i
>= 0 )
1308 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1316 return IOPMNoSuchState
;
1320 case IOPMHighestState
:
1321 i
= pm_vars
->theNumberOfPowerStates
;
1322 while ( (int) i
>= 0 )
1325 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1332 return IOPMNoSuchState
;
1336 case IOPMNextHigherState
:
1337 i
= pm_vars
->myCurrentState
+ 1;
1338 while ( i
< pm_vars
->theNumberOfPowerStates
)
1340 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1346 if ( i
== pm_vars
->theNumberOfPowerStates
)
1348 return IOPMNoSuchState
;
1353 return IOPMBadSpecification
;
1358 IOLockLock(pm_vars
->childLock
);
1360 // Now loop through the children. When we encounter the calling child, save
1361 // the computed state as this child's desire.
1362 iter
= getChildIterator(gIOPowerPlane
);
1366 while ( (next
= iter
->getNextObject()) )
1368 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1370 if ( connection
== whichChild
)
1372 connection
->setDesiredDomainState(computedState
);
1373 connection
->setPreventIdleSleepFlag(desiredState
& kIOPMPreventIdleSleep
);
1374 connection
->setPreventSystemSleepFlag(desiredState
& kIOPMPreventSystemSleep
);
1375 connection
->setChildHasRequestedPower();
1382 // Since a child's power requirements may have changed, clear and rebuild
1383 // kIOPMChildClamp and kIOPMChildClamp2 (idle and system sleep clamps)
1384 rebuildChildClampBits();
1386 IOLockUnlock(pm_vars
->childLock
);
1388 // this may be different now
1389 computeDesiredState();
1391 if ( inPlane(gIOPowerPlane
) &&
1392 (pm_vars
->parentsKnowState
) ) {
1393 // change state if all children can now tolerate lower power
1397 // are we clamped on, waiting for this child?
1398 if ( priv
->clampOn
) {
1399 // yes, remove the clamp
1400 priv
->clampOn
= false;
1401 changePowerStateToPriv(0);
1408 //*********************************************************************************
1409 // temporaryPowerClampOn
1411 // A power domain wants to clamp its power on till it has children which
1412 // will thendetermine the power domain state.
1414 // We enter the highest state until addPowerChild is called.
1415 //*********************************************************************************
1417 IOReturn
IOService::temporaryPowerClampOn ( void )
1419 priv
->clampOn
= true;
1425 //*********************************************************************************
1428 // Some client of our device is asking that we become usable. Although
1429 // this has not come from a subclassed device object, treat it exactly
1430 // as if it had. In this way, subsequent requests for lower power from
1431 // a subclassed device object will pre-empt this request.
1433 // We treat this as a subclass object request to switch to the
1434 // highest power state.
1435 //*********************************************************************************
1437 IOReturn
IOService::makeUsable ( void )
1439 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogMakeUsable
,0,0);
1441 if ( pm_vars
->theControllingDriver
== NULL
)
1443 priv
->need_to_become_usable
= true;
1446 priv
->deviceDesire
= pm_vars
->theNumberOfPowerStates
- 1;
1447 computeDesiredState();
1448 if ( inPlane(gIOPowerPlane
) && (pm_vars
->parentsKnowState
) )
1450 return changeState();
1455 //******************************************************************************
1456 // temporaryMakeUsable
1458 // Private function, called by IOService::addPowerChild to ensure that the
1459 // device is temporarily in a usable power state so that attached power
1460 // children may properly initialize.
1461 //******************************************************************************
1463 IOReturn
IOService::temporaryMakeUsable ( void )
1465 IOReturn ret
= kIOReturnSuccess
;
1466 unsigned long tempDesire
;
1468 pm_vars
->thePlatform
->PMLog( pm_vars
->ourName
,
1471 priv
->deviceDesire
);
1473 if ( pm_vars
->theControllingDriver
== NULL
)
1475 priv
->need_to_become_usable
= true;
1478 tempDesire
= priv
->deviceDesire
;
1479 priv
->deviceDesire
= pm_vars
->theNumberOfPowerStates
- 1;
1480 computeDesiredState();
1481 if ( inPlane(gIOPowerPlane
) && (pm_vars
->parentsKnowState
) )
1483 ret
= changeState();
1485 priv
->deviceDesire
= tempDesire
;
1490 //*********************************************************************************
1491 // currentCapability
1493 //*********************************************************************************
1495 IOPMPowerFlags
IOService::currentCapability ( void )
1497 if ( pm_vars
->theControllingDriver
== NULL
)
1501 return pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
;
1506 //*********************************************************************************
1507 // changePowerStateTo
1509 // For some reason, our power-controlling driver has decided it needs to change
1510 // power state. We enqueue the power change so that appropriate parties
1511 // will be notified, and then we will instruct the driver to make the change.
1512 //*********************************************************************************
1514 IOReturn
IOService::changePowerStateTo ( unsigned long ordinal
)
1516 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeStateTo
,ordinal
,0);
1518 if ( ordinal
>= pm_vars
->theNumberOfPowerStates
)
1520 return IOPMParameterError
;
1522 priv
->driverDesire
= ordinal
;
1523 computeDesiredState();
1524 if ( inPlane(gIOPowerPlane
) && (pm_vars
->parentsKnowState
) )
1526 return changeState();
1532 //*********************************************************************************
1533 // changePowerStateToPriv
1535 // For some reason, a subclassed device object has decided it needs to change
1536 // power state. We enqueue the power change so that appropriate parties
1537 // will be notified, and then we will instruct the driver to make the change.
1538 //*********************************************************************************
1540 IOReturn
IOService::changePowerStateToPriv ( unsigned long ordinal
)
1542 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeStateToPriv
,ordinal
,0);
1544 if ( pm_vars
->theControllingDriver
== NULL
)
1546 return IOPMNotYetInitialized
;
1548 if ( ordinal
>= pm_vars
->theNumberOfPowerStates
)
1550 return IOPMParameterError
;
1552 priv
->deviceDesire
= ordinal
;
1553 computeDesiredState();
1554 if ( inPlane(gIOPowerPlane
) && (pm_vars
->parentsKnowState
) )
1556 return changeState();
1563 //*********************************************************************************
1564 // computeDesiredState
1566 //*********************************************************************************
1568 void IOService::computeDesiredState ( void )
1572 IOPowerConnection
*connection
;
1573 unsigned long newDesiredState
= 0;
1575 // Compute the maximum of our children's desires, our controlling driver's desire, and the subclass device's desire.
1576 if ( ! priv
->device_overrides
)
1578 iter
= getChildIterator(gIOPowerPlane
);
1582 while ( (next
= iter
->getNextObject()) )
1584 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1586 if ( connection
->getDesiredDomainState() > newDesiredState
)
1588 newDesiredState
= connection
->getDesiredDomainState();
1595 if ( priv
->driverDesire
> newDesiredState
)
1597 newDesiredState
= priv
->driverDesire
;
1601 if ( priv
->deviceDesire
> newDesiredState
)
1603 newDesiredState
= priv
->deviceDesire
;
1606 priv
->ourDesiredPowerState
= newDesiredState
;
1610 //*********************************************************************************
1613 // A subclass object, our controlling driver, or a power domain child
1614 // has asked for a different power state. Here we compute what new
1615 // state we should enter and enqueue the change (or start it).
1616 //*********************************************************************************
1618 IOReturn
IOService::changeState ( void )
1620 // if not fully initialized
1621 if ( (pm_vars
->theControllingDriver
== NULL
) ||
1622 !(inPlane(gIOPowerPlane
)) ||
1623 !(pm_vars
->parentsKnowState
) )
1625 // we can do no more
1629 return enqueuePowerChange(IOPMWeInitiated
,priv
->ourDesiredPowerState
,0,0,0);
1633 //*********************************************************************************
1634 // currentPowerConsumption
1636 //*********************************************************************************
1638 unsigned long IOService::currentPowerConsumption ( void )
1640 if ( pm_vars
->theControllingDriver
== NULL
)
1642 return kIOPMUnknown
;
1644 if ( pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
& kIOPMStaticPowerValid
)
1646 return pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].staticPower
;
1648 return kIOPMUnknown
;
1651 //*********************************************************************************
1654 // The activity tickle with parameter kIOPMSubclassPolicyis not handled
1655 // here and should have been intercepted by the subclass.
1656 // The tickle with parameter kIOPMSuperclassPolicy1 causes the activity
1657 // flag to be set, and the device state checked. If the device has been
1658 // powered down, it is powered up again.
1659 //*********************************************************************************
1661 bool IOService::activityTickle ( unsigned long type
, unsigned long stateNumber
)
1663 IOPMrootDomain
*pmRootDomain
;
1664 AbsoluteTime uptime
;
1666 if ( type
== kIOPMSuperclassPolicy1
)
1668 if ( pm_vars
->theControllingDriver
== NULL
)
1673 if( priv
->activityLock
== NULL
)
1675 priv
->activityLock
= IOLockAlloc();
1678 IOTakeLock(priv
->activityLock
);
1679 priv
->device_active
= true;
1681 clock_get_uptime(&uptime
);
1682 priv
->device_active_timestamp
= uptime
;
1684 if ( pm_vars
->myCurrentState
>= stateNumber
)
1686 IOUnlock(priv
->activityLock
);
1689 IOUnlock(priv
->activityLock
);
1691 // Transfer execution to the PM workloop
1692 if( (pmRootDomain
= getPMRootDomain()) )
1693 pmRootDomain
->unIdleDevice(this, stateNumber
);
1700 //*********************************************************************************
1703 // A child is calling to get a pointer to the Power Management workloop.
1704 // We got it or get it from one of our parents.
1705 //*********************************************************************************
1707 IOWorkLoop
* IOService::getPMworkloop ( void )
1712 if ( ! inPlane(gIOPowerPlane
) )
1716 // we have no workloop yet
1717 if ( pm_vars
->PMworkloop
== NULL
)
1719 nub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
1722 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
1724 // ask one of our parents for the workloop
1727 pm_vars
->PMworkloop
= parent
->getPMworkloop();
1732 return pm_vars
->PMworkloop
;
1736 //*********************************************************************************
1737 // setIdleTimerPeriod
1739 // A subclass policy-maker is going to use our standard idleness
1740 // detection service. Make a command queue and an idle timer and
1741 // connect them to the power management workloop. Finally,
1743 //*********************************************************************************
1745 IOReturn
IOService::setIdleTimerPeriod ( unsigned long period
)
1747 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMsetIdleTimerPeriod
,period
, 0);
1749 priv
->idle_timer_period
= period
;
1753 if ( getPMworkloop() == NULL
)
1755 return kIOReturnError
;
1758 // make the timer event
1759 if ( priv
->timerEventSrc
== NULL
)
1761 priv
->timerEventSrc
= IOTimerEventSource::timerEventSource(this,
1762 PM_idle_timer_expired
);
1763 if ((!priv
->timerEventSrc
) ||
1764 (pm_vars
->PMworkloop
->addEventSource(priv
->timerEventSrc
) != kIOReturnSuccess
) )
1766 return kIOReturnError
;
1770 if ( priv
->activityLock
== NULL
)
1772 priv
->activityLock
= IOLockAlloc();
1775 start_PM_idle_timer();
1780 //******************************************************************************
1783 // Returns how many "seconds from now" the device should idle into its
1784 // next lowest power state.
1785 //******************************************************************************
1786 SInt32
IOService::nextIdleTimeout(
1787 AbsoluteTime currentTime
,
1788 AbsoluteTime lastActivity
,
1789 unsigned int powerState
)
1796 // Calculate time difference using funky macro from clock.h.
1797 delta
= currentTime
;
1798 SUB_ABSOLUTETIME(&delta
, &lastActivity
);
1800 // Figure it in seconds.
1801 absolutetime_to_nanoseconds(delta
, &delta_ns
);
1802 delta_secs
= (SInt32
)(delta_ns
/ NSEC_PER_SEC
);
1804 // Be paranoid about delta somehow exceeding timer period.
1805 if (delta_secs
< (int) priv
->idle_timer_period
)
1806 delay_secs
= (int) priv
->idle_timer_period
- delta_secs
;
1808 delay_secs
= (int) priv
->idle_timer_period
;
1810 return (SInt32
)delay_secs
;
1813 //******************************************************************************
1814 // start_PM_idle_timer
1816 // The parameter is a pointer to us. Use it to call our timeout method.
1817 //******************************************************************************
1818 void IOService::start_PM_idle_timer ( void )
1820 static const int maxTimeout
= 100000;
1821 static const int minTimeout
= 1;
1822 AbsoluteTime uptime
;
1825 IOLockLock(priv
->activityLock
);
1827 clock_get_uptime(&uptime
);
1829 // Subclasses may modify idle sleep algorithm
1830 idle_in
= nextIdleTimeout(uptime
,
1831 priv
->device_active_timestamp
,
1832 pm_vars
->myCurrentState
);
1834 // Check for out-of range responses
1835 if(idle_in
> maxTimeout
)
1837 // use standard implementation
1838 idle_in
= IOService::nextIdleTimeout(uptime
,
1839 priv
->device_active_timestamp
,
1840 pm_vars
->myCurrentState
);
1841 } else if(idle_in
< minTimeout
) {
1846 priv
->timerEventSrc
->setTimeout(idle_in
, NSEC_PER_SEC
);
1848 IOLockUnlock(priv
->activityLock
);
1853 //*********************************************************************************
1854 // PM_idle_timer_expired
1856 // The parameter is a pointer to us. Use it to call our timeout method.
1857 //*********************************************************************************
1859 void PM_idle_timer_expired(OSObject
* ourSelves
, IOTimerEventSource
*)
1861 ((IOService
*)ourSelves
)->PM_idle_timer_expiration();
1865 //*********************************************************************************
1866 // PM_idle_timer_expiration
1868 // The idle timer has expired. If there has been activity since the last
1869 // expiration, just restart the timer and return. If there has not been
1870 // activity, switch to the next lower power state and restart the timer.
1871 //*********************************************************************************
1873 void IOService::PM_idle_timer_expiration ( void )
1875 if ( ! initialized
)
1881 if ( priv
->idle_timer_period
> 0 )
1883 IOTakeLock(priv
->activityLock
);
1884 if ( priv
->device_active
)
1886 priv
->device_active
= false;
1887 IOUnlock(priv
->activityLock
);
1888 start_PM_idle_timer();
1891 if ( pm_vars
->myCurrentState
> 0 )
1894 unsigned long newState
= pm_vars
->myCurrentState
- 1;
1896 IOUnlock(priv
->activityLock
);
1897 changePowerStateToPriv(newState
);
1898 if ( newState
>= priv
->ourDesiredPowerState
)
1899 start_PM_idle_timer();
1902 IOUnlock(priv
->activityLock
);
1903 start_PM_idle_timer();
1908 // **********************************************************************************
1911 // We are un-idling a device due to its activity tickle. This routine runs on the
1912 // PM workloop, and is initiated by IOService::activityTickle.
1913 // We process all activityTickle state requests on the list.
1914 // **********************************************************************************
1915 void IOService::command_received ( void *statePtr
, void *, void * , void * )
1917 unsigned long stateNumber
;
1919 stateNumber
= (unsigned long)statePtr
;
1921 // If not initialized, we're unloading
1922 if ( ! initialized
) return;
1924 if ( (pm_vars
->myCurrentState
< stateNumber
) &&
1925 (priv
->imminentState
< stateNumber
) )
1927 changePowerStateToPriv(stateNumber
);
1929 // After we raise our state, re-schedule the idle timer.
1930 if(priv
->timerEventSrc
)
1931 start_PM_idle_timer();
1936 //*********************************************************************************
1937 // setAggressiveness
1939 // Pass on the input parameters to all power domain children. All those which are
1940 // power domains will pass it on to their children, etc.
1941 //*********************************************************************************
1943 IOReturn
IOService::setAggressiveness ( unsigned long type
, unsigned long newLevel
)
1947 IOPowerConnection
*connection
;
1950 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogSetAggressiveness
,type
, newLevel
);
1952 if ( type
<= kMaxType
)
1954 pm_vars
->current_aggressiveness_values
[type
] = newLevel
;
1955 pm_vars
->current_aggressiveness_valid
[type
] = true;
1958 iter
= getChildIterator(gIOPowerPlane
);
1962 while ( (next
= iter
->getNextObject()) )
1964 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1966 child
= ((IOService
*)(connection
->copyChildEntry(gIOPowerPlane
)));
1969 child
->setAggressiveness(type
, newLevel
);
1980 //*********************************************************************************
1981 // getAggressiveness
1983 // Called by the user client.
1984 //*********************************************************************************
1986 IOReturn
IOService::getAggressiveness ( unsigned long type
, unsigned long * currentLevel
)
1988 if ( type
> kMaxType
)
1989 return kIOReturnBadArgument
;
1991 if ( !pm_vars
->current_aggressiveness_valid
[type
] )
1992 return kIOReturnInvalid
;
1994 *currentLevel
= pm_vars
->current_aggressiveness_values
[type
];
1996 return kIOReturnSuccess
;
1999 //*********************************************************************************
2002 // Pass this to all power domain children. All those which are
2003 // power domains will pass it on to their children, etc.
2004 //*********************************************************************************
2006 IOReturn
IOService::systemWake ( void )
2010 IOPowerConnection
*connection
;
2011 IOService
*theChild
;
2013 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogSystemWake
,0, 0);
2015 iter
= getChildIterator(gIOPowerPlane
);
2019 while ( (next
= iter
->getNextObject()) )
2021 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
2023 theChild
= (IOService
*)connection
->copyChildEntry(gIOPowerPlane
);
2026 theChild
->systemWake();
2027 theChild
->release();
2034 if ( pm_vars
->theControllingDriver
!= NULL
)
2036 if ( pm_vars
->theControllingDriver
->didYouWakeSystem() )
2046 //*********************************************************************************
2047 // temperatureCriticalForZone
2049 //*********************************************************************************
2051 IOReturn
IOService::temperatureCriticalForZone ( IOService
* whichZone
)
2053 IOService
*theParent
;
2056 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogCriticalTemp
,0,0);
2058 if ( inPlane(gIOPowerPlane
) && !(priv
->we_are_root
) )
2060 theNub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
2063 theParent
= (IOService
*)theNub
->copyParentEntry(gIOPowerPlane
);
2067 theParent
->temperatureCriticalForZone(whichZone
);
2068 theParent
->release();
2076 //*********************************************************************************
2077 // powerOverrideOnPriv
2079 //*********************************************************************************
2082 IOReturn
IOService::powerOverrideOnPriv ( void )
2084 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogOverrideOn
,0,0);
2086 // turn on the override
2087 priv
->device_overrides
= true;
2088 computeDesiredState();
2090 // change state if that changed something
2091 return changeState();
2095 //*********************************************************************************
2096 // powerOverrideOffPriv
2098 //*********************************************************************************
2099 IOReturn
IOService::powerOverrideOffPriv ( void )
2101 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogOverrideOff
,0,0);
2103 // turn off the override
2104 priv
->device_overrides
= false;
2105 computeDesiredState();
2108 return makeUsable();
2110 // change state if that changed something
2111 return changeState();
2116 //*********************************************************************************
2117 // enqueuePowerChange
2119 // Allocate a new state change notification, initialize it with fields from the
2120 // caller, and add it to the tail of the list of pending power changes.
2122 // If it is early enough in the list, and almost all the time it is the only one in
2123 // the list, start the power change.
2125 // In rare instances, this change will preempt the previous change in the list.
2126 // If the previous change is un-actioned in any way (because we are still
2127 // processing an even earlier power change), and if both the previous change
2128 // in the list and this change are initiated by us (not the parent), then we
2129 // needn't perform the previous change, so we collapse the list a little.
2130 //*********************************************************************************
2132 IOReturn
IOService::enqueuePowerChange (
2133 unsigned long flags
,
2134 unsigned long whatStateOrdinal
,
2135 unsigned long domainState
,
2136 IOPowerConnection
* whichParent
,
2137 unsigned long singleParentState
)
2142 // Create and initialize the new change note
2144 IOLockLock(priv
->queue_lock
);
2145 newNote
= priv
->changeList
->createChangeNote();
2146 if ( newNote
== -1 ) {
2147 // uh-oh, our list is full
2148 IOLockUnlock(priv
->queue_lock
);
2149 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogEnqueueErr
,0,0);
2150 return IOPMAckImplied
;
2153 priv
->changeList
->changeNote
[newNote
].newStateNumber
= whatStateOrdinal
;
2154 priv
->changeList
->changeNote
[newNote
].outputPowerCharacter
= pm_vars
->thePowerStates
[whatStateOrdinal
].outputPowerCharacter
;
2155 priv
->changeList
->changeNote
[newNote
].inputPowerRequirement
= pm_vars
->thePowerStates
[whatStateOrdinal
].inputPowerRequirement
;
2156 priv
->changeList
->changeNote
[newNote
].capabilityFlags
= pm_vars
->thePowerStates
[whatStateOrdinal
].capabilityFlags
;
2157 priv
->changeList
->changeNote
[newNote
].flags
= flags
;
2158 priv
->changeList
->changeNote
[newNote
].parent
= NULL
;
2159 if (flags
& IOPMParentInitiated
)
2161 priv
->changeList
->changeNote
[newNote
].domainState
= domainState
;
2162 priv
->changeList
->changeNote
[newNote
].parent
= whichParent
;
2163 whichParent
->retain();
2164 priv
->changeList
->changeNote
[newNote
].singleParentState
= singleParentState
;
2167 previousNote
= priv
->changeList
->previousChangeNote(newNote
);
2169 if ( previousNote
== -1 )
2172 // Queue is empty, we can start this change.
2174 if (flags
& IOPMWeInitiated
)
2176 IOLockUnlock(priv
->queue_lock
);
2177 start_our_change(newNote
);
2180 IOLockUnlock(priv
->queue_lock
);
2181 return start_parent_change(newNote
);
2185 // The queue is not empty. Try to collapse this new change and the previous one in queue into one change.
2186 // This is possible only if both changes are initiated by us, and neither has been started yet.
2187 // Do this more than once if possible.
2189 // (A change is started iff it is at the head of the queue)
2191 while ( (previousNote
!= priv
->head_note
) && (previousNote
!= -1) &&
2192 (priv
->changeList
->changeNote
[newNote
].flags
& priv
->changeList
->changeNote
[previousNote
].flags
& IOPMWeInitiated
) )
2194 priv
->changeList
->changeNote
[previousNote
].outputPowerCharacter
= priv
->changeList
->changeNote
[newNote
].outputPowerCharacter
;
2195 priv
->changeList
->changeNote
[previousNote
].inputPowerRequirement
= priv
->changeList
->changeNote
[newNote
].inputPowerRequirement
;
2196 priv
->changeList
->changeNote
[previousNote
].capabilityFlags
=priv
-> changeList
->changeNote
[newNote
].capabilityFlags
;
2197 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogCollapseQueue
,priv
->changeList
->changeNote
[newNote
].newStateNumber
,
2198 priv
->changeList
->changeNote
[previousNote
].newStateNumber
);
2199 priv
->changeList
->changeNote
[previousNote
].newStateNumber
= priv
->changeList
->changeNote
[newNote
].newStateNumber
;
2200 priv
->changeList
->releaseTailChangeNote();
2201 newNote
= previousNote
;
2202 previousNote
= priv
->changeList
->previousChangeNote(newNote
);
2204 IOLockUnlock(priv
->queue_lock
);
2205 // in any case, we can't start yet
2206 return IOPMWillAckLater
;
2209 //*********************************************************************************
2212 // Notify all interested parties either that a change is impending or that the
2213 // previously-notified change is done and power has settled.
2214 // The parameter identifies whether this is the
2215 // pre-change notification or the post-change notification.
2217 //*********************************************************************************
2219 IOReturn
IOService::notifyAll ( bool is_prechange
)
2221 IOPMinformee
* nextObject
;
2224 IOPowerConnection
* connection
;
2226 // To prevent acknowledgePowerChange from finishing the change note and
2227 // removing it from the queue if
2228 // some driver calls it, we inflate the number of pending acks so it
2229 // cannot become zero. We'll fix it later.
2231 if(!acquire_lock()) return IOPMAckImplied
;
2233 OSAddAtomic(1, (SInt32
*)&priv
->head_note_pendingAcks
);
2235 // OK, we will go through the lists of interested drivers and
2236 // power domain children and notify each one of this change.
2238 nextObject
= priv
->interestedDrivers
->firstInList();
2239 while ( nextObject
!= NULL
) {
2241 OSAddAtomic(1, (SInt32
*)&priv
->head_note_pendingAcks
);
2243 IOUnlock(priv
->our_lock
);
2245 inform(nextObject
, is_prechange
);
2252 nextObject
= priv
->interestedDrivers
->nextInList(nextObject
);
2255 // did they all ack?
2256 if ( priv
->head_note_pendingAcks
> 1 ) {
2258 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2262 IOUnlock(priv
->our_lock
);
2265 iter
= getChildIterator(gIOPowerPlane
);
2266 // summing their power consumption
2267 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
= 0;
2269 if ( iter
&& acquire_lock())
2271 while ( (next
= iter
->getNextObject()) )
2273 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
2275 OSAddAtomic(1, (SInt32
*)&priv
->head_note_pendingAcks
);
2277 IOUnlock(priv
->our_lock
);
2279 notifyChild(connection
, is_prechange
);
2288 IOUnlock(priv
->our_lock
);
2291 if (! acquire_lock() ) {
2294 // now make this real
2295 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
2298 if (priv
->head_note_pendingAcks
== 0 ) {
2300 IOUnlock(priv
->our_lock
);
2301 // return ack to parent
2302 return IOPMAckImplied
;
2306 IOUnlock(priv
->our_lock
);
2308 exit
: // unable to acquire_lock exit case
2310 return IOPMWillAckLater
;
2314 //*********************************************************************************
2317 // Notify a power domain child of an upcoming power change.
2319 // If the object acknowledges the current change, we return TRUE.
2320 //*********************************************************************************
2322 bool IOService::notifyChild ( IOPowerConnection
* theNub
, bool is_prechange
)
2324 IOReturn k
= IOPMAckImplied
;
2325 unsigned long childPower
;
2326 IOService
*theChild
;
2328 theChild
= (IOService
*)(theNub
->copyChildEntry(gIOPowerPlane
));
2331 // The child has been detached since we grabbed the child iterator.
2332 // Decrement pending_acks, already incremented in notifyAll,
2333 // to account for this unexpected departure.
2335 if( acquire_lock() )
2337 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
2338 IOUnlock(priv
->our_lock
);
2343 // Unless the child handles the notification immediately and returns
2344 // kIOPMAckImplied, we'll be awaiting their acknowledgement later.
2345 theNub
->setAwaitingAck(true);
2349 k
= theChild
->powerDomainWillChangeTo(priv
->head_note_outputFlags
,theNub
);
2351 k
= theChild
->powerDomainDidChangeTo(priv
->head_note_outputFlags
,theNub
);
2354 // did the return code ack?
2355 if ( k
== IOPMAckImplied
)
2358 if( acquire_lock() )
2360 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
2361 IOUnlock(priv
->our_lock
);
2364 theNub
->setAwaitingAck(false);
2365 childPower
= theChild
->currentPowerConsumption();
2366 if ( childPower
== kIOPMUnknown
)
2368 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
= kIOPMUnknown
;
2370 if ( pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
!= kIOPMUnknown
)
2372 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
+= childPower
;
2375 theChild
->release();
2378 theChild
->release();
2383 //*********************************************************************************
2386 // Notify an interested driver of an upcoming power change.
2388 // If the object acknowledges the current change, we return TRUE.
2389 //*********************************************************************************
2391 bool IOService::inform ( IOPMinformee
* nextObject
, bool is_prechange
)
2393 IOReturn k
= IOPMAckImplied
;
2396 nextObject
->timer
= -1;
2400 pm_vars
->thePlatform
->PMLog (pm_vars
->ourName
,PMlogInformDriverPreChange
,
2401 (unsigned long)priv
->head_note_capabilityFlags
,(unsigned long)priv
->head_note_state
);
2402 k
= nextObject
->whatObject
->powerStateWillChangeTo( priv
->head_note_capabilityFlags
,priv
->head_note_state
,this);
2404 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInformDriverPostChange
,
2405 (unsigned long)priv
->head_note_capabilityFlags
,(unsigned long)priv
->head_note_state
);
2406 k
= nextObject
->whatObject
->powerStateDidChangeTo(priv
->head_note_capabilityFlags
,priv
->head_note_state
,this);
2409 // did it ack behind our back?
2410 if ( nextObject
->timer
== 0 )
2416 if ( (k
==IOPMAckImplied
) // no, did the return code ack?
2417 || (k
< 0) ) // somebody goofed
2420 nextObject
->timer
= 0;
2422 if( acquire_lock() )
2424 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
2425 IOUnlock(priv
->our_lock
);
2431 nextObject
->timer
= (k
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
2437 //*********************************************************************************
2438 // OurChangeTellClientsPowerDown
2440 // All registered applications and kernel clients have positively acknowledged our
2441 // intention of lowering power. Here we notify them all that we will definitely
2442 // lower the power. If we don't have to wait for any of them to acknowledge, we
2443 // carry on by notifying interested drivers. Otherwise, we do wait.
2444 //*********************************************************************************
2446 void IOService::OurChangeTellClientsPowerDown ( void )
2449 priv
->machine_state
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
2451 // are we waiting for responses?
2452 if ( tellChangeDown1(priv
->head_note_state
) )
2454 // no, notify priority clients
2455 OurChangeTellPriorityClientsPowerDown();
2457 // If we are waiting for responses, execution will resume via
2458 // allowCancelCommon() or ack timeout
2462 //*********************************************************************************
2463 // OurChangeTellPriorityClientsPowerDown
2465 // All registered applications and kernel clients have positively acknowledged our
2466 // intention of lowering power. Here we notify "priority" clients that we are
2467 // lowering power. If we don't have to wait for any of them to acknowledge, we
2468 // carry on by notifying interested drivers. Otherwise, we do wait.
2469 //*********************************************************************************
2471 void IOService::OurChangeTellPriorityClientsPowerDown ( void )
2474 priv
->machine_state
= kIOPM_OurChangeNotifyInterestedDriversWillChange
;
2475 // are we waiting for responses?
2476 if ( tellChangeDown2(priv
->head_note_state
) )
2478 // no, notify interested drivers
2479 return OurChangeNotifyInterestedDriversWillChange();
2481 // If we are waiting for responses, execution will resume via
2482 // allowCancelCommon() or ack timeout
2486 //*********************************************************************************
2487 // OurChangeNotifyInterestedDriversWillChange
2489 // All registered applications and kernel clients have acknowledged our notification
2490 // that we are lowering power. Here we notify interested drivers. If we don't have
2491 // to wait for any of them to acknowledge, we instruct our power driver to make the change.
2492 // Otherwise, we do wait.
2493 //*********************************************************************************
2495 void IOService::OurChangeNotifyInterestedDriversWillChange ( void )
2497 // no, in case they don't all ack
2498 priv
->machine_state
= kIOPM_OurChangeSetPowerState
;
2499 if ( notifyAll(true) == IOPMAckImplied
)
2501 // not waiting for responses
2502 OurChangeSetPowerState();
2504 // If we are waiting for responses, execution will resume via
2505 // all_acked() or ack timeout
2509 //*********************************************************************************
2510 // OurChangeSetPowerState
2512 // All interested drivers have acknowledged our pre-change notification of a power
2513 // change we initiated. Here we instruct our controlling driver to make
2514 // the change to the hardware. If it does so, we continue processing
2515 // (waiting for settle and notifying interested parties post-change.)
2516 // If it doesn't, we have to wait for it to acknowledge and then continue.
2517 //*********************************************************************************
2519 void IOService::OurChangeSetPowerState ( void )
2521 priv
->machine_state
= kIOPM_OurChangeWaitForPowerSettle
;
2523 IOLockLock(priv
->our_lock
);
2525 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2527 // it's done, carry on
2528 IOLockUnlock(priv
->our_lock
);
2529 OurChangeWaitForPowerSettle();
2531 // it's not, wait for it
2532 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2534 IOLockUnlock(priv
->our_lock
);
2535 // execution will resume via ack_timer_ticked()
2540 //*********************************************************************************
2541 // OurChangeWaitForPowerSettle
2543 // Our controlling driver has changed power state on the hardware
2544 // during a power change we initiated. Here we see if we need to wait
2545 // for power to settle before continuing. If not, we continue processing
2546 // (notifying interested parties post-change). If so, we wait and
2548 //*********************************************************************************
2550 void IOService::OurChangeWaitForPowerSettle ( void )
2552 priv
->settle_time
= compute_settle_time();
2553 if ( priv
->settle_time
== 0 )
2555 OurChangeNotifyInterestedDriversDidChange();
2557 priv
->machine_state
= kIOPM_OurChangeNotifyInterestedDriversDidChange
;
2558 startSettleTimer(priv
->settle_time
);
2563 //*********************************************************************************
2564 // OurChangeNotifyInterestedDriversDidChange
2566 // Power has settled on a power change we initiated. Here we notify
2567 // all our interested parties post-change. If they all acknowledge, we're
2568 // done with this change note, and we can start on the next one.
2569 // Otherwise we have to wait for acknowledgements and finish up later.
2570 //*********************************************************************************
2572 void IOService::OurChangeNotifyInterestedDriversDidChange ( void )
2574 // in case they don't all ack
2575 priv
->machine_state
= kIOPM_OurChangeFinish
;
2576 if ( notifyAll(false) == IOPMAckImplied
)
2578 // not waiting for responses
2581 // If we are waiting for responses, execution will resume via
2582 // all_acked() or ack timeout
2586 //*********************************************************************************
2589 // Power has settled on a power change we initiated, and
2590 // all our interested parties have acknowledged. We're
2591 // done with this change note, and we can start on the next one.
2592 //*********************************************************************************
2594 void IOService::OurChangeFinish ( void )
2600 //*********************************************************************************
2601 // ParentDownTellPriorityClientsPowerDown_Immediate
2603 // All applications and kernel clients have been notified of a power lowering
2604 // initiated by the parent and we didn't have to wait for any responses. Here
2605 // we notify any priority clients. If they all ack, we continue with the power change.
2606 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2607 //*********************************************************************************
2609 IOReturn
IOService::ParentDownTellPriorityClientsPowerDown_Immediate ( void )
2611 // in case they don't all ack
2612 priv
->machine_state
= kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
;
2613 // are we waiting for responses?
2614 if ( tellChangeDown2(priv
->head_note_state
) )
2616 // no, notify interested drivers
2617 return ParentDownNotifyInterestedDriversWillChange_Immediate();
2619 // If we are waiting for responses, execution will resume via
2620 // allowCancelCommon() or ack timeout
2621 return IOPMWillAckLater
;
2625 //*********************************************************************************
2626 // ParentDownTellPriorityClientsPowerDown_Immediate2
2628 // All priority kernel clients have been notified of a power lowering
2629 // initiated by the parent and we didn't have to wait for any responses. Here
2630 // we notify any interested drivers and power domain children. If they all ack,
2631 // we continue with the power change.
2632 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2633 //*********************************************************************************
2635 IOReturn
IOService::ParentDownNotifyInterestedDriversWillChange_Immediate ( void )
2637 // in case they don't all ack
2638 priv
->machine_state
= kIOPM_ParentDownSetPowerState_Delayed
;
2639 if ( notifyAll(true) == IOPMAckImplied
)
2642 return ParentDownSetPowerState_Immediate();
2644 // If we are waiting for responses, execution will resume via
2645 // all_acked() or ack timeout
2646 return IOPMWillAckLater
;
2650 //*********************************************************************************
2651 // ParentDownTellPriorityClientsPowerDown_Immediate4
2653 // All applications and kernel clients have been notified of a power lowering
2654 // initiated by the parent and we had to wait for responses. Here
2655 // we notify any priority clients. If they all ack, we continue with the power change.
2656 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2657 //*********************************************************************************
2659 void IOService::ParentDownTellPriorityClientsPowerDown_Delayed ( void )
2661 // in case they don't all ack
2662 priv
->machine_state
= kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
;
2664 // are we waiting for responses?
2665 if ( tellChangeDown2(priv
->head_note_state
) )
2667 // no, notify interested drivers
2668 ParentDownNotifyInterestedDriversWillChange_Delayed();
2670 // If we are waiting for responses, execution will resume via
2671 // allowCancelCommon() or ack timeout
2675 //*********************************************************************************
2676 // ParentDownTellPriorityClientsPowerDown_Immediate5
2678 // All applications and kernel clients have been notified of a power lowering
2679 // initiated by the parent and we had to wait for their responses. Here we notify
2680 // any interested drivers and power domain children. If they all ack, we continue
2681 // with the power change.
2682 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2683 //*********************************************************************************
2685 void IOService::ParentDownNotifyInterestedDriversWillChange_Delayed ( void )
2687 // in case they don't all ack
2688 priv
->machine_state
= kIOPM_ParentDownSetPowerState_Delayed
;
2689 if ( notifyAll(true) == IOPMAckImplied
)
2692 ParentDownSetPowerState_Delayed();
2694 // If we are waiting for responses, execution will resume via
2695 // all_acked() or ack timeout
2699 //*********************************************************************************
2700 // ParentDownSetPowerState_Immediate
2702 // All parties have acknowledged our pre-change notification of a power
2703 // lowering initiated by the parent. Here we instruct our controlling driver
2704 // to put the hardware in the state it needs to be in when the domain is
2705 // lowered. If it does so, we continue processing
2706 // (waiting for settle and acknowledging the parent.)
2707 // If it doesn't, we have to wait for it to acknowledge and then continue.
2708 //*********************************************************************************
2710 IOReturn
IOService::ParentDownSetPowerState_Immediate ( void )
2712 priv
->machine_state
= kIOPM_ParentDownWaitForPowerSettle_Delayed
;
2714 IOLockLock(priv
->our_lock
);
2716 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2718 // it's done, carry on
2719 IOLockUnlock(priv
->our_lock
);
2720 return ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate();
2722 // it's not, wait for it
2723 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2725 IOLockUnlock(priv
->our_lock
);
2726 return IOPMWillAckLater
;
2730 //*********************************************************************************
2731 // ParentDownSetPowerState_Delayed
2733 // We had to wait for it, but all parties have acknowledged our pre-change
2734 // notification of a power lowering initiated by the parent.
2735 // Here we instruct our controlling driver
2736 // to put the hardware in the state it needs to be in when the domain is
2737 // lowered. If it does so, we continue processing
2738 // (waiting for settle and acknowledging the parent.)
2739 // If it doesn't, we have to wait for it to acknowledge and then continue.
2740 //*********************************************************************************
2742 void IOService::ParentDownSetPowerState_Delayed ( void )
2744 priv
-> machine_state
= kIOPM_ParentDownWaitForPowerSettle_Delayed
;
2746 IOLockLock(priv
->our_lock
);
2748 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2750 // it's done, carry on
2751 IOLockUnlock(priv
->our_lock
);
2752 ParentDownWaitForPowerSettle_Delayed();
2754 // it's not, wait for it
2755 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2757 IOLockUnlock(priv
->our_lock
);
2762 //*********************************************************************************
2763 // ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate
2765 // Our controlling driver has changed power state on the hardware
2766 // during a power change initiated by our parent. Here we see if we need
2767 // to wait for power to settle before continuing. If not, we continue
2768 // processing (acknowledging our preparedness to the parent).
2769 // If so, we wait and continue later.
2770 //*********************************************************************************
2772 IOReturn
IOService::ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate ( void )
2776 priv
->settle_time
= compute_settle_time();
2777 if ( priv
->settle_time
== 0 )
2779 // store current state in case they don't all ack
2780 priv
->machine_state
= kIOPM_ParentDownAcknowledgeChange_Delayed
;
2781 if ( notifyAll(false) == IOPMAckImplied
)
2783 // not waiting for responses
2784 nub
= priv
->head_note_parent
;
2788 return IOPMAckImplied
;
2790 // If we are waiting for responses, execution will resume via
2791 // all_acked() or ack timeout
2792 return IOPMWillAckLater
;
2794 // let settle time elapse, then notify interest drivers of our power state change in ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
2795 priv
->machine_state
= kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
;
2796 startSettleTimer(priv
->settle_time
);
2797 return IOPMWillAckLater
;
2802 //*********************************************************************************
2803 // ParentDownWaitForPowerSettle_Delayed
2805 // Our controlling driver has changed power state on the hardware
2806 // during a power change initiated by our parent. We have had to wait
2807 // for acknowledgement from interested parties, or we have had to wait
2808 // for the controlling driver to change the state. Here we see if we need
2809 // to wait for power to settle before continuing. If not, we continue
2810 // processing (acknowledging our preparedness to the parent).
2811 // If so, we wait and continue later.
2812 //*********************************************************************************
2814 void IOService::ParentDownWaitForPowerSettle_Delayed ( void )
2816 priv
->settle_time
= compute_settle_time();
2817 if ( priv
->settle_time
== 0 )
2819 ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed();
2821 priv
->machine_state
= kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
;
2822 startSettleTimer(priv
->settle_time
);
2827 //*********************************************************************************
2828 // ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
2830 // Power has settled on a power change initiated by our parent. Here we
2831 // notify interested parties.
2832 //*********************************************************************************
2834 void IOService::ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed ( void )
2836 IORegistryEntry
*nub
;
2839 // in case they don't all ack
2840 priv
->machine_state
= kIOPM_ParentDownAcknowledgeChange_Delayed
;
2841 if ( notifyAll(false) == IOPMAckImplied
) {
2842 nub
= priv
->head_note_parent
;
2845 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
2847 parent
->acknowledgePowerChange((IOService
*)nub
);
2852 // If we are waiting for responses, execution will resume via
2853 // all_acked() or ack timeout in ParentDownAcknowledgeChange_Delayed.
2854 // Notice the duplication of code just above and in ParentDownAcknowledgeChange_Delayed.
2858 //*********************************************************************************
2859 // ParentDownAcknowledgeChange_Delayed
2861 // We had to wait for it, but all parties have acknowledged our post-change
2862 // notification of a power lowering initiated by the parent.
2863 // Here we acknowledge the parent.
2864 // We are done with this change note, and we can start on the next one.
2865 //*********************************************************************************
2867 void IOService::ParentDownAcknowledgeChange_Delayed ( void )
2869 IORegistryEntry
*nub
;
2872 nub
= priv
->head_note_parent
;
2875 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
2878 parent
->acknowledgePowerChange((IOService
*)nub
);
2885 //*********************************************************************************
2886 // ParentUpSetPowerState_Delayed
2888 // Our parent has informed us via powerStateDidChange that it has
2889 // raised the power in our power domain, and we have had to wait
2890 // for some interested party to acknowledge our notification.
2891 // Here we instruct our controlling
2892 // driver to program the hardware to take advantage of the higher domain
2893 // power. If it does so, we continue processing
2894 // (waiting for settle and notifying interested parties post-change.)
2895 // If it doesn't, we have to wait for it to acknowledge and then continue.
2896 //*********************************************************************************
2898 void IOService::ParentUpSetPowerState_Delayed ( void )
2900 priv
->machine_state
= kIOPM_ParentUpWaitForSettleTime_Delayed
;
2902 IOLockLock(priv
->our_lock
);
2904 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2906 // it did it, carry on
2907 IOLockUnlock(priv
->our_lock
);
2908 ParentUpWaitForSettleTime_Delayed();
2910 // it didn't, wait for it
2911 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2913 IOLockUnlock(priv
->our_lock
);
2918 //*********************************************************************************
2919 // ParentUpSetPowerState_Immediate
2921 // Our parent has informed us via powerStateDidChange that it has
2922 // raised the power in our power domain. Here we instruct our controlling
2923 // driver to program the hardware to take advantage of the higher domain
2924 // power. If it does so, we continue processing
2925 // (waiting for settle and notifying interested parties post-change.)
2926 // If it doesn't, we have to wait for it to acknowledge and then continue.
2927 //*********************************************************************************
2929 IOReturn
IOService::ParentUpSetPowerState_Immediate ( void )
2931 priv
->machine_state
= kIOPM_ParentUpWaitForSettleTime_Delayed
;
2933 IOLockLock(priv
->our_lock
);
2935 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2937 // it did it, carry on
2938 IOLockUnlock(priv
->our_lock
);
2939 return ParentUpWaitForSettleTime_Immediate();
2942 // it didn't, wait for it
2943 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2945 IOLockUnlock(priv
->our_lock
);
2946 return IOPMWillAckLater
;
2951 //*********************************************************************************
2952 // ParentUpWaitForSettleTime_Immediate
2954 // Our controlling driver has changed power state on the hardware
2955 // during a power raise initiated by the parent. Here we see if we need to wait
2956 // for power to settle before continuing. If not, we continue processing
2957 // (notifying interested parties post-change). If so, we wait and
2959 //*********************************************************************************
2961 IOReturn
IOService::ParentUpWaitForSettleTime_Immediate ( void )
2963 priv
->settle_time
= compute_settle_time();
2964 if ( priv
->settle_time
== 0 )
2966 return ParentUpNotifyInterestedDriversDidChange_Immediate();
2968 priv
->machine_state
= kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed
;
2969 startSettleTimer(priv
->settle_time
);
2970 return IOPMWillAckLater
;
2975 //*********************************************************************************
2976 // ParentUpWaitForSettleTime_Delayed
2978 // Our controlling driver has changed power state on the hardware
2979 // during a power raise initiated by the parent, but we had to wait for it.
2980 // Here we see if we need to wait for power to settle before continuing.
2981 // If not, we continue processing (notifying interested parties post-change).
2982 // If so, we wait and continue later.
2983 //*********************************************************************************
2985 void IOService::ParentUpWaitForSettleTime_Delayed ( void )
2987 priv
->settle_time
= compute_settle_time();
2988 if ( priv
->settle_time
== 0 )
2990 ParentUpNotifyInterestedDriversDidChange_Delayed();
2992 priv
->machine_state
= kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed
;
2993 startSettleTimer(priv
->settle_time
);
2998 //*********************************************************************************
2999 // ParentUpNotifyInterestedDriversDidChange_Immediate
3001 // No power settling was required on a power raise initiated by the parent.
3002 // Here we notify all our interested parties post-change. If they all acknowledge,
3003 // we're done with this change note, and we can start on the next one.
3004 // Otherwise we have to wait for acknowledgements and finish up later.
3005 //*********************************************************************************
3007 IOReturn
IOService::ParentUpNotifyInterestedDriversDidChange_Immediate ( void )
3011 // in case they don't all ack
3012 priv
->machine_state
= kIOPM_ParentUpAcknowledgePowerChange_Delayed
;
3013 if ( notifyAll(false) == IOPMAckImplied
)
3015 nub
= priv
->head_note_parent
;
3019 return IOPMAckImplied
;
3021 // If we are waiting for responses, execution will resume via
3022 // all_acked() or ack timeout in ParentUpAcknowledgePowerChange_Delayed.
3023 return IOPMWillAckLater
;
3027 //*********************************************************************************
3028 // ParentUpNotifyInterestedDriversDidChange_Delayed
3030 // Power has settled on a power raise initiated by the parent.
3031 // Here we notify all our interested parties post-change. If they all acknowledge,
3032 // we're done with this change note, and we can start on the next one.
3033 // Otherwise we have to wait for acknowledgements and finish up later.
3034 //*********************************************************************************
3036 void IOService::ParentUpNotifyInterestedDriversDidChange_Delayed ( void )
3038 // in case they don't all ack
3039 priv
->machine_state
= kIOPM_ParentUpAcknowledgePowerChange_Delayed
;
3040 if ( notifyAll(false) == IOPMAckImplied
)
3042 ParentUpAcknowledgePowerChange_Delayed();
3044 // If we are waiting for responses, execution will resume via
3045 // all_acked() or ack timeout in ParentUpAcknowledgePowerChange_Delayed.
3049 //*********************************************************************************
3050 // ParentUpAcknowledgePowerChange_Delayed
3052 // All parties have acknowledged our post-change notification of a power
3053 // raising initiated by the parent. Here we acknowledge the parent.
3054 // We are done with this change note, and we can start on the next one.
3055 //*********************************************************************************
3057 void IOService::ParentUpAcknowledgePowerChange_Delayed ( void )
3059 IORegistryEntry
*nub
;
3062 nub
= priv
->head_note_parent
;
3065 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
3068 parent
->acknowledgePowerChange((IOService
*)nub
);
3075 //*********************************************************************************
3078 // A power change is complete, and the used post-change note is at
3079 // the head of the queue. Remove it and set myCurrentState to the result
3080 // of the change. Start up the next change in queue.
3081 //*********************************************************************************
3083 void IOService::all_done ( void )
3085 unsigned long previous_state
;
3086 IORegistryEntry
*nub
;
3089 priv
->machine_state
= kIOPM_Finished
;
3092 if ( priv
->head_note_flags
& IOPMWeInitiated
)
3094 // could our driver switch to the new state?
3095 if ( !( priv
->head_note_flags
& IOPMNotDone
) )
3097 // yes, did power raise?
3098 if ( pm_vars
->myCurrentState
< priv
->head_note_state
)
3100 // yes, inform clients and apps
3101 tellChangeUp (priv
->head_note_state
);
3103 // no, if this lowers our
3104 if ( ! priv
->we_are_root
)
3106 // power requirements, tell the parent
3107 ask_parent(priv
->head_note_state
);
3110 previous_state
= pm_vars
->myCurrentState
;
3112 pm_vars
->myCurrentState
= priv
->head_note_state
;
3113 priv
->imminentState
= pm_vars
->myCurrentState
;
3114 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeDone
,(unsigned long)pm_vars
->myCurrentState
,0);
3115 // inform subclass policy-maker
3116 powerChangeDone(previous_state
);
3120 // parent's power change
3121 if ( priv
->head_note_flags
& IOPMParentInitiated
)
3123 if ( ((priv
->head_note_flags
& IOPMDomainWillChange
) && (pm_vars
->myCurrentState
>= priv
->head_note_state
)) ||
3124 ((priv
->head_note_flags
& IOPMDomainDidChange
) && (pm_vars
->myCurrentState
< priv
->head_note_state
)) )
3127 if ( pm_vars
->myCurrentState
< priv
->head_note_state
)
3129 // yes, inform clients and apps
3130 tellChangeUp (priv
->head_note_state
);
3133 previous_state
= pm_vars
->myCurrentState
;
3134 pm_vars
->myCurrentState
= priv
->head_note_state
;
3135 priv
->imminentState
= pm_vars
->myCurrentState
;
3136 pm_vars
->maxCapability
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(priv
->head_note_domainState
);
3138 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeDone
,(unsigned long)pm_vars
->myCurrentState
,0);
3139 // inform subclass policy-maker
3140 powerChangeDone(previous_state
);
3144 IOLockLock(priv
->queue_lock
);
3145 // we're done with this
3146 priv
->changeList
->releaseHeadChangeNote();
3148 // start next one in queue
3149 priv
->head_note
= priv
->changeList
->currentChange();
3150 if ( priv
->head_note
!= -1 )
3153 IOLockUnlock(priv
->queue_lock
);
3154 if (priv
->changeList
->changeNote
[priv
->head_note
].flags
& IOPMWeInitiated
)
3156 start_our_change(priv
->head_note
);
3158 nub
= priv
->changeList
->changeNote
[priv
->head_note
].parent
;
3159 if (nub
) nub
->retain(); // might be released by start_parent_change()
3160 if ( start_parent_change(priv
->head_note
) == IOPMAckImplied
)
3162 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
3165 parent
->acknowledgePowerChange((IOService
*)nub
);
3169 if (nub
) nub
->release();
3172 IOLockUnlock(priv
->queue_lock
);
3178 //*********************************************************************************
3181 // A driver or child has acknowledged our notification of an upcoming power
3182 // change, and this acknowledgement is the last one pending
3183 // before we change power or after changing power.
3185 //*********************************************************************************
3189 void IOService::all_acked( void )
3191 switch (priv
->machine_state
) {
3192 case kIOPM_OurChangeSetPowerState
:
3193 OurChangeSetPowerState();
3195 case kIOPM_OurChangeFinish
:
3198 case kIOPM_ParentDownSetPowerState_Delayed
:
3199 ParentDownSetPowerState_Delayed();
3201 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3202 ParentDownAcknowledgeChange_Delayed();
3204 case kIOPM_ParentUpSetPowerState_Delayed
:
3205 ParentUpSetPowerState_Delayed();
3207 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3208 ParentUpAcknowledgePowerChange_Delayed();
3213 //*********************************************************************************
3214 // settleTimerExpired
3216 // Power has settled after our last change. Notify interested parties that
3217 // there is a new power state.
3218 //*********************************************************************************
3220 void IOService::settleTimerExpired ( void )
3222 if ( ! initialized
)
3228 switch (priv
->machine_state
) {
3229 case kIOPM_OurChangeNotifyInterestedDriversDidChange
:
3230 OurChangeNotifyInterestedDriversDidChange();
3232 case kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
:
3233 ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed();
3235 case kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed
:
3236 ParentUpNotifyInterestedDriversDidChange_Delayed();
3242 //*********************************************************************************
3243 // compute_settle_time
3245 // Compute the power-settling delay in microseconds for the
3246 // change from myCurrentState to head_note_state.
3247 //*********************************************************************************
3249 unsigned long IOService::compute_settle_time ( void )
3251 unsigned long totalTime
;
3254 // compute total time to attain the new state
3256 i
= pm_vars
->myCurrentState
;
3258 // we're lowering power
3259 if ( priv
->head_note_state
< pm_vars
->myCurrentState
)
3261 while ( i
> priv
->head_note_state
)
3263 totalTime
+= pm_vars
->thePowerStates
[i
].settleDownTime
;
3268 // we're raising power
3269 if ( priv
->head_note_state
> pm_vars
->myCurrentState
)
3271 while ( i
< priv
->head_note_state
)
3273 totalTime
+= pm_vars
->thePowerStates
[i
+1].settleUpTime
;
3282 //*********************************************************************************
3285 // Enter with a power-settling delay in microseconds and start a nano-second
3286 // timer for that delay.
3287 //*********************************************************************************
3289 IOReturn
IOService::startSettleTimer ( unsigned long delay
)
3291 AbsoluteTime deadline
;
3293 clock_interval_to_deadline(delay
, kMicrosecondScale
, &deadline
);
3295 thread_call_enter_delayed(priv
->settleTimer
, deadline
);
3300 //*********************************************************************************
3303 // The acknowledgement timeout periodic timer has ticked.
3304 // If we are awaiting acks for a power change notification,
3305 // we decrement the timer word of each interested driver which hasn't acked.
3306 // If a timer word becomes zero, we pretend the driver aknowledged.
3307 // If we are waiting for the controlling driver to change the power
3308 // state of the hardware, we decrement its timer word, and if it becomes
3309 // zero, we pretend the driver acknowledged.
3310 //*********************************************************************************
3312 void IOService::ack_timer_ticked ( void )
3314 IOPMinformee
* nextObject
;
3316 if ( ! initialized
)
3322 if (! acquire_lock() )
3327 switch (priv
->machine_state
) {
3328 case kIOPM_OurChangeWaitForPowerSettle
:
3329 case kIOPM_ParentDownWaitForPowerSettle_Delayed
:
3330 case kIOPM_ParentUpWaitForSettleTime_Delayed
:
3331 // are we waiting for our driver to make its change?
3332 if ( priv
->driver_timer
!= 0 ) {
3334 priv
->driver_timer
-= 1;
3335 // it's tardy, we'll go on without it
3336 if ( priv
->driver_timer
== 0 )
3338 IOUnlock(priv
->our_lock
);
3339 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogCtrlDriverTardy
,0,0);
3342 // still waiting, set timer again
3344 IOUnlock(priv
->our_lock
);
3348 IOUnlock(priv
->our_lock
);
3352 case kIOPM_OurChangeSetPowerState
:
3353 case kIOPM_OurChangeFinish
:
3354 case kIOPM_ParentDownSetPowerState_Delayed
:
3355 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3356 case kIOPM_ParentUpSetPowerState_Delayed
:
3357 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3358 // are we waiting for interested parties to acknowledge?
3359 if (priv
->head_note_pendingAcks
!= 0 )
3361 // yes, go through the list of interested drivers
3362 nextObject
= priv
->interestedDrivers
->firstInList();
3363 // and check each one
3364 while ( nextObject
!= NULL
)
3366 if ( nextObject
->timer
> 0 )
3368 nextObject
->timer
-= 1;
3369 // this one should have acked by now
3370 if ( nextObject
->timer
== 0 )
3372 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogIntDriverTardy
,0,0);
3373 //kprintf("interested driver tardy: %s\n",nextObject->whatObject->getName());
3374 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
3377 nextObject
= priv
->interestedDrivers
->nextInList(nextObject
);
3380 // is that the last?
3381 if ( priv
->head_note_pendingAcks
== 0 )
3383 IOUnlock(priv
->our_lock
);
3384 // yes, we can continue
3387 // no, set timer again
3389 IOUnlock(priv
->our_lock
);
3392 IOUnlock(priv
->our_lock
);
3396 // apps didn't respond to parent-down notification
3397 case kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate
:
3398 IOUnlock(priv
->our_lock
);
3399 IOLockLock(priv
->flags_lock
);
3400 if (pm_vars
->responseFlags
)
3402 // get rid of this stuff
3403 pm_vars
->responseFlags
->release();
3404 pm_vars
->responseFlags
= NULL
;
3406 IOLockUnlock(priv
->flags_lock
);
3407 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,5);
3408 // carry on with the change
3409 ParentDownTellPriorityClientsPowerDown_Delayed();
3412 case kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
:
3413 IOUnlock(priv
->our_lock
);
3414 IOLockLock(priv
->flags_lock
);
3415 if (pm_vars
->responseFlags
)
3417 // get rid of this stuff
3418 pm_vars
->responseFlags
->release();
3419 pm_vars
->responseFlags
= NULL
;
3421 IOLockUnlock(priv
->flags_lock
);
3422 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,1);
3423 // carry on with the change
3424 ParentDownNotifyInterestedDriversWillChange_Delayed();
3427 case kIOPM_OurChangeTellClientsPowerDown
:
3428 // apps didn't respond to our power-down request
3429 IOUnlock(priv
->our_lock
);
3430 IOLockLock(priv
->flags_lock
);
3431 if (pm_vars
->responseFlags
)
3433 // get rid of this stuff
3434 pm_vars
->responseFlags
->release();
3435 pm_vars
->responseFlags
= NULL
;
3437 IOLockUnlock(priv
->flags_lock
);
3438 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,2);
3439 // rescind the request
3440 tellNoChangeDown(priv
->head_note_state
);
3441 // mark the change note un-actioned
3442 priv
->head_note_flags
|= IOPMNotDone
;
3447 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
3448 // clients didn't respond to our power-down note
3449 IOUnlock(priv
->our_lock
);
3450 IOLockLock(priv
->flags_lock
);
3451 if (pm_vars
->responseFlags
)
3453 // get rid of this stuff
3454 pm_vars
->responseFlags
->release();
3455 pm_vars
->responseFlags
= NULL
;
3457 IOLockUnlock(priv
->flags_lock
);
3458 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,4);
3459 // carry on with the change
3460 OurChangeTellPriorityClientsPowerDown();
3463 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
3464 // apps didn't respond to our power-down notification
3465 IOUnlock(priv
->our_lock
);
3466 IOLockLock(priv
->flags_lock
);
3467 if (pm_vars
->responseFlags
)
3469 // get rid of this stuff
3470 pm_vars
->responseFlags
->release();
3471 pm_vars
->responseFlags
= NULL
;
3473 IOLockUnlock(priv
->flags_lock
);
3474 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,3);
3475 // carry on with the change
3476 OurChangeNotifyInterestedDriversWillChange();
3480 // not waiting for acks
3481 IOUnlock(priv
->our_lock
);
3487 //*********************************************************************************
3490 //*********************************************************************************
3492 void IOService::start_ack_timer ( void )
3494 AbsoluteTime deadline
;
3496 clock_interval_to_deadline(ACK_TIMER_PERIOD
, kNanosecondScale
, &deadline
);
3498 thread_call_enter_delayed(priv
->ackTimer
, deadline
);
3502 //*********************************************************************************
3505 //*********************************************************************************
3507 void IOService::stop_ack_timer ( void )
3509 thread_call_cancel(priv
->ackTimer
);
3513 //*********************************************************************************
3514 // c-language timer expiration functions
3516 //*********************************************************************************
3518 static void ack_timer_expired ( thread_call_param_t us
)
3520 ((IOService
*)us
)->ack_timer_ticked();
3524 static void settle_timer_expired ( thread_call_param_t us
)
3526 ((IOService
*)us
)->settleTimerExpired();
3530 //*********************************************************************************
3531 // add_child_to_active_change
3533 // A child has just registered with us. If there is
3534 // currently a change in progress, get the new party involved: if we
3535 // have notified all parties and are waiting for acks, notify the new
3537 //*********************************************************************************
3539 IOReturn
IOService::add_child_to_active_change ( IOPowerConnection
* newObject
)
3541 if (! acquire_lock() )
3546 switch (priv
->machine_state
)
3548 case kIOPM_OurChangeSetPowerState
:
3549 case kIOPM_ParentDownSetPowerState_Delayed
:
3550 case kIOPM_ParentUpSetPowerState_Delayed
:
3551 // one for this child and one to prevent
3552 OSAddAtomic(2, (SInt32
*)&priv
->head_note_pendingAcks
);
3553 // incoming acks from changing our state
3554 IOUnlock(priv
->our_lock
);
3555 notifyChild(newObject
, true);
3556 if (! acquire_lock() )
3559 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
3562 // are we still waiting for acks?
3563 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
3564 if ( priv
->head_note_pendingAcks
== 0 )
3566 // no, stop the timer
3568 IOUnlock(priv
->our_lock
);
3570 // and now we can continue
3575 case kIOPM_OurChangeFinish
:
3576 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3577 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3578 // one for this child and one to prevent
3579 OSAddAtomic(2, (SInt32
*)&priv
->head_note_pendingAcks
);
3580 // incoming acks from changing our state
3581 IOUnlock(priv
->our_lock
);
3582 notifyChild(newObject
, false);
3583 if (! acquire_lock() )
3586 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
3589 // are we still waiting for acks?
3590 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
3591 if ( priv
->head_note_pendingAcks
== 0 )
3593 // no, stop the timer
3595 IOUnlock(priv
->our_lock
);
3597 // and now we can continue
3603 IOUnlock(priv
->our_lock
);
3608 //*********************************************************************************
3609 // add_driver_to_active_change
3611 // An interested driver has just registered with us. If there is
3612 // currently a change in progress, get the new party involved: if we
3613 // have notified all parties and are waiting for acks, notify the new
3615 //*********************************************************************************
3617 IOReturn
IOService::add_driver_to_active_change ( IOPMinformee
* newObject
)
3619 if (! acquire_lock() )
3624 switch (priv
->machine_state
) {
3625 case kIOPM_OurChangeSetPowerState
:
3626 case kIOPM_ParentDownSetPowerState_Delayed
:
3627 case kIOPM_ParentUpSetPowerState_Delayed
:
3628 // one for this driver and one to prevent
3629 OSAddAtomic(2, (SInt32
*)&priv
->head_note_pendingAcks
);
3630 // incoming acks from changing our state
3631 IOUnlock(priv
->our_lock
);
3632 // inform the driver
3633 inform(newObject
, true);
3634 if (! acquire_lock() )
3637 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
3640 // are we still waiting for acks?
3641 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
3642 if ( priv
->head_note_pendingAcks
== 0 )
3644 // no, stop the timer
3646 IOUnlock(priv
->our_lock
);
3648 // and now we can continue
3653 case kIOPM_OurChangeFinish
:
3654 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3655 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3656 // one for this driver and one to prevent
3657 OSAddAtomic(2, (SInt32
*)&priv
->head_note_pendingAcks
);
3658 // incoming acks from changing our state
3659 IOUnlock(priv
->our_lock
);
3660 // inform the driver
3661 inform(newObject
, false);
3662 if (! acquire_lock() ) {
3664 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
3667 // are we still waiting for acks?
3668 OSAddAtomic(-1, (SInt32
*)&priv
->head_note_pendingAcks
);
3669 if ( priv
->head_note_pendingAcks
== 0 ) {
3670 // no, stop the timer
3672 IOUnlock(priv
->our_lock
);
3674 // and now we can continue
3680 IOUnlock(priv
->our_lock
);
3685 //*********************************************************************************
3686 // start_parent_change
3688 // Here we begin the processing of a change note initiated by our parent
3689 // which is at the head of the queue.
3691 // It is possible for the change to be processed to completion and removed from the queue.
3692 // There are several possible interruptions to the processing, though, and they are:
3693 // we may have to wait for interested parties to acknowledge our pre-change notification,
3694 // we may have to wait for our controlling driver to change the hardware power state,
3695 // there may be a settling time after changing the hardware power state,
3696 // we may have to wait for interested parties to acknowledge our post-change notification,
3697 // we may have to wait for the acknowledgement timer expiration to substitute for the
3698 // acknowledgement from a failing driver.
3699 //*********************************************************************************
3701 IOReturn
IOService::start_parent_change ( unsigned long queue_head
)
3703 priv
->head_note
= queue_head
;
3704 priv
->head_note_flags
= priv
-> changeList
->changeNote
[priv
->head_note
].flags
;
3705 priv
->head_note_state
= priv
->changeList
->changeNote
[priv
->head_note
].newStateNumber
;
3706 priv
->imminentState
= priv
->head_note_state
;
3707 priv
->head_note_outputFlags
= priv
->changeList
->changeNote
[priv
->head_note
].outputPowerCharacter
;
3708 priv
->head_note_domainState
= priv
->changeList
->changeNote
[priv
->head_note
].domainState
;
3709 priv
->head_note_parent
= priv
->changeList
->changeNote
[priv
->head_note
].parent
;
3710 priv
->head_note_capabilityFlags
= priv
->changeList
->changeNote
[priv
->head_note
].capabilityFlags
;
3712 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartParentChange
,
3713 (unsigned long)priv
->head_note_state
,(unsigned long)pm_vars
->myCurrentState
);
3715 // if we need something and haven't told the parent, do so
3716 ask_parent( priv
->ourDesiredPowerState
);
3718 // power domain is lowering
3719 if ( priv
->head_note_state
< pm_vars
->myCurrentState
)
3721 setParentInfo(priv
->changeList
->changeNote
[priv
->head_note
].singleParentState
,priv
->head_note_parent
);
3722 priv
->initial_change
= false;
3723 // tell apps and kernel clients
3724 priv
->machine_state
= kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate
;
3726 // are we waiting for responses?
3727 if ( tellChangeDown1(priv
->head_note_state
) )
3729 // no, notify priority clients
3730 return ParentDownTellPriorityClientsPowerDown_Immediate();
3733 return IOPMWillAckLater
;
3736 // parent is raising power, we may or may not
3737 if ( priv
->head_note_state
> pm_vars
->myCurrentState
)
3739 if ( priv
->ourDesiredPowerState
> pm_vars
->myCurrentState
)
3741 if ( priv
->ourDesiredPowerState
< priv
->head_note_state
)
3743 // we do, but not all the way
3744 priv
->head_note_state
= priv
->ourDesiredPowerState
;
3745 priv
->imminentState
= priv
->head_note_state
;
3746 priv
->head_note_outputFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].outputPowerCharacter
;
3747 priv
->head_note_capabilityFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].capabilityFlags
;
3748 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAmendParentChange
,(unsigned long)priv
->head_note_state
,0);
3752 priv
->head_note_state
= pm_vars
->myCurrentState
;
3753 priv
->imminentState
= priv
->head_note_state
;
3754 priv
->head_note_outputFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].outputPowerCharacter
;
3755 priv
->head_note_capabilityFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].capabilityFlags
;
3756 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAmendParentChange
,(unsigned long)priv
->head_note_state
,0);
3760 if ( (priv
->head_note_state
> pm_vars
->myCurrentState
) &&
3761 (priv
->head_note_flags
& IOPMDomainDidChange
) )
3764 priv
->initial_change
= false;
3765 priv
->machine_state
= kIOPM_ParentUpSetPowerState_Delayed
;
3766 if ( notifyAll(true) == IOPMAckImplied
) {
3767 return ParentUpSetPowerState_Immediate();
3769 // they didn't all ack
3770 return IOPMWillAckLater
;
3774 // a null change or power will go up
3775 return IOPMAckImplied
;
3779 //*********************************************************************************
3782 // Here we begin the processing of a change note initiated by us
3783 // which is at the head of the queue.
3785 // It is possible for the change to be processed to completion and removed from the queue.
3786 // There are several possible interruptions to the processing, though, and they are:
3787 // we may have to wait for interested parties to acknowledge our pre-change notification,
3788 // changes initiated by the parent will wait in the middle for powerStateDidChange,
3789 // we may have to wait for our controlling driver to change the hardware power state,
3790 // there may be a settling time after changing the hardware power state,
3791 // we may have to wait for interested parties to acknowledge our post-change notification,
3792 // we may have to wait for the acknowledgement timer expiration to substitute for the
3793 // acknowledgement from a failing driver.
3794 //*********************************************************************************
3796 void IOService::start_our_change ( unsigned long queue_head
)
3798 priv
->head_note
= queue_head
;
3799 priv
->head_note_flags
= priv
->changeList
->changeNote
[priv
->head_note
].flags
;
3800 priv
->head_note_state
= priv
->changeList
->changeNote
[priv
->head_note
].newStateNumber
;
3801 priv
->imminentState
= priv
->head_note_state
;
3802 priv
->head_note_outputFlags
= priv
->changeList
->changeNote
[priv
->head_note
].outputPowerCharacter
;
3803 priv
->head_note_capabilityFlags
= priv
->changeList
->changeNote
[priv
->head_note
].capabilityFlags
;
3805 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartDeviceChange
,
3806 (unsigned long)priv
->head_note_state
,(unsigned long)pm_vars
->myCurrentState
);
3808 // can our driver switch to the new state?
3809 if ( priv
->head_note_capabilityFlags
& IOPMNotAttainable
)
3811 // no, ask the parent to do it then
3812 if ( ! priv
->we_are_root
)
3814 ask_parent(priv
->head_note_state
);
3816 // mark the change note un-actioned
3817 priv
-> head_note_flags
|= IOPMNotDone
;
3823 // is there enough power in the domain?
3824 if ( (pm_vars
->maxCapability
< priv
->head_note_state
) && (! priv
->we_are_root
) )
3826 // no, ask the parent to raise it
3827 if ( ! priv
->we_are_root
)
3829 ask_parent(priv
->head_note_state
);
3831 // no, mark the change note un-actioned
3832 priv
->head_note_flags
|= IOPMNotDone
;
3834 // till the parent raises power
3839 if ( ! priv
->initial_change
)
3841 if ( priv
->head_note_state
== pm_vars
->myCurrentState
)
3843 // we initiated a null change; forget it
3848 priv
->initial_change
= false;
3851 if ( priv
->head_note_state
< pm_vars
->myCurrentState
)
3853 // yes, in case we have to wait for acks
3854 priv
->machine_state
= kIOPM_OurChangeTellClientsPowerDown
;
3855 pm_vars
->doNotPowerDown
= false;
3857 // ask apps and kernel clients if we can drop power
3858 pm_vars
->outofbandparameter
= kNotifyApps
;
3859 if ( askChangeDown(priv
->head_note_state
) )
3861 // don't have to wait, did any clients veto?
3862 if ( pm_vars
->doNotPowerDown
)
3864 // yes, rescind the warning
3865 tellNoChangeDown(priv
->head_note_state
);
3866 // mark the change note un-actioned
3867 priv
-> head_note_flags
|= IOPMNotDone
;
3871 // no, tell'em we're dropping power
3872 OurChangeTellClientsPowerDown();
3876 // we are raising power
3877 if ( ! priv
->we_are_root
)
3879 // if this changes our power requirement, tell the parent
3880 ask_parent(priv
->head_note_state
);
3882 // in case they don't all ack
3883 priv
->machine_state
= kIOPM_OurChangeSetPowerState
;
3885 // notify interested drivers and children
3886 if ( notifyAll(true) == IOPMAckImplied
)
3888 OurChangeSetPowerState();
3894 //*********************************************************************************
3897 // Call the power domain parent to ask for a higher power state in the domain
3898 // or to suggest a lower power state.
3899 //*********************************************************************************
3901 IOReturn
IOService::ask_parent ( unsigned long requestedState
)
3905 IOPowerConnection
*connection
;
3907 unsigned long ourRequest
= pm_vars
->thePowerStates
[requestedState
].inputPowerRequirement
;
3909 if ( pm_vars
->thePowerStates
[requestedState
].capabilityFlags
& (kIOPMChildClamp
| kIOPMPreventIdleSleep
) )
3911 ourRequest
|= kIOPMPreventIdleSleep
;
3913 if ( pm_vars
->thePowerStates
[requestedState
].capabilityFlags
& (kIOPMChildClamp2
| kIOPMPreventSystemSleep
) )
3915 ourRequest
|= kIOPMPreventSystemSleep
;
3918 // is this a new desire?
3919 if ( priv
->previousRequest
== ourRequest
)
3921 // no, the parent knows already, just return
3925 if ( priv
->we_are_root
)
3929 priv
->previousRequest
= ourRequest
;
3931 iter
= getParentIterator(gIOPowerPlane
);
3935 while ( (next
= iter
->getNextObject()) )
3937 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
3939 parent
= (IOService
*)connection
->copyParentEntry(gIOPowerPlane
);
3941 if ( parent
->requestPowerDomainState(ourRequest
,connection
,IOPMLowestState
)!= IOPMNoErr
)
3943 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRequestDenied
,
3944 (unsigned long)priv
->previousRequest
,0);
3957 //*********************************************************************************
3960 // Call the controlling driver and have it change the power state of the
3961 // hardware. If it returns IOPMAckImplied, the change is complete, and
3962 // we return IOPMAckImplied. Otherwise, it will ack when the change
3963 // is done; we return IOPMWillAckLater.
3964 //*********************************************************************************
3965 IOReturn
IOService::instruct_driver ( unsigned long newState
)
3969 // can our driver switch to the desired state?
3970 if ( pm_vars
->thePowerStates
[newState
].capabilityFlags
& IOPMNotAttainable
)
3973 return IOPMAckImplied
;
3976 priv
->driver_timer
= -1;
3979 IOLockUnlock(priv
->our_lock
);
3980 OUR_PMLog( kPMLogProgramHardware
, (UInt32
) this, newState
);
3981 delay
= pm_vars
->theControllingDriver
->setPowerState( newState
,this );
3982 OUR_PMLog((UInt32
) -kPMLogProgramHardware
, (UInt32
) this, (UInt32
) delay
);
3983 IOLockLock(priv
->our_lock
);
3986 if ( delay
== IOPMAckImplied
)
3988 priv
->driver_timer
= 0;
3989 return IOPMAckImplied
;
3992 // it acked behind our back
3993 if ( priv
->driver_timer
== 0 )
3995 return IOPMAckImplied
;
4001 return IOPMAckImplied
;
4005 priv
->driver_timer
= (delay
/ ( ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
4006 return IOPMWillAckLater
;
4010 //*********************************************************************************
4013 // We are acquiring the lock we use to protect our queue head from
4014 // simutaneous access by a thread which calls acknowledgePowerStateChange
4015 // or acknowledgeSetPowerState and the ack timer expiration thread.
4016 // Return TRUE if we acquire the lock, and the queue head didn't change
4017 // while we were acquiring the lock (and maybe blocked).
4018 // If there is no queue head, or it changes while we are blocked,
4019 // return FALSE with the lock unlocked.
4020 //*********************************************************************************
4022 bool IOService::acquire_lock ( void )
4024 long current_change_note
;
4026 current_change_note
= priv
->head_note
;
4027 if ( current_change_note
== -1 ) {
4031 IOTakeLock(priv
->our_lock
);
4032 if ( current_change_note
== priv
->head_note
)
4036 // we blocked and something changed radically
4037 // so there's nothing to do any more
4038 IOUnlock(priv
->our_lock
);
4044 //*********************************************************************************
4047 // Ask registered applications and kernel clients if we can change to a lower
4050 // Subclass can override this to send a different message type. Parameter is
4051 // the destination state number.
4053 // Return true if we don't have to wait for acknowledgements
4054 //*********************************************************************************
4056 bool IOService::askChangeDown ( unsigned long stateNum
)
4058 return tellClientsWithResponse(kIOMessageCanDevicePowerOff
);
4062 //*********************************************************************************
4065 // Notify registered applications and kernel clients that we are definitely
4068 // Return true if we don't have to wait for acknowledgements
4069 //*********************************************************************************
4071 bool IOService::tellChangeDown1 ( unsigned long stateNum
)
4073 pm_vars
->outofbandparameter
= kNotifyApps
;
4074 return tellChangeDown(stateNum
);
4078 //*********************************************************************************
4081 // Notify priority clients that we are definitely dropping power.
4083 // Return true if we don't have to wait for acknowledgements
4084 //*********************************************************************************
4086 bool IOService::tellChangeDown2 ( unsigned long stateNum
)
4088 pm_vars
->outofbandparameter
= kNotifyPriority
;
4089 return tellChangeDown(stateNum
);
4093 //*********************************************************************************
4096 // Notify registered applications and kernel clients that we are definitely
4099 // Subclass can override this to send a different message type. Parameter is
4100 // the destination state number.
4102 // Return true if we don't have to wait for acknowledgements
4103 //*********************************************************************************
4105 bool IOService::tellChangeDown ( unsigned long stateNum
)
4107 return tellClientsWithResponse(kIOMessageDeviceWillPowerOff
);
4111 //*********************************************************************************
4112 // tellClientsWithResponse
4114 // Notify registered applications and kernel clients that we are definitely
4117 // Return true if we don't have to wait for acknowledgements
4118 //*********************************************************************************
4120 bool IOService::tellClientsWithResponse ( int messageType
)
4122 struct context theContext
;
4123 AbsoluteTime deadline
;
4126 pm_vars
->responseFlags
= OSArray::withCapacity( 1 );
4127 pm_vars
->serialNumber
+= 1;
4129 theContext
.responseFlags
= pm_vars
->responseFlags
;
4130 theContext
.serialNumber
= pm_vars
->serialNumber
;
4131 theContext
.flags_lock
= priv
->flags_lock
;
4132 theContext
.counter
= 1;
4133 theContext
.msgType
= messageType
;
4134 theContext
.us
= this;
4135 theContext
.maxTimeRequested
= 0;
4136 theContext
.stateNumber
= priv
->head_note_state
;
4137 theContext
.stateFlags
= priv
->head_note_capabilityFlags
;
4139 IOLockLock(priv
->flags_lock
);
4141 // position zero is false to
4142 // prevent allowCancelCommon from succeeding
4143 aBool
= OSBoolean::withBoolean(false);
4144 theContext
.responseFlags
->setObject(0,aBool
);
4146 IOLockUnlock(priv
->flags_lock
);
4148 switch ( pm_vars
->outofbandparameter
) {
4150 applyToInterested(gIOAppPowerStateInterest
,tellAppWithResponse
,(void *)&theContext
);
4151 applyToInterested(gIOGeneralInterest
,tellClientWithResponse
,(void *)&theContext
);
4153 case kNotifyPriority
:
4154 applyToInterested(gIOPriorityPowerStateInterest
,tellClientWithResponse
,(void *)&theContext
);
4158 if (! acquire_lock() )
4162 IOLockLock(priv
->flags_lock
);
4163 // now fix position zero
4164 aBool
= OSBoolean::withBoolean(true);
4165 theContext
.responseFlags
->replaceObject(0,aBool
);
4167 IOLockUnlock(priv
->flags_lock
);
4169 // do we have to wait for somebody?
4170 if ( ! checkForDone() )
4172 // yes, start the ackTimer
4173 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,theContext
.maxTimeRequested
,0);
4174 clock_interval_to_deadline(theContext
.maxTimeRequested
/ 1000, kMillisecondScale
, &deadline
);
4176 thread_call_enter_delayed(priv
->ackTimer
, deadline
);
4178 IOUnlock(priv
->our_lock
);
4182 IOUnlock(priv
->our_lock
);
4183 IOLockLock(priv
->flags_lock
);
4185 // everybody responded
4186 pm_vars
->responseFlags
->release();
4187 pm_vars
->responseFlags
= NULL
;
4188 IOLockUnlock(priv
->flags_lock
);
4194 //*********************************************************************************
4195 // tellAppWithResponse
4197 // We send a message to an application, and we expect a response, so we compute a
4198 // cookie we can identify the response with.
4199 //*********************************************************************************
4200 void tellAppWithResponse ( OSObject
* object
, void * context
)
4202 struct context
*theContext
= (struct context
*)context
;
4204 IOPMprot
*pm_vars
= theContext
->us
->pm_vars
;
4206 if( OSDynamicCast( IOService
, object
) )
4208 // Automatically 'ack' in kernel clients
4209 IOLockLock(theContext
->flags_lock
);
4210 aBool
= OSBoolean::withBoolean(true);
4211 theContext
->responseFlags
->setObject(theContext
->counter
,aBool
);
4213 IOLockUnlock(theContext
->flags_lock
);
4215 const char *who
= ((IOService
*) object
)->getName();
4216 pm_vars
->thePlatform
->PMLog(who
,
4217 kPMLogClientAcknowledge
, theContext
->msgType
, * (UInt32
*) object
);
4219 UInt32 refcon
= ((theContext
->serialNumber
& 0xFFFF)<<16)
4220 + (theContext
->counter
& 0xFFFF);
4221 IOLockLock(theContext
->flags_lock
);
4222 aBool
= OSBoolean::withBoolean(false);
4223 theContext
->responseFlags
->setObject(theContext
->counter
,aBool
);
4225 IOLockUnlock(theContext
->flags_lock
);
4227 OUR_PMLog(kPMLogAppNotify
, theContext
->msgType
, refcon
);
4228 theContext
->us
->messageClient(theContext
->msgType
,object
,(void *)refcon
);
4229 if ( theContext
->maxTimeRequested
< k30seconds
)
4231 theContext
->maxTimeRequested
= k30seconds
;
4234 theContext
->counter
+= 1;
4237 //*********************************************************************************
4238 // tellClientWithResponse
4240 // We send a message to an in-kernel client, and we expect a response, so we compute a
4241 // cookie we can identify the response with.
4242 // If it doesn't understand the notification (it is not power-management savvy)
4243 // we won't wait for it to prepare for sleep. If it tells us via a return code
4244 // in the passed struct that it is currently ready, we won't wait for it to prepare.
4245 // If it tells us via the return code in the struct that it does need time, we will chill.
4246 //*********************************************************************************
4247 void tellClientWithResponse ( OSObject
* object
, void * context
)
4249 struct context
*theContext
= (struct context
*)context
;
4250 IOPowerStateChangeNotification notify
;
4256 refcon
= ((theContext
->serialNumber
& 0xFFFF)<<16) + (theContext
->counter
& 0xFFFF);
4257 IOLockLock(theContext
->flags_lock
);
4258 aBool
= OSBoolean::withBoolean(false);
4259 theContext
->responseFlags
->setObject(theContext
->counter
,aBool
);
4261 IOLockUnlock(theContext
->flags_lock
);
4263 IOPMprot
*pm_vars
= theContext
->us
->pm_vars
;
4264 if (gIOKitDebug
& kIOLogPower
) {
4265 OUR_PMLog(kPMLogClientNotify
, refcon
, (UInt32
) theContext
->msgType
);
4266 if (OSDynamicCast(IOService
, object
)) {
4267 const char *who
= ((IOService
*) object
)->getName();
4268 pm_vars
->thePlatform
->PMLog(who
,
4269 kPMLogClientNotify
, * (UInt32
*) object
, (UInt32
) object
);
4270 } else if (OSDynamicCast(_IOServiceInterestNotifier
, object
)) {
4271 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
4272 OUR_PMLog(kPMLogClientNotify
, (UInt32
) n
->handler
, 0);
4276 notify
.powerRef
= (void *)refcon
;
4277 notify
.returnValue
= 0;
4278 notify
.stateNumber
= theContext
->stateNumber
;
4279 notify
.stateFlags
= theContext
->stateFlags
;
4280 retCode
= theContext
->us
->messageClient(theContext
->msgType
,object
,(void *)¬ify
);
4281 if ( retCode
== kIOReturnSuccess
)
4283 if ( notify
.returnValue
== 0 )
4285 // client doesn't want time to respond
4286 IOLockLock(theContext
->flags_lock
);
4287 aBool
= OSBoolean::withBoolean(true);
4288 // so set its flag true
4289 theContext
->responseFlags
->replaceObject(theContext
->counter
,aBool
);
4291 IOLockUnlock(theContext
->flags_lock
);
4292 OUR_PMLog(kPMLogClientAcknowledge
, refcon
, (UInt32
) object
);
4294 IOLockLock(theContext
->flags_lock
);
4296 // it does want time, and it hasn't responded yet
4297 theFlag
= theContext
->responseFlags
->getObject(theContext
->counter
);
4300 if ( ((OSBoolean
*)theFlag
)->isFalse() )
4302 // so note its time requirement
4303 if ( theContext
->maxTimeRequested
< notify
.returnValue
)
4305 theContext
->maxTimeRequested
= notify
.returnValue
;
4309 IOLockUnlock(theContext
->flags_lock
);
4312 OUR_PMLog(kPMLogClientAcknowledge
, refcon
, 0);
4313 // not a client of ours
4314 IOLockLock(theContext
->flags_lock
);
4315 // so we won't be waiting for response
4316 aBool
= OSBoolean::withBoolean(true);
4317 theContext
->responseFlags
->replaceObject(theContext
->counter
,aBool
);
4319 IOLockUnlock(theContext
->flags_lock
);
4321 theContext
->counter
+= 1;
4325 //*********************************************************************************
4328 // Notify registered applications and kernel clients that we are not
4331 // Subclass can override this to send a different message type. Parameter is
4332 // the aborted destination state number.
4333 //*********************************************************************************
4335 void IOService::tellNoChangeDown ( unsigned long )
4337 return tellClients(kIOMessageDeviceWillNotPowerOff
);
4341 //*********************************************************************************
4344 // Notify registered applications and kernel clients that we are raising power.
4346 // Subclass can override this to send a different message type. Parameter is
4347 // the aborted destination state number.
4348 //*********************************************************************************
4350 void IOService::tellChangeUp ( unsigned long )
4352 return tellClients(kIOMessageDeviceHasPoweredOn
);
4356 //*********************************************************************************
4359 // Notify registered applications and kernel clients of something.
4360 //*********************************************************************************
4362 void IOService::tellClients ( int messageType
)
4364 struct context theContext
;
4366 theContext
.msgType
= messageType
;
4367 theContext
.us
= this;
4368 theContext
.stateNumber
= priv
->head_note_state
;
4369 theContext
.stateFlags
= priv
->head_note_capabilityFlags
;
4371 applyToInterested(gIOAppPowerStateInterest
,tellClient
,(void *)&theContext
);
4372 applyToInterested(gIOGeneralInterest
,tellClient
,(void *)&theContext
);
4376 //*********************************************************************************
4379 // Notify a registered application or kernel client of something.
4380 //*********************************************************************************
4381 void tellClient ( OSObject
* object
, void * context
)
4383 struct context
*theContext
= (struct context
*)context
;
4384 IOPowerStateChangeNotification notify
;
4386 notify
.powerRef
= (void *) 0;
4387 notify
.returnValue
= 0;
4388 notify
.stateNumber
= theContext
->stateNumber
;
4389 notify
.stateFlags
= theContext
->stateFlags
;
4391 theContext
->us
->messageClient(theContext
->msgType
,object
, ¬ify
);
4395 // **********************************************************************************
4398 // **********************************************************************************
4399 bool IOService::checkForDone ( void )
4404 IOLockLock(priv
->flags_lock
);
4405 if ( pm_vars
->responseFlags
== NULL
)
4407 IOLockUnlock(priv
->flags_lock
);
4411 for ( i
= 0; ; i
++ )
4413 theFlag
= pm_vars
->responseFlags
->getObject(i
);
4414 if ( theFlag
== NULL
)
4418 if ( ((OSBoolean
*)theFlag
)->isFalse() )
4420 IOLockUnlock(priv
->flags_lock
);
4424 IOLockUnlock(priv
->flags_lock
);
4429 // **********************************************************************************
4432 // **********************************************************************************
4433 bool IOService::responseValid ( unsigned long x
)
4435 UInt16 serialComponent
;
4436 UInt16 ordinalComponent
;
4438 unsigned long refcon
= (unsigned long)x
;
4441 serialComponent
= (refcon
>>16) & 0xFFFF;
4442 ordinalComponent
= refcon
& 0xFFFF;
4444 if ( serialComponent
!= pm_vars
->serialNumber
)
4449 IOLockLock(priv
->flags_lock
);
4450 if ( pm_vars
->responseFlags
== NULL
)
4452 IOLockUnlock(priv
->flags_lock
);
4456 theFlag
= pm_vars
->responseFlags
->getObject(ordinalComponent
);
4460 IOLockUnlock(priv
->flags_lock
);
4464 if ( ((OSBoolean
*)theFlag
)->isFalse() )
4466 aBool
= OSBoolean::withBoolean(true);
4467 pm_vars
->responseFlags
->replaceObject(ordinalComponent
,aBool
);
4471 IOLockUnlock(priv
->flags_lock
);
4476 // **********************************************************************************
4479 // Our power state is about to lower, and we have notified applications
4480 // and kernel clients, and one of them has acknowledged. If this is the last to do
4481 // so, and all acknowledgements are positive, we continue with the power change.
4483 // We serialize this processing with timer expiration with a command gate on the
4484 // power management workloop, which the timer expiration is command gated to as well.
4485 // **********************************************************************************
4486 IOReturn
IOService::allowPowerChange ( unsigned long refcon
)
4488 if ( ! initialized
)
4491 return kIOReturnSuccess
;
4494 return pm_vars
->PMcommandGate
->runAction(serializedAllowPowerChange
,(void *)refcon
);
4498 IOReturn
serializedAllowPowerChange ( OSObject
*owner
, void * refcon
, void *, void *, void *)
4500 return ((IOService
*)owner
)->serializedAllowPowerChange2((unsigned long)refcon
);
4503 IOReturn
IOService::serializedAllowPowerChange2 ( unsigned long refcon
)
4506 if ( ! responseValid(refcon
) )
4508 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr5
,refcon
,0);
4510 return kIOReturnSuccess
;
4512 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientAcknowledge
,refcon
,0);
4514 return allowCancelCommon();
4518 // **********************************************************************************
4519 // cancelPowerChange
4521 // Our power state is about to lower, and we have notified applications
4522 // and kernel clients, and one of them has vetoed the change. If this is the last
4523 // client to respond, we abandon the power change.
4525 // We serialize this processing with timer expiration with a command gate on the
4526 // power management workloop, which the timer expiration is command gated to as well.
4527 // **********************************************************************************
4528 IOReturn
IOService::cancelPowerChange ( unsigned long refcon
)
4530 if ( ! initialized
)
4533 return kIOReturnSuccess
;
4536 return pm_vars
->PMcommandGate
->runAction(serializedCancelPowerChange
,(void *)refcon
);
4540 IOReturn
serializedCancelPowerChange ( OSObject
*owner
, void * refcon
, void *, void *, void *)
4542 return ((IOService
*)owner
)->serializedCancelPowerChange2((unsigned long)refcon
);
4545 IOReturn
IOService::serializedCancelPowerChange2 ( unsigned long refcon
)
4548 if ( ! responseValid(refcon
) )
4550 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr5
,refcon
,0);
4552 return kIOReturnSuccess
;
4554 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientCancel
,refcon
,0);
4556 pm_vars
->doNotPowerDown
= true;
4558 return allowCancelCommon();
4562 // **********************************************************************************
4563 // allowCancelCommon
4565 // **********************************************************************************
4566 IOReturn
IOService::allowCancelCommon ( void )
4568 if (! acquire_lock() )
4570 return kIOReturnSuccess
;
4573 // is this the last response?
4574 if ( checkForDone() )
4576 // yes, stop the timer
4578 IOUnlock(priv
->our_lock
);
4579 IOLockLock(priv
->flags_lock
);
4580 if ( pm_vars
->responseFlags
)
4582 pm_vars
->responseFlags
->release();
4583 pm_vars
->responseFlags
= NULL
;
4585 IOLockUnlock(priv
->flags_lock
);
4586 switch (priv
->machine_state
) {
4587 case kIOPM_OurChangeTellClientsPowerDown
:
4588 // our change, was it vetoed?
4589 if ( ! pm_vars
->doNotPowerDown
)
4591 // no, we can continue
4592 OurChangeTellClientsPowerDown();
4594 // yes, rescind the warning
4595 tellNoChangeDown(priv
->head_note_state
);
4596 // mark the change note un-actioned
4597 priv
->head_note_flags
|= IOPMNotDone
;
4603 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
4604 OurChangeTellPriorityClientsPowerDown();
4606 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
4607 // our change, continue
4608 OurChangeNotifyInterestedDriversWillChange();
4610 case kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate
:
4611 // parent change, continue
4612 ParentDownTellPriorityClientsPowerDown_Delayed();
4614 case kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
:
4615 // parent change, continue
4616 ParentDownNotifyInterestedDriversWillChange_Delayed();
4621 IOUnlock(priv
->our_lock
);
4624 return kIOReturnSuccess
;
4629 //*********************************************************************************
4630 // c_PM_clamp_Timer_Expired (C Func)
4632 // Called when our clamp timer expires...we will call the object method.
4633 //*********************************************************************************
4635 static void c_PM_Clamp_Timer_Expired (OSObject
* client
, IOTimerEventSource
*)
4638 ((IOService
*)client
)->PM_Clamp_Timer_Expired ();
4643 //*********************************************************************************
4644 // PM_Clamp_Timer_Expired
4646 // called when clamp timer expires...set power state to 0.
4647 //*********************************************************************************
4649 void IOService::PM_Clamp_Timer_Expired (void)
4652 if ( ! initialized
)
4658 changePowerStateToPriv (0);
4662 //******************************************************************************
4665 // Set to highest available power state for a minimum of duration milliseconds
4666 //******************************************************************************
4668 #define kFiveMinutesInNanoSeconds (300 * NSEC_PER_SEC)
4670 void IOService::clampPowerOn (unsigned long duration
)
4673 changePowerStateToPriv (pm_vars
->theNumberOfPowerStates
-1);
4675 if ( priv
->clampTimerEventSrc
== NULL
) {
4676 priv
->clampTimerEventSrc
= IOTimerEventSource::timerEventSource(this,
4677 c_PM_Clamp_Timer_Expired
);
4679 IOWorkLoop
* workLoop
= getPMworkloop ();
4681 if ( !priv
->clampTimerEventSrc
|| !workLoop
||
4682 ( workLoop
->addEventSource( priv
->clampTimerEventSrc
) != kIOReturnSuccess
) ) {
4687 priv
->clampTimerEventSrc
->setTimeout(300*USEC_PER_SEC
, USEC_PER_SEC
);
4691 //*********************************************************************************
4694 // Does nothing here. This should be implemented in a subclass driver.
4695 //*********************************************************************************
4697 IOReturn
IOService::setPowerState ( unsigned long powerStateOrdinal
, IOService
* whatDevice
)
4703 //*********************************************************************************
4704 // maxCapabilityForDomainState
4706 // Finds the highest power state in the array whose input power
4707 // requirement is equal to the input parameter. Where a more intelligent
4708 // decision is possible, override this in the subclassed driver.
4709 //*********************************************************************************
4711 unsigned long IOService::maxCapabilityForDomainState ( IOPMPowerFlags domainState
)
4715 if (pm_vars
->theNumberOfPowerStates
== 0 )
4719 for ( i
= (pm_vars
->theNumberOfPowerStates
)-1; i
>= 0; i
-- )
4721 if ( (domainState
& pm_vars
->thePowerStates
[i
].inputPowerRequirement
) == pm_vars
->thePowerStates
[i
].inputPowerRequirement
)
4730 //*********************************************************************************
4731 // initialPowerStateForDomainState
4733 // Finds the highest power state in the array whose input power
4734 // requirement is equal to the input parameter. Where a more intelligent
4735 // decision is possible, override this in the subclassed driver.
4736 //*********************************************************************************
4738 unsigned long IOService::initialPowerStateForDomainState ( IOPMPowerFlags domainState
)
4742 if (pm_vars
->theNumberOfPowerStates
== 0 )
4746 for ( i
= (pm_vars
->theNumberOfPowerStates
)-1; i
>= 0; i
-- )
4748 if ( (domainState
& pm_vars
->thePowerStates
[i
].inputPowerRequirement
) == pm_vars
->thePowerStates
[i
].inputPowerRequirement
)
4757 //*********************************************************************************
4758 // powerStateForDomainState
4760 // Finds the highest power state in the array whose input power
4761 // requirement is equal to the input parameter. Where a more intelligent
4762 // decision is possible, override this in the subclassed driver.
4763 //*********************************************************************************
4765 unsigned long IOService::powerStateForDomainState ( IOPMPowerFlags domainState
)
4769 if (pm_vars
->theNumberOfPowerStates
== 0 )
4773 for ( i
= (pm_vars
->theNumberOfPowerStates
)-1; i
>= 0; i
-- )
4775 if ( (domainState
& pm_vars
->thePowerStates
[i
].inputPowerRequirement
) == pm_vars
->thePowerStates
[i
].inputPowerRequirement
)
4784 //*********************************************************************************
4787 // Does nothing here. This should be implemented in a subclass driver.
4788 //*********************************************************************************
4790 bool IOService::didYouWakeSystem ( void )
4796 //*********************************************************************************
4797 // powerStateWillChangeTo
4799 // Does nothing here. This should be implemented in a subclass driver.
4800 //*********************************************************************************
4802 IOReturn
IOService::powerStateWillChangeTo ( IOPMPowerFlags
, unsigned long, IOService
*)
4808 //*********************************************************************************
4809 // powerStateDidChangeTo
4811 // Does nothing here. This should be implemented in a subclass driver.
4812 //*********************************************************************************
4814 IOReturn
IOService::powerStateDidChangeTo ( IOPMPowerFlags
, unsigned long, IOService
*)
4820 //*********************************************************************************
4823 // Does nothing here. This should be implemented in a subclass policy-maker.
4824 //*********************************************************************************
4826 void IOService::powerChangeDone ( unsigned long )
4831 //*********************************************************************************
4834 // Does nothing here. This should be implemented in a subclass driver.
4835 //*********************************************************************************
4837 IOReturn
IOService::newTemperature ( long currentTemp
, IOService
* whichZone
)
4845 #define super OSObject
4847 OSDefineMetaClassAndStructors(IOPMprot
, OSObject
)
4848 //*********************************************************************************
4851 // Serialize protected instance variables for debug output.
4852 //*********************************************************************************
4853 bool IOPMprot::serialize(OSSerialize
*s
) const
4855 OSString
* theOSString
;
4862 // estimate how many bytes we need to present all power states
4863 buf_size
= 150 // beginning and end of string
4864 + (275 * (int)theNumberOfPowerStates
) // size per state
4865 + 100; // extra room just for kicks
4867 buffer
= ptr
= IONew(char, buf_size
);
4871 ptr
+= sprintf(ptr
,"{ theNumberOfPowerStates = %d, ",(unsigned int)theNumberOfPowerStates
);
4873 if ( theNumberOfPowerStates
!= 0 ) {
4874 ptr
+= sprintf(ptr
,"version %d, ",(unsigned int)thePowerStates
[0].version
);
4877 if ( theNumberOfPowerStates
!= 0 ) {
4878 for ( i
= 0; i
< (int)theNumberOfPowerStates
; i
++ ) {
4879 ptr
+= sprintf(ptr
, "power state %d = { ",i
);
4880 ptr
+= sprintf(ptr
,"capabilityFlags %08x, ",(unsigned int)thePowerStates
[i
].capabilityFlags
);
4881 ptr
+= sprintf(ptr
,"outputPowerCharacter %08x, ",(unsigned int)thePowerStates
[i
].outputPowerCharacter
);
4882 ptr
+= sprintf(ptr
,"inputPowerRequirement %08x, ",(unsigned int)thePowerStates
[i
].inputPowerRequirement
);
4883 ptr
+= sprintf(ptr
,"staticPower %d, ",(unsigned int)thePowerStates
[i
].staticPower
);
4884 ptr
+= sprintf(ptr
,"unbudgetedPower %d, ",(unsigned int)thePowerStates
[i
].unbudgetedPower
);
4885 ptr
+= sprintf(ptr
,"powerToAttain %d, ",(unsigned int)thePowerStates
[i
].powerToAttain
);
4886 ptr
+= sprintf(ptr
,"timeToAttain %d, ",(unsigned int)thePowerStates
[i
].timeToAttain
);
4887 ptr
+= sprintf(ptr
,"settleUpTime %d, ",(unsigned int)thePowerStates
[i
].settleUpTime
);
4888 ptr
+= sprintf(ptr
,"timeToLower %d, ",(unsigned int)thePowerStates
[i
].timeToLower
);
4889 ptr
+= sprintf(ptr
,"settleDownTime %d, ",(unsigned int)thePowerStates
[i
].settleDownTime
);
4890 ptr
+= sprintf(ptr
,"powerDomainBudget %d }, ",(unsigned int)thePowerStates
[i
].powerDomainBudget
);
4894 ptr
+= sprintf(ptr
,"aggressiveness = %d, ",(unsigned int)aggressiveness
);
4895 ptr
+= sprintf(ptr
,"myCurrentState = %d, ",(unsigned int)myCurrentState
);
4896 ptr
+= sprintf(ptr
,"parentsCurrentPowerFlags = %08x, ",(unsigned int)parentsCurrentPowerFlags
);
4897 ptr
+= sprintf(ptr
,"maxCapability = %d }",(unsigned int)maxCapability
);
4899 theOSString
= OSString::withCString(buffer
);
4900 rtn_code
= theOSString
->serialize(s
);
4901 theOSString
->release();
4902 IODelete(buffer
, char, buf_size
);
4909 #define super OSObject
4911 OSDefineMetaClassAndStructors(IOPMpriv
, OSObject
)
4912 //*********************************************************************************
4915 // Serialize private instance variables for debug output.
4916 //*********************************************************************************
4917 bool IOPMpriv::serialize(OSSerialize
*s
) const
4919 OSString
* theOSString
;
4923 IOPMinformee
* nextObject
;
4925 buffer
= ptr
= IONew(char, 2000);
4929 ptr
+= sprintf(ptr
,"{ this object = %08x",(unsigned int)owner
);
4930 if ( we_are_root
) {
4931 ptr
+= sprintf(ptr
," (root)");
4933 ptr
+= sprintf(ptr
,", ");
4935 nextObject
= interestedDrivers
->firstInList(); // display interested drivers
4936 while ( nextObject
!= NULL
) {
4937 ptr
+= sprintf(ptr
,"interested driver = %08x, ",(unsigned int)nextObject
->whatObject
);
4938 nextObject
= interestedDrivers
->nextInList(nextObject
);
4941 if ( machine_state
!= kIOPM_Finished
) {
4942 ptr
+= sprintf(ptr
,"machine_state = %d, ",(unsigned int)machine_state
);
4943 ptr
+= sprintf(ptr
,"driver_timer = %d, ",(unsigned int)driver_timer
);
4944 ptr
+= sprintf(ptr
,"settle_time = %d, ",(unsigned int)settle_time
);
4945 ptr
+= sprintf(ptr
,"head_note_flags = %08x, ",(unsigned int)head_note_flags
);
4946 ptr
+= sprintf(ptr
,"head_note_state = %d, ",(unsigned int)head_note_state
);
4947 ptr
+= sprintf(ptr
,"head_note_outputFlags = %08x, ",(unsigned int)head_note_outputFlags
);
4948 ptr
+= sprintf(ptr
,"head_note_domainState = %08x, ",(unsigned int)head_note_domainState
);
4949 ptr
+= sprintf(ptr
,"head_note_capabilityFlags = %08x, ",(unsigned int)head_note_capabilityFlags
);
4950 ptr
+= sprintf(ptr
,"head_note_pendingAcks = %d, ",(unsigned int)head_note_pendingAcks
);
4953 if ( device_overrides
) {
4954 ptr
+= sprintf(ptr
,"device overrides, ");
4956 ptr
+= sprintf(ptr
,"driverDesire = %d, ",(unsigned int)driverDesire
);
4957 ptr
+= sprintf(ptr
,"deviceDesire = %d, ",(unsigned int)deviceDesire
);
4958 ptr
+= sprintf(ptr
,"ourDesiredPowerState = %d, ",(unsigned int)ourDesiredPowerState
);
4959 ptr
+= sprintf(ptr
,"previousRequest = %d }",(unsigned int)previousRequest
);
4961 theOSString
= OSString::withCString(buffer
);
4962 rtn_code
= theOSString
->serialize(s
);
4963 theOSString
->release();
4964 IODelete(buffer
, char, 2000);