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/IOService.h>
24 #include <IOKit/IOLib.h>
25 #include <IOKit/IOCommandGate.h>
26 #include <IOKit/IOTimerEventSource.h>
27 #include <IOKit/IOWorkLoop.h>
28 #include <IOKit/IOPlatformExpert.h>
29 #include <IOKit/assert.h>
30 #include <IOKit/IOMessage.h>
31 #include <IOKit/IOKitDebug.h>
32 #include <IOKit/IOTimeStamp.h>
33 #include <IOKit/pwr_mgt/RootDomain.h>
34 #include <IOKit/pwr_mgt/IOPMinformee.h>
35 #include "IOKit/pwr_mgt/IOPMinformeeList.h"
36 #include "IOKit/pwr_mgt/IOPMchangeNoteList.h"
37 #include "IOKit/pwr_mgt/IOPMlog.h"
38 #include "IOKit/pwr_mgt/IOPowerConnection.h"
39 #include <kern/clock.h>
41 #define super IORegistryEntry
43 // Some debug functions
45 ioSPMTrace(unsigned int csc
,
46 unsigned int a
= 0, unsigned int b
= 0,
47 unsigned int c
= 0, unsigned int d
= 0)
49 if (gIOKitDebug
& kIOLogTracePower
)
50 IOTimeStampConstant(IODBG_POWER(csc
), a
, b
, c
, d
);
54 ioSPMTraceStart(unsigned int csc
,
55 unsigned int a
= 0, unsigned int b
= 0,
56 unsigned int c
= 0, unsigned int d
= 0)
58 if (gIOKitDebug
& kIOLogTracePower
)
59 IOTimeStampConstant(IODBG_POWER(csc
)|DBG_FUNC_START
, a
, b
, c
, d
);
63 ioSPMTraceEnd(unsigned int csc
,
64 unsigned int a
= 0, unsigned int b
= 0,
65 unsigned int c
= 0, unsigned int d
= 0)
67 if (gIOKitDebug
& kIOLogTracePower
)
68 IOTimeStampConstant(IODBG_POWER(csc
)|DBG_FUNC_END
, a
, b
, c
, d
);
72 static void ack_timer_expired(thread_call_param_t
);
73 static void settle_timer_expired(thread_call_param_t
);
74 static void PM_idle_timer_expired(OSObject
*, IOTimerEventSource
*);
75 static void c_PM_Clamp_Timer_Expired (OSObject
* client
,IOTimerEventSource
*);
76 void tellAppWithResponse ( OSObject
* object
, void * context
);
77 void tellClientWithResponse ( OSObject
* object
, void * context
);
78 void tellClient ( OSObject
* object
, void * context
);
79 IOReturn
serializedAllowPowerChange ( OSObject
*, void *, void *, void *, void *);
80 IOReturn
serializedCancelPowerChange ( OSObject
*, void *, void *, void *, void *);
82 extern const IORegistryPlane
* gIOPowerPlane
;
85 // and there's 1000 nanoseconds in a microsecond:
86 #define ns_per_us 1000
89 // The current change note is processed by a state machine.
90 // Inputs are acks from interested parties, ack from the controlling driver,
91 // ack timeouts, settle timeout, and powerStateDidChange from the parent.
92 // These are the states:
94 kIOPM_OurChangeTellClientsPowerDown
= 1,
95 kIOPM_OurChangeTellPriorityClientsPowerDown
,
96 kIOPM_OurChangeNotifyInterestedDriversWillChange
,
97 kIOPM_OurChangeSetPowerState
,
98 kIOPM_OurChangeWaitForPowerSettle
,
99 kIOPM_OurChangeNotifyInterestedDriversDidChange
,
100 kIOPM_OurChangeFinish
,
101 kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate
,
102 kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
,
103 kIOPM_ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate
,
104 kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
,
105 kIOPM_ParentDownSetPowerState_Delayed
,
106 kIOPM_ParentDownWaitForPowerSettle_Delayed
,
107 kIOPM_ParentDownAcknowledgeChange_Delayed
,
108 kIOPM_ParentUpSetPowerState_Delayed
,
109 kIOPM_ParentUpSetPowerState_Immediate
,
110 kIOPM_ParentUpWaitForSettleTime_Delayed
,
111 kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed
,
112 kIOPM_ParentUpAcknowledgePowerChange_Delayed
,
116 // values of outofbandparameter
123 // used for applyToInterested
125 OSArray
* responseFlags
;
128 UInt32 maxTimeRequested
;
132 unsigned long stateNumber
;
133 IOPMPowerFlags stateFlags
;
136 // five minutes in microseconds
137 #define FIVE_MINUTES 5*60*1000000
138 #define k30seconds 30*1000000
141 There are two different kinds of power state changes. One is initiated by a subclassed device object which has either
142 decided to change power state, or its controlling driver has suggested it, or some other driver wants to use the
143 idle device and has asked it to become usable. The second kind of power state change is initiated by the power
144 domain parent. The two are handled slightly differently.
146 There is a queue of so-called change notifications, or change notes for short. Usually the queue is empty, and when
147 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
148 at one time, a queue is implemented. Example: the subclass device decides it's idle and initiates a change to a lower
149 power state. This causes interested parties to be notified, but they don't all acknowledge right away. This causes the
150 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
151 wants to raise power back up again. This change can't be started, however, because the previous one isn't complete yet,
152 so the second one waits in the queue. During this time, the parent decides to lower or raise the power state of the entire
153 power domain and notifies the device, and that notification goes into the queue, too, and can't be actioned until the
156 This is how a power change initiated by the subclass device is handled:
157 First, all interested parties are notified of the change via their powerStateWillChangeTo method. If they all don't
158 acknowledge via return code, then we have to wait. If they do, or when they finally all acknowledge via our
159 acknowledgePowerChange method, then we can continue. We call the controlling driver, instructing it to change to
160 the new state. Then we wait for power to settle. If there is no settling-time, or after it has passed, we notify
161 interested parties again, this time via their powerStateDidChangeTo methods. When they have all acked, we're done.
162 If we lowered power and don't need the power domain to be in its current power state, we suggest to the parent that
163 it lower the power domain state.
165 This is how a change to a lower power domain state initiated by the parent is handled:
166 First, we figure out what power state we will be in when the new domain state is reached. Then all interested parties are
167 notified that we are moving to that new state. When they have acknowledged, we call the controlling driver to assume
168 that state and we wait for power to settle. Then we acknowledge our preparedness to our parent. When all its interested
169 parties have acknowledged, it lowers power and then notifies its interested parties again. When we get this call, we notify
170 our interested parties that the power state has changed, and when they have all acknowledged, we're done.
172 This is how a change to a higher power domain state initiated by the parent is handled:
173 We figure out what power state we will be in when the new domain state is reached. If it is different from our current
174 state we acknowledge the parent. When all the parent's interested parties have acknowledged, it raises power in the
175 domain and waits for power to settle. Then it notifies everyone that the new state has been reached. When we get this call,
176 we call the controlling driver, instructing it to assume the new state, and wait for power to settle. Then we notify our interested
177 parties. When they all acknowledge we are done.
179 In either of the two cases above, it is possible that we will not be changing state even though the domain is. Examples:
180 A change to a lower domain state may not affect us because we are already in a low enough state, and
181 We will not take advantage of a change to a higher domain state, because we have no need of the higher power.
182 In such a case, there is nothing to do but acknowledge the parent. So when the parent calls our powerDomainWillChange
183 method, and we decide that we will not be changing state, we merely acknowledge the parent, via return code, and wait.
184 When the parent subsequently calls powerStateDidChange, we acknowledge again via return code, and the change is complete.
186 Power state changes are processed in a state machine, and since there are four varieties of power state changes, there are
187 four major paths through the state machine:
189 The fourth is nearly trivial. In this path, the parent is changing the domain state, but we are not changing the device state.
190 The change starts when the parent calls powerDomainWillChange. All we do is acknowledge the parent.
191 When the parent calls powerStateDidChange, we acknowledge the parent again, and we're done.
193 The first is fairly simple. It starts when a power domain child calls requestPowerDomainState and we decide to change power states
194 to accomodate the child, or if our power-controlling driver calls changePowerStateTo, or if some other driver which is using our
195 device calls makeUsable, or if a subclassed object calls changePowerStateToPriv. These are all power changes initiated by us, not
196 forced upon us by the parent. We start by notifying interested parties. If they all acknowledge via return code, we can go
197 on to state "OurChangeSetPowerState". Otherwise, we start the ack timer and wait for the stragglers to acknowlege by calling
198 acknowledgePowerChange. We move on to state "OurChangeSetPowerState" when all the stragglers have acknowledged,
199 or when the ack timer expires on all those which didn't acknowledge. In "OurChangeSetPowerState" we call the power-controlling
200 driver to change the power state of the hardware. If it returns saying it has done so, we go on to state "OurChangeWaitForPowerSettle".
201 Otherwise, we have to wait for it, so we set the ack timer and wait. When it calls acknowledgeSetPowerState, or when the
202 ack timer expires, we go on. In "OurChangeWaitForPowerSettle", we look in the power state array to see if there is any settle time required
203 when changing from our current state to the new state. If not, we go right away to "OurChangeNotifyInterestedDriversDidChange". Otherwise, we
204 set the settle timer and wait. When it expires, we move on. In "OurChangeNotifyInterestedDriversDidChange" state, we notify all our interested parties
205 via their powerStateDidChange methods that we have finished changing power state. If they all acknowledge via return
206 code, we move on to "OurChangeFinish". Otherwise we set the ack timer and wait. When they have all acknowledged, or
207 when the ack timer has expired for those that didn't, we move on to "OurChangeFinish", where we remove the used
208 change note from the head of the queue and start the next one if one exists.
210 Parent-initiated changes are more complex in the state machine. First, power going up and power going down are handled
211 differently, so they have different paths throught the state machine. Second, we can acknowledge the parent's notification
212 in two different ways, so each of the parent paths is really two.
214 When the parent calls our powerDomainWillChange method, notifying us that it will lower power in the domain, we decide
215 what state that will put our device in. Then we embark on the state machine path "IOPMParentDownSetPowerState_Immediate"
216 and "kIOPM_ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate", in which we notify interested parties of the upcoming change, instruct our driver to make
217 the change, check for settle time, and notify interested parties of the completed change. If we get to the end of this path without
218 stalling due to an interested party which didn't acknowledge via return code, due to the controlling driver not able to change
219 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.
220 If we do stall in any of those states, we return IOPMWillAckLater to the parent and enter the parallel path "kIOPM_ParentDownSetPowerState_Delayed"
221 "kIOPM_ParentDownWaitForPowerSettle_Delayed", and "kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed", where we continue with the same processing, except that at the end we
222 acknowledge the parent explicitly via acknowledgePowerChange, and we're done with the change.
223 Then when the parent calls us at powerStateDidChange we acknowledging via return code, because we have already made
224 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.
226 The case of the parent raising power in the domain is handled similarly in that there are parallel paths, one for no-stall
227 that ends in implicit acknowleging the parent, and one that has stalled at least once that ends in explicit acknowledging
228 the parent. This case is different, though in that our device changes state in the second half, after the parent calls
229 powerStateDidChange rather than before, as in the power-lowering case.
231 When the parent calls our powerDomainWillChange method, notifying us that it will raise power in the domain, we acknowledge
232 via return code, because there's really nothing we can do until the power is actually raised in the domain.
233 When the parent calls us at powerStateDidChange, we start by notifying our interested parties. If they all acknowledge via return code,
234 we go on to" kIOPM_ParentUpSetPowerState_Immediate" to instruct the driver to raise its power level. After that, we check for any
235 necessary settling time in "IOPMParentUpWaitForSettleTime_Immediate", and we notify all interested parties that power has changed
236 in "IOPMParentUpNotifyInterestedDriversDidChange_Immediate". If none of these operations stall, we acknowledge the parent via return code, release
237 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",
238 "kIOPM_ParentUpWaitForSettleTime_Delayed", "kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed", and "kIOPM_ParentUpAcknowledgePowerChange_Delayed", which ends with
239 our explicit acknowledgement to the parent.
244 const char priv_key
[ ] = "Power Management private data";
245 const char prot_key
[ ] = "Power Management protected data";
248 void IOService::PMinit ( void )
250 if ( ! initialized
) {
252 // make space for our variables
253 pm_vars
= new IOPMprot
;
259 // add pm_vars & priv to the properties
260 setProperty(prot_key
, (OSObject
*) pm_vars
);
261 setProperty(priv_key
, (OSObject
*) priv
);
263 // then initialize them
265 pm_vars
->theNumberOfPowerStates
= 0;
266 priv
->we_are_root
= false;
267 pm_vars
->theControllingDriver
= NULL
;
268 priv
->our_lock
= IOLockAlloc();
269 priv
->flags_lock
= IOLockAlloc();
270 priv
->queue_lock
= IOLockAlloc();
271 pm_vars
->childLock
= IOLockAlloc();
272 pm_vars
->parentLock
= IOLockAlloc();
273 priv
->interestedDrivers
= new IOPMinformeeList
;
274 priv
->interestedDrivers
->initialize();
275 priv
->changeList
= new IOPMchangeNoteList
;
276 priv
->changeList
->initialize();
277 pm_vars
->aggressiveness
= 0;
278 for (unsigned int i
= 0; i
<= kMaxType
; i
++)
280 pm_vars
->current_aggressiveness_values
[i
] = 0;
281 pm_vars
->current_aggressiveness_valid
[i
] = false;
283 pm_vars
->myCurrentState
= 0;
284 priv
->imminentState
= 0;
285 priv
->ourDesiredPowerState
= 0;
286 pm_vars
->parentsCurrentPowerFlags
= 0;
287 pm_vars
->maxCapability
= 0;
288 priv
->driverDesire
= 0;
289 priv
->deviceDesire
= 0;
290 priv
->initial_change
= true;
291 priv
->need_to_become_usable
= false;
292 priv
->previousRequest
= 0;
293 priv
->device_overrides
= false;
294 priv
->machine_state
= kIOPM_Finished
;
295 priv
->timerEventSrc
= NULL
;
296 priv
->clampTimerEventSrc
= NULL
;
297 pm_vars
->PMworkloop
= NULL
;
298 priv
->activityLock
= NULL
;
299 pm_vars
->ourName
= getName();
300 pm_vars
->thePlatform
= getPlatform();
301 pm_vars
->parentsKnowState
= false;
302 assert( pm_vars
->thePlatform
!= 0 );
303 priv
->clampOn
= false;
304 pm_vars
->serialNumber
= 0;
305 pm_vars
->responseFlags
= NULL
;
306 pm_vars
->doNotPowerDown
= true;
307 pm_vars
->PMcommandGate
= NULL
;
308 priv
->ackTimer
= thread_call_allocate((thread_call_func_t
)ack_timer_expired
, (thread_call_param_t
)this);
309 priv
->settleTimer
= thread_call_allocate((thread_call_func_t
)settle_timer_expired
, (thread_call_param_t
)this);
315 //*********************************************************************************
318 // Free up the data created in PMinit, if it exists.
319 //*********************************************************************************
320 void IOService::PMfree ( void )
323 if ( priv
->clampTimerEventSrc
!= NULL
) {
324 getPMworkloop()->removeEventSource(priv
->clampTimerEventSrc
);
325 priv
->clampTimerEventSrc
->release();
326 priv
->clampTimerEventSrc
= NULL
;
328 if ( priv
->timerEventSrc
!= NULL
) {
329 pm_vars
->PMworkloop
->removeEventSource(priv
->timerEventSrc
);
330 priv
->timerEventSrc
->release();
331 priv
->timerEventSrc
= NULL
;
333 if ( priv
->settleTimer
) {
334 thread_call_cancel(priv
->settleTimer
);
335 thread_call_free(priv
->settleTimer
);
336 priv
->settleTimer
= NULL
;
338 if ( priv
->ackTimer
) {
339 thread_call_cancel(priv
->ackTimer
);
340 thread_call_free(priv
->ackTimer
);
341 priv
->ackTimer
= NULL
;
343 if ( priv
->our_lock
) {
344 IOLockFree(priv
->our_lock
);
345 priv
->our_lock
= NULL
;
347 if ( priv
->flags_lock
) {
348 IOLockFree(priv
->flags_lock
);
349 priv
->flags_lock
= NULL
;
351 if ( priv
->activityLock
) {
352 IOLockFree(priv
->activityLock
);
353 priv
->activityLock
= NULL
;
355 priv
->interestedDrivers
->release();
356 priv
->changeList
->release();
357 // remove instance variables
362 if ( pm_vars
->PMcommandGate
) {
363 pm_vars
->PMcommandGate
->release();
364 pm_vars
->PMcommandGate
= NULL
;
366 if ( pm_vars
->PMworkloop
) {
367 // The work loop object returned from getPMworkLoop() is
368 // never retained, therefore it should not be released.
369 // pm_vars->PMworkloop->release();
370 pm_vars
->PMworkloop
= NULL
;
372 if ( pm_vars
->responseFlags
) {
373 pm_vars
->responseFlags
->release();
374 pm_vars
->responseFlags
= NULL
;
376 // remove instance variables
382 //*********************************************************************************
385 // Disconnect the node from its parents and children in the Power Plane.
386 //*********************************************************************************
387 void IOService::PMstop ( void )
391 IOPowerConnection
* connection
;
392 IOService
* theChild
;
393 IOService
* theParent
;
395 // remove the properties
396 removeProperty(prot_key
);
397 removeProperty(priv_key
);
400 iter
= getParentIterator(gIOPowerPlane
);
404 while ( (next
= iter
->getNextObject()) )
406 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
408 theParent
= (IOService
*)connection
->copyParentEntry(gIOPowerPlane
);
411 theParent
->removePowerChild(connection
);
412 theParent
->release();
419 // detach IOConnections
420 detachAbove( gIOPowerPlane
);
422 // no more power state changes
423 pm_vars
->parentsKnowState
= false;
426 iter
= getChildIterator(gIOPowerPlane
);
430 while ( (next
= iter
->getNextObject()) )
432 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
434 theChild
= ((IOService
*)(connection
->copyChildEntry(gIOPowerPlane
)));
437 // detach nub from child
438 connection
->detachFromChild(theChild
,gIOPowerPlane
);
441 // detach us from nub
442 detachFromChild(connection
,gIOPowerPlane
);
448 // Remove all interested drivers from the list, including the power
449 // controlling driver.
451 // Usually, the controlling driver and the policy-maker functionality
452 // are implemented by the same object, and without the deregistration,
453 // the object will be holding an extra retain on itself, and cannot
456 if ( priv
&& priv
->interestedDrivers
)
458 IOPMinformee
* informee
;
460 while (( informee
= priv
->interestedDrivers
->firstInList() ))
461 deRegisterInterestedDriver( informee
->whatObject
);
466 //*********************************************************************************
469 // A policy-maker calls its nub here when initializing, to be attached into
470 // the power management hierarchy. The default function is to call the
471 // platform expert, which knows how to do it. This method is overridden
472 // by a nub subclass which may either know how to do it, or may need
473 // to take other action.
475 // This may be the only "power management" method used in a nub,
476 // meaning it may not be initialized for power management.
477 //*********************************************************************************
478 void IOService::joinPMtree ( IOService
* driver
)
480 IOPlatformExpert
* thePlatform
;
482 thePlatform
= getPlatform();
483 assert(thePlatform
!= 0 );
484 thePlatform
->PMRegisterDevice(this,driver
);
488 //*********************************************************************************
491 // Power Managment is informing us that we are the root power domain.
492 // The only difference between us and any other power domain is that
493 // we have no parent and therefore never call it.
494 //*********************************************************************************
495 IOReturn
IOService::youAreRoot ( void )
497 priv
-> we_are_root
= true;
498 pm_vars
->parentsKnowState
= true;
499 attachToParent( getRegistryRoot(),gIOPowerPlane
);
505 //*********************************************************************************
508 // Power Management is informing us who our parent is.
509 // If we have a controlling driver, find out, given our newly-informed
510 // power domain state, what state it would be in, and then tell it
511 // to assume that state.
512 //*********************************************************************************
513 IOReturn
IOService::setPowerParent ( IOPowerConnection
* theParent
, bool stateKnown
, IOPMPowerFlags currentState
)
517 IOPowerConnection
* connection
;
518 unsigned long tempDesire
;
520 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogSetParent
,stateKnown
,currentState
);
522 IOLockLock(pm_vars
->parentLock
);
524 if ( stateKnown
&& ((pm_vars
->PMworkloop
== NULL
) || (pm_vars
->PMcommandGate
== NULL
)) )
526 // we have a path to the root
527 // find out the workloop
529 if ( pm_vars
->PMworkloop
!= NULL
)
531 if ( pm_vars
->PMcommandGate
== NULL
)
533 // and make our command gate
534 pm_vars
->PMcommandGate
= IOCommandGate::commandGate((OSObject
*)this);
535 if ( pm_vars
->PMcommandGate
!= NULL
)
537 pm_vars
->PMworkloop
->addEventSource(pm_vars
->PMcommandGate
);
543 IOLockUnlock(pm_vars
->parentLock
);
545 // set our connection data
546 theParent
->setParentCurrentPowerFlags(currentState
);
547 theParent
->setParentKnowsState(stateKnown
);
549 // combine parent knowledge
550 pm_vars
->parentsKnowState
= true;
551 pm_vars
->parentsCurrentPowerFlags
= 0;
553 iter
= getParentIterator(gIOPowerPlane
);
557 while ( (next
= iter
->getNextObject()) )
559 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
561 pm_vars
->parentsKnowState
&= connection
->parentKnowsState();
562 pm_vars
->parentsCurrentPowerFlags
|= connection
->parentCurrentPowerFlags();
568 if ( (pm_vars
->theControllingDriver
!= NULL
) &&
569 (pm_vars
->parentsKnowState
) )
571 pm_vars
->maxCapability
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(pm_vars
->parentsCurrentPowerFlags
);
572 // initially change into the state we are already in
573 tempDesire
= priv
->deviceDesire
;
574 priv
->deviceDesire
= pm_vars
->theControllingDriver
->initialPowerStateForDomainState(pm_vars
->parentsCurrentPowerFlags
);
575 computeDesiredState();
576 priv
->previousRequest
= 0xffffffff;
578 // put this back like before
579 priv
->deviceDesire
= tempDesire
;
586 //*********************************************************************************
589 // Power Management is informing us who our children are.
590 //*********************************************************************************
591 IOReturn
IOService::addPowerChild ( IOService
* theChild
)
593 IOPowerConnection
*connection
;
598 // we're not a power-managed IOService
599 return IOPMNotYetInitialized
;
602 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAddChild
,0,0);
604 // Put ourselves into a usable power state.
605 // We must be in an "on" power state, as our children must be able to access
606 // our hardware after joining the power plane.
610 connection
= new IOPowerConnection
;
613 connection
->start(this);
614 connection
->setAwaitingAck(false);
617 attachToChild( connection
,gIOPowerPlane
);
618 connection
->attachToChild( theChild
,gIOPowerPlane
);
619 connection
->release();
621 // tell it the current state of the power domain
622 if ( (pm_vars
->theControllingDriver
== NULL
) ||
623 ! (inPlane(gIOPowerPlane
)) ||
624 ! (pm_vars
->parentsKnowState
) )
626 theChild
->setPowerParent(connection
,false,0);
627 if ( inPlane(gIOPowerPlane
) )
629 for (i
= 0; i
<= kMaxType
; i
++) {
630 if ( pm_vars
->current_aggressiveness_valid
[i
] )
632 theChild
->setAggressiveness (i
, pm_vars
->current_aggressiveness_values
[i
]);
637 theChild
->setPowerParent(connection
,true,pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].outputPowerCharacter
);
638 for (i
= 0; i
<= kMaxType
; i
++)
640 if ( pm_vars
->current_aggressiveness_valid
[i
] )
642 theChild
->setAggressiveness (i
, pm_vars
->current_aggressiveness_values
[i
]);
645 // catch it up if change is in progress
646 add_child_to_active_change(connection
);
653 //*********************************************************************************
656 //*********************************************************************************
657 IOReturn
IOService::removePowerChild ( IOPowerConnection
* theNub
)
659 IORegistryEntry
*theChild
;
662 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRemoveChild
,0,0);
666 // detach nub from child
667 theChild
= theNub
->copyChildEntry(gIOPowerPlane
);
670 theNub
->detachFromChild(theChild
, gIOPowerPlane
);
673 // detach from the nub
674 detachFromChild(theNub
,gIOPowerPlane
);
676 // are we awaiting an ack from this child?
677 if ( theNub
->getAwaitingAck() )
679 // yes, pretend we got one
680 theNub
->setAwaitingAck(false);
681 if ( acquire_lock() )
683 if (priv
->head_note_pendingAcks
!= 0 )
685 // that's one fewer ack to worry about
686 priv
->head_note_pendingAcks
-= 1;
688 if ( priv
->head_note_pendingAcks
== 0 )
690 // yes, stop the timer
692 IOUnlock(priv
->our_lock
);
693 // and now we can continue our power change
696 IOUnlock(priv
->our_lock
);
699 IOUnlock(priv
->our_lock
);
706 // if not fully initialized
707 if ( (pm_vars
->theControllingDriver
== NULL
) ||
708 !(inPlane(gIOPowerPlane
)) ||
709 !(pm_vars
->parentsKnowState
) )
715 // Perhaps the departing child was holding up idle or system sleep - we need to re-evaluate our
716 // childrens' requests. Clear and re-calculate our kIOPMChildClamp and kIOPMChildClamp2 bits.
717 rebuildChildClampBits();
722 iter
= getChildIterator(gIOPowerPlane
);
723 if ( !iter
|| !iter
->getNextObject() )
725 // paired to match the makeUsable() call in addPowerChild()
726 changePowerStateToPriv(0);
728 if(iter
) iter
->release();
731 // this may be different now
732 computeDesiredState();
733 // change state if we can now tolerate lower power
740 //*********************************************************************************
741 // registerPowerDriver
743 // A driver has called us volunteering to control power to our device.
744 // If the power state array it provides is richer than the one we already
745 // know about (supplied by an earlier volunteer), then accept the offer.
746 // Notify all interested parties of our power state, which we now know.
747 //*********************************************************************************
749 IOReturn
IOService::registerPowerDriver ( IOService
* controllingDriver
, IOPMPowerState
* powerStates
, unsigned long numberOfStates
)
752 unsigned long tempDesire
;
754 if ( (numberOfStates
> pm_vars
->theNumberOfPowerStates
)
755 && (numberOfStates
> 1) )
757 if ( priv
->changeList
->currentChange() == -1 )
759 if ( controllingDriver
!= NULL
)
761 if ( numberOfStates
<= IOPMMaxPowerStates
)
763 switch ( powerStates
[0].version
)
766 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriver
,
767 (unsigned long)numberOfStates
, (unsigned long)powerStates
[0].version
);
768 for ( i
= 0; i
< numberOfStates
; i
++ )
770 pm_vars
->thePowerStates
[i
] = powerStates
[i
];
774 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriver
,
775 (unsigned long) numberOfStates
,(unsigned long) powerStates
[0].version
);
776 for ( i
= 0; i
< numberOfStates
; i
++ )
778 pm_vars
->thePowerStates
[i
].version
= powerStates
[i
].version
;
779 pm_vars
->thePowerStates
[i
].capabilityFlags
= powerStates
[i
].capabilityFlags
;
780 pm_vars
->thePowerStates
[i
].outputPowerCharacter
= powerStates
[i
].outputPowerCharacter
;
781 pm_vars
->thePowerStates
[i
].inputPowerRequirement
= powerStates
[i
].inputPowerRequirement
;
782 pm_vars
->thePowerStates
[i
].staticPower
= powerStates
[i
].staticPower
;
783 pm_vars
->thePowerStates
[i
].unbudgetedPower
= powerStates
[i
].unbudgetedPower
;
784 pm_vars
->thePowerStates
[i
].powerToAttain
= powerStates
[i
].powerToAttain
;
785 pm_vars
->thePowerStates
[i
].timeToAttain
= powerStates
[i
].timeToAttain
;
786 pm_vars
->thePowerStates
[i
].settleUpTime
= powerStates
[i
].settleUpTime
;
787 pm_vars
->thePowerStates
[i
].timeToLower
= powerStates
[i
].timeToLower
;
788 pm_vars
->thePowerStates
[i
].settleDownTime
= powerStates
[i
].settleDownTime
;
789 pm_vars
->thePowerStates
[i
].powerDomainBudget
= powerStates
[i
].powerDomainBudget
;
793 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr1
,
794 (unsigned long)powerStates
[0].version
,0);
798 // make a mask of all the character bits we know about
799 pm_vars
->myCharacterFlags
= 0;
800 for ( i
= 0; i
< numberOfStates
; i
++ ) {
801 pm_vars
->myCharacterFlags
|= pm_vars
->thePowerStates
[i
].outputPowerCharacter
;
804 pm_vars
->theNumberOfPowerStates
= numberOfStates
;
805 pm_vars
->theControllingDriver
= controllingDriver
;
806 if ( priv
->interestedDrivers
->findItem(controllingDriver
) == NULL
)
808 // register it as interested, unless already done
809 registerInterestedDriver (controllingDriver
);
811 if ( priv
->need_to_become_usable
) {
812 priv
->need_to_become_usable
= false;
813 priv
->deviceDesire
= pm_vars
->theNumberOfPowerStates
- 1;
816 if ( inPlane(gIOPowerPlane
) &&
817 (pm_vars
->parentsKnowState
) ) {
818 pm_vars
->maxCapability
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(pm_vars
->parentsCurrentPowerFlags
);
819 // initially change into the state we are already in
820 tempDesire
= priv
->deviceDesire
;
821 priv
->deviceDesire
= pm_vars
->theControllingDriver
->initialPowerStateForDomainState(pm_vars
->parentsCurrentPowerFlags
);
822 computeDesiredState();
824 // put this back like before
825 priv
->deviceDesire
= tempDesire
;
828 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr2
,(unsigned long)numberOfStates
,0);
831 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr4
,0,0);
836 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogControllingDriverErr5
,(unsigned long)numberOfStates
,0);
841 //*********************************************************************************
842 // registerInterestedDriver
844 // Add the caller to our list of interested drivers and return our current
845 // power state. If we don't have a power-controlling driver yet, we will
846 // call this interested driver again later when we do get a driver and find
847 // out what the current power state of the device is.
848 //*********************************************************************************
850 IOPMPowerFlags
IOService::registerInterestedDriver ( IOService
* theDriver
)
852 IOPMinformee
*newInformee
;
853 IOPMPowerFlags futureCapability
;
855 if (theDriver
== NULL
) {
859 // make new driver node
860 newInformee
= new IOPMinformee
;
861 newInformee
->initialize(theDriver
);
862 // add it to list of drivers
863 priv
->interestedDrivers
->addToList(newInformee
);
865 if ( (pm_vars
->theControllingDriver
== NULL
) ||
866 !(inPlane(gIOPowerPlane
)) ||
867 !(pm_vars
->parentsKnowState
) )
869 // can't tell it a state yet
870 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInterestedDriver
,IOPMNotPowerManaged
,0);
871 return IOPMNotPowerManaged
;
874 // can we notify new driver of a change in progress?
875 switch (priv
->machine_state
) {
876 case kIOPM_OurChangeSetPowerState
:
877 case kIOPM_OurChangeFinish
:
878 case kIOPM_ParentDownSetPowerState_Delayed
:
879 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
880 case kIOPM_ParentUpSetPowerState_Delayed
:
881 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
882 // yes, remember what we tell it
883 futureCapability
= priv
->head_note_capabilityFlags
;
884 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInterestedDriver
,(unsigned long)futureCapability
,1);
886 add_driver_to_active_change(newInformee
);
887 // and return the same thing
888 return futureCapability
;
891 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInterestedDriver
,
892 (unsigned long) pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
,2);
894 // no, return current capability
895 return pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
;
899 //*********************************************************************************
900 // deRegisterInterestedDriver
902 //*********************************************************************************
903 IOReturn
IOService::deRegisterInterestedDriver ( IOService
* theDriver
)
905 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRemoveDriver
,0,0);
907 // remove the departing driver
908 priv
->interestedDrivers
->removeFromList(theDriver
);
914 //*********************************************************************************
915 // acknowledgePowerChange
917 // After we notified one of the interested drivers or a power-domain child
918 // of an impending change in power, it has called to say it is now
919 // prepared for the change. If this object is the last to
920 // acknowledge this change, we take whatever action we have been waiting
922 // That may include acknowledging to our parent. In this case, we do it
923 // last of all to insure that this doesn't cause the parent to call us some-
924 // where else and alter data we are relying on here (like the very existance
925 // of a "current change note".)
926 //*********************************************************************************
928 IOReturn
IOService::acknowledgePowerChange ( IOService
* whichObject
)
930 IOPMinformee
*ackingObject
;
931 unsigned long childPower
= kIOPMUnknown
;
934 // one of our interested drivers?
935 ackingObject
= priv
->interestedDrivers
->findItem(whichObject
);
936 if ( ackingObject
== NULL
)
938 if ( ! isChild(whichObject
,gIOPowerPlane
) )
940 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr1
,0,0);
941 //kprintf("errant driver: %s\n",whichObject->getName());
945 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChildAcknowledge
,priv
->head_note_pendingAcks
,0);
948 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogDriverAcknowledge
,priv
->head_note_pendingAcks
,0);
951 if (! acquire_lock() )
956 if (priv
->head_note_pendingAcks
!= 0 )
958 // yes, make sure we're expecting acks
959 if ( ackingObject
!= NULL
)
961 // it's an interested driver
962 // make sure we're expecting this ack
963 if ( ackingObject
->timer
!= 0 )
966 ackingObject
->timer
= 0;
967 // that's one fewer to worry about
968 priv
->head_note_pendingAcks
-= 1;
970 if ( priv
->head_note_pendingAcks
== 0 )
972 // yes, stop the timer
974 IOUnlock(priv
->our_lock
);
975 // and now we can continue
980 // this driver has already acked
981 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr2
,0,0);
982 //kprintf("errant driver: %s\n",whichObject->getName());
986 // make sure we're expecting this ack
987 if ( ((IOPowerConnection
*)whichObject
)->getAwaitingAck() )
989 // that's one fewer to worry about
990 priv
->head_note_pendingAcks
-= 1;
991 ((IOPowerConnection
*)whichObject
)->setAwaitingAck(false);
992 theChild
= (IOService
*)whichObject
->copyChildEntry(gIOPowerPlane
);
995 childPower
= theChild
->currentPowerConsumption();
998 if ( childPower
== kIOPMUnknown
)
1000 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
= kIOPMUnknown
;
1002 if ( pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
!= kIOPMUnknown
)
1004 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
+= childPower
;
1007 // is that the last?
1008 if ( priv
->head_note_pendingAcks
== 0 ) {
1009 // yes, stop the timer
1011 IOUnlock(priv
->our_lock
);
1012 // and now we can continue
1019 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr3
,0,0); // not expecting anybody to ack
1020 //kprintf("errant driver: %s\n",whichObject->getName());
1022 IOUnlock(priv
->our_lock
);
1026 //*********************************************************************************
1027 // acknowledgeSetPowerState
1029 // After we instructed our controlling driver to change power states,
1030 // it has called to say it has finished doing so.
1031 // We continue to process the power state change.
1032 //*********************************************************************************
1034 IOReturn
IOService::acknowledgeSetPowerState ( void )
1036 if (! acquire_lock() )
1041 ioSPMTrace(IOPOWER_ACK
, * (int *) this);
1043 if ( priv
->driver_timer
== -1 )
1045 // driver is acking instead of using return code
1046 priv
->driver_timer
= 0;
1048 // are we expecting this?
1049 if ( priv
->driver_timer
> 0 )
1051 // yes, stop the timer
1053 priv
->driver_timer
= 0;
1054 IOUnlock(priv
->our_lock
);
1055 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogDriverAcknowledgeSet
,0,0);
1059 // not expecting this
1060 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr4
,0,0);
1063 IOUnlock(priv
->our_lock
);
1068 //*********************************************************************************
1071 // Either the controlling driver has called acknowledgeSetPowerState
1072 // or the acknowledgement timer has expired while waiting for that.
1073 // We carry on processing the current change note.
1074 //*********************************************************************************
1076 void IOService::driver_acked ( void )
1078 switch (priv
->machine_state
) {
1079 case kIOPM_OurChangeWaitForPowerSettle
:
1080 OurChangeWaitForPowerSettle();
1082 case kIOPM_ParentDownWaitForPowerSettle_Delayed
:
1083 ParentDownWaitForPowerSettle_Delayed();
1085 case kIOPM_ParentUpWaitForSettleTime_Delayed
:
1086 ParentUpWaitForSettleTime_Delayed();
1092 //*********************************************************************************
1093 // powerDomainWillChangeTo
1095 // Called by the power-hierarchy parent notifying of a new power state
1096 // in the power domain.
1097 // We enqueue a parent power-change to our queue of power changes.
1098 // This may or may not cause us to change power, depending on what
1099 // kind of change is occuring in the domain.
1100 //*********************************************************************************
1102 IOReturn
IOService::powerDomainWillChangeTo ( IOPMPowerFlags newPowerStateFlags
, IOPowerConnection
* whichParent
)
1106 IOPowerConnection
*connection
;
1107 unsigned long newStateNumber
;
1108 IOPMPowerFlags combinedPowerFlags
;
1110 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogWillChange
,(unsigned long)newPowerStateFlags
,0);
1112 if ( ! inPlane(gIOPowerPlane
) )
1115 return IOPMAckImplied
;
1118 IOLockLock(pm_vars
->parentLock
);
1120 if ( (pm_vars
->PMworkloop
== NULL
) || (pm_vars
->PMcommandGate
== NULL
) )
1122 // we have a path to the root
1124 // so find out the workloop
1125 if ( pm_vars
->PMworkloop
!= NULL
)
1127 // and make our command gate
1128 if ( pm_vars
->PMcommandGate
== NULL
)
1130 pm_vars
->PMcommandGate
= IOCommandGate::commandGate((OSObject
*)this);
1131 if ( pm_vars
->PMcommandGate
!= NULL
)
1133 pm_vars
->PMworkloop
->addEventSource(pm_vars
->PMcommandGate
);
1139 IOLockUnlock(pm_vars
->parentLock
);
1141 // combine parents' power states
1142 // to determine our maximum state within the new power domain
1143 combinedPowerFlags
= 0;
1145 iter
= getParentIterator(gIOPowerPlane
);
1149 while ( (next
= iter
->getNextObject()) )
1151 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1153 if ( connection
== whichParent
){
1154 combinedPowerFlags
|= newPowerStateFlags
;
1156 combinedPowerFlags
|= connection
->parentCurrentPowerFlags();
1163 if ( pm_vars
->theControllingDriver
== NULL
)
1165 // we can't take any more action
1166 return IOPMAckImplied
;
1168 newStateNumber
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(combinedPowerFlags
);
1170 return enqueuePowerChange(IOPMParentInitiated
| IOPMDomainWillChange
,
1171 newStateNumber
,combinedPowerFlags
,whichParent
,newPowerStateFlags
);
1175 //*********************************************************************************
1176 // powerDomainDidChangeTo
1178 // Called by the power-hierarchy parent after the power state of the power domain
1179 // has settled at a new level.
1180 // We enqueue a parent power-change to our queue of power changes.
1181 // This may or may not cause us to change power, depending on what
1182 // kind of change is occuring in the domain.
1183 //*********************************************************************************
1185 IOReturn
IOService::powerDomainDidChangeTo ( IOPMPowerFlags newPowerStateFlags
, IOPowerConnection
* whichParent
)
1187 unsigned long newStateNumber
;
1189 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogDidChange
,newPowerStateFlags
,0);
1191 setParentInfo(newPowerStateFlags
,whichParent
);
1193 if ( pm_vars
->theControllingDriver
== NULL
) {
1194 return IOPMAckImplied
;
1197 newStateNumber
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(pm_vars
->parentsCurrentPowerFlags
);
1198 // tell interested parties about it
1199 return enqueuePowerChange(IOPMParentInitiated
| IOPMDomainDidChange
,
1200 newStateNumber
,pm_vars
->parentsCurrentPowerFlags
,whichParent
,0);
1204 //*********************************************************************************
1207 // Set our connection data for one specific parent, and then combine all the parent
1209 //*********************************************************************************
1211 void IOService::setParentInfo ( IOPMPowerFlags newPowerStateFlags
, IOPowerConnection
* whichParent
)
1215 IOPowerConnection
*connection
;
1217 // set our connection data
1218 whichParent
->setParentCurrentPowerFlags(newPowerStateFlags
);
1219 whichParent
->setParentKnowsState(true);
1221 IOLockLock(pm_vars
->parentLock
);
1223 // recompute our parent info
1224 pm_vars
->parentsCurrentPowerFlags
= 0;
1225 pm_vars
->parentsKnowState
= true;
1227 iter
= getParentIterator(gIOPowerPlane
);
1231 while ( (next
= iter
->getNextObject()) )
1233 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1235 pm_vars
->parentsKnowState
&= connection
->parentKnowsState();
1236 pm_vars
->parentsCurrentPowerFlags
|= connection
->parentCurrentPowerFlags();
1241 IOLockUnlock(pm_vars
->parentLock
);
1244 //*********************************************************************************
1245 // rebuildChildClampBits
1247 // The ChildClamp bits (kIOPMChildClamp & kIOPMChildClamp2) in our capabilityFlags
1248 // indicate that one of our children (or grandchildren or great-grandchildren or ...)
1249 // doesn't support idle or system sleep in its current state. Since we don't track the
1250 // origin of each bit, every time any child changes state we have to clear these bits
1251 // and rebuild them.
1252 //*********************************************************************************
1254 void IOService::rebuildChildClampBits(void)
1259 IOPowerConnection
*connection
;
1262 // A child's desires has changed. We need to rebuild the child-clamp bits in our
1263 // power state array. Start by clearing the bits in each power state.
1265 for ( i
= 0; i
< pm_vars
->theNumberOfPowerStates
; i
++ )
1267 pm_vars
->thePowerStates
[i
].capabilityFlags
&= ~(kIOPMChildClamp
| kIOPMChildClamp2
);
1270 // Now loop through the children. When we encounter the calling child, save
1271 // the computed state as this child's desire. And while we're at it, set the ChildClamp bits
1272 // in any of our states that some child has requested with clamp on.
1274 iter
= getChildIterator(gIOPowerPlane
);
1278 while ( (next
= iter
->getNextObject()) )
1280 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1282 if ( connection
->getPreventIdleSleepFlag() )
1283 pm_vars
->thePowerStates
[connection
->getDesiredDomainState()].capabilityFlags
|= kIOPMChildClamp
;
1284 if ( connection
->getPreventSystemSleepFlag() )
1285 pm_vars
->thePowerStates
[connection
->getDesiredDomainState()].capabilityFlags
|= kIOPMChildClamp2
;
1294 //*********************************************************************************
1295 // requestPowerDomainState
1297 // The kIOPMPreventIdleSleep and/or kIOPMPreventIdleSleep bits may be be set in the parameter.
1298 // It is not considered part of the state specification.
1299 //*********************************************************************************
1300 IOReturn
IOService::requestPowerDomainState ( IOPMPowerFlags desiredState
, IOPowerConnection
* whichChild
, unsigned long specification
)
1303 unsigned long computedState
;
1304 unsigned long theDesiredState
= desiredState
& ~(kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
1307 IOPowerConnection
*connection
;
1309 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRequestDomain
,
1310 (unsigned long)desiredState
,(unsigned long)specification
);
1312 if ( pm_vars
->theControllingDriver
== NULL
)
1314 return IOPMNotYetInitialized
;
1317 switch (specification
) {
1318 case IOPMLowestState
:
1320 while ( i
< pm_vars
->theNumberOfPowerStates
)
1322 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1328 if ( i
>= pm_vars
->theNumberOfPowerStates
)
1330 return IOPMNoSuchState
;
1334 case IOPMNextLowerState
:
1335 i
= pm_vars
->myCurrentState
- 1;
1338 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1346 return IOPMNoSuchState
;
1350 case IOPMHighestState
:
1351 i
= pm_vars
->theNumberOfPowerStates
;
1355 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1362 return IOPMNoSuchState
;
1366 case IOPMNextHigherState
:
1367 i
= pm_vars
->myCurrentState
+ 1;
1368 while ( i
< pm_vars
->theNumberOfPowerStates
)
1370 if ( ( pm_vars
->thePowerStates
[i
].outputPowerCharacter
& theDesiredState
) == (theDesiredState
& pm_vars
->myCharacterFlags
) )
1376 if ( i
== pm_vars
->theNumberOfPowerStates
)
1378 return IOPMNoSuchState
;
1383 return IOPMBadSpecification
;
1388 IOLockLock(pm_vars
->childLock
);
1390 // Now loop through the children. When we encounter the calling child, save
1391 // the computed state as this child's desire.
1392 iter
= getChildIterator(gIOPowerPlane
);
1396 while ( (next
= iter
->getNextObject()) )
1398 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1400 if ( connection
== whichChild
)
1402 connection
->setDesiredDomainState(computedState
);
1403 connection
->setPreventIdleSleepFlag(desiredState
& kIOPMPreventIdleSleep
);
1404 connection
->setPreventSystemSleepFlag(desiredState
& kIOPMPreventSystemSleep
);
1405 connection
->setChildHasRequestedPower();
1412 // Since a child's power requirements may have changed, clear and rebuild
1413 // kIOPMChildClamp and kIOPMChildClamp2 (idle and system sleep clamps)
1414 rebuildChildClampBits();
1416 IOLockUnlock(pm_vars
->childLock
);
1418 // this may be different now
1419 computeDesiredState();
1421 if ( inPlane(gIOPowerPlane
) &&
1422 (pm_vars
->parentsKnowState
) ) {
1423 // change state if all children can now tolerate lower power
1427 // are we clamped on, waiting for this child?
1428 if ( priv
->clampOn
) {
1429 // yes, remove the clamp
1430 priv
->clampOn
= false;
1431 changePowerStateToPriv(0);
1438 //*********************************************************************************
1439 // temporaryPowerClampOn
1441 // A power domain wants to clamp its power on till it has children which
1442 // will thendetermine the power domain state.
1444 // We enter the highest state until addPowerChild is called.
1445 //*********************************************************************************
1447 IOReturn
IOService::temporaryPowerClampOn ( void )
1449 priv
->clampOn
= true;
1455 //*********************************************************************************
1458 // Some client of our device is asking that we become usable. Although
1459 // this has not come from a subclassed device object, treat it exactly
1460 // as if it had. In this way, subsequent requests for lower power from
1461 // a subclassed device object will pre-empt this request.
1463 // We treat this as a subclass object request to switch to the
1464 // highest power state.
1465 //*********************************************************************************
1467 IOReturn
IOService::makeUsable ( void )
1469 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogMakeUsable
,0,0);
1471 if ( pm_vars
->theControllingDriver
== NULL
)
1473 priv
->need_to_become_usable
= true;
1476 priv
->deviceDesire
= pm_vars
->theNumberOfPowerStates
- 1;
1477 computeDesiredState();
1478 if ( inPlane(gIOPowerPlane
) && (pm_vars
->parentsKnowState
) )
1480 return changeState();
1486 //*********************************************************************************
1487 // currentCapability
1489 //*********************************************************************************
1491 IOPMPowerFlags
IOService::currentCapability ( void )
1493 if ( pm_vars
->theControllingDriver
== NULL
)
1497 return pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
;
1502 //*********************************************************************************
1503 // changePowerStateTo
1505 // For some reason, our power-controlling driver has decided it needs to change
1506 // power state. We enqueue the power change so that appropriate parties
1507 // will be notified, and then we will instruct the driver to make the change.
1508 //*********************************************************************************
1510 IOReturn
IOService::changePowerStateTo ( unsigned long ordinal
)
1512 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeStateTo
,ordinal
,0);
1514 if ( ordinal
>= pm_vars
->theNumberOfPowerStates
)
1516 return IOPMParameterError
;
1518 priv
->driverDesire
= ordinal
;
1519 computeDesiredState();
1520 if ( inPlane(gIOPowerPlane
) && (pm_vars
->parentsKnowState
) )
1522 return changeState();
1528 //*********************************************************************************
1529 // changePowerStateToPriv
1531 // For some reason, a subclassed device object has decided it needs to change
1532 // power state. We enqueue the power change so that appropriate parties
1533 // will be notified, and then we will instruct the driver to make the change.
1534 //*********************************************************************************
1536 IOReturn
IOService::changePowerStateToPriv ( unsigned long ordinal
)
1538 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeStateToPriv
,ordinal
,0);
1540 if ( pm_vars
->theControllingDriver
== NULL
)
1542 return IOPMNotYetInitialized
;
1544 if ( ordinal
>= pm_vars
->theNumberOfPowerStates
)
1546 return IOPMParameterError
;
1548 priv
->deviceDesire
= ordinal
;
1549 computeDesiredState();
1550 if ( inPlane(gIOPowerPlane
) && (pm_vars
->parentsKnowState
) )
1552 return changeState();
1559 //*********************************************************************************
1560 // computeDesiredState
1562 //*********************************************************************************
1564 void IOService::computeDesiredState ( void )
1568 IOPowerConnection
*connection
;
1569 unsigned long newDesiredState
= 0;
1571 // Compute the maximum of our children's desires, our controlling driver's desire, and the subclass device's desire.
1572 if ( ! priv
->device_overrides
)
1574 iter
= getChildIterator(gIOPowerPlane
);
1578 while ( (next
= iter
->getNextObject()) )
1580 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1582 if ( connection
->getDesiredDomainState() > newDesiredState
)
1584 newDesiredState
= connection
->getDesiredDomainState();
1591 if ( priv
->driverDesire
> newDesiredState
)
1593 newDesiredState
= priv
->driverDesire
;
1597 if ( priv
->deviceDesire
> newDesiredState
)
1599 newDesiredState
= priv
->deviceDesire
;
1602 priv
->ourDesiredPowerState
= newDesiredState
;
1606 //*********************************************************************************
1609 // A subclass object, our controlling driver, or a power domain child
1610 // has asked for a different power state. Here we compute what new
1611 // state we should enter and enqueue the change (or start it).
1612 //*********************************************************************************
1614 IOReturn
IOService::changeState ( void )
1616 // if not fully initialized
1617 if ( (pm_vars
->theControllingDriver
== NULL
) ||
1618 !(inPlane(gIOPowerPlane
)) ||
1619 !(pm_vars
->parentsKnowState
) )
1621 // we can do no more
1625 return enqueuePowerChange(IOPMWeInitiated
,priv
->ourDesiredPowerState
,0,0,0);
1629 //*********************************************************************************
1630 // currentPowerConsumption
1632 //*********************************************************************************
1634 unsigned long IOService::currentPowerConsumption ( void )
1636 if ( pm_vars
->theControllingDriver
== NULL
)
1638 return kIOPMUnknown
;
1640 if ( pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].capabilityFlags
& kIOPMStaticPowerValid
)
1642 return pm_vars
->thePowerStates
[pm_vars
->myCurrentState
].staticPower
;
1644 return kIOPMUnknown
;
1647 //*********************************************************************************
1650 // The activity tickle with parameter kIOPMSubclassPolicyis not handled
1651 // here and should have been intercepted by the subclass.
1652 // The tickle with parameter kIOPMSuperclassPolicy1 causes the activity
1653 // flag to be set, and the device state checked. If the device has been
1654 // powered down, it is powered up again.
1655 //*********************************************************************************
1657 bool IOService::activityTickle ( unsigned long type
, unsigned long stateNumber
)
1659 IOPMrootDomain
*pmRootDomain
;
1660 AbsoluteTime uptime
;
1662 if ( type
== kIOPMSuperclassPolicy1
)
1664 if ( pm_vars
->theControllingDriver
== NULL
)
1669 if( priv
->activityLock
== NULL
)
1671 priv
->activityLock
= IOLockAlloc();
1674 IOTakeLock(priv
->activityLock
);
1675 priv
->device_active
= true;
1677 clock_get_uptime(&uptime
);
1678 priv
->device_active_timestamp
= uptime
;
1680 if ( pm_vars
->myCurrentState
>= stateNumber
)
1682 IOUnlock(priv
->activityLock
);
1685 IOUnlock(priv
->activityLock
);
1687 // Transfer execution to the PM workloop
1688 if( (pmRootDomain
= getPMRootDomain()) )
1689 pmRootDomain
->unIdleDevice(this, stateNumber
);
1696 //*********************************************************************************
1699 // A child is calling to get a pointer to the Power Management workloop.
1700 // We got it or get it from one of our parents.
1701 //*********************************************************************************
1703 IOWorkLoop
* IOService::getPMworkloop ( void )
1708 if ( ! inPlane(gIOPowerPlane
) )
1712 // we have no workloop yet
1713 if ( pm_vars
->PMworkloop
== NULL
)
1715 nub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
1718 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
1720 // ask one of our parents for the workloop
1723 pm_vars
->PMworkloop
= parent
->getPMworkloop();
1728 return pm_vars
->PMworkloop
;
1732 //*********************************************************************************
1733 // setIdleTimerPeriod
1735 // A subclass policy-maker is going to use our standard idleness
1736 // detection service. Make a command queue and an idle timer and
1737 // connect them to the power management workloop. Finally,
1739 //*********************************************************************************
1741 IOReturn
IOService::setIdleTimerPeriod ( unsigned long period
)
1743 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMsetIdleTimerPeriod
,period
, 0);
1745 priv
->idle_timer_period
= period
;
1749 if ( getPMworkloop() == NULL
)
1751 return kIOReturnError
;
1754 // make the timer event
1755 if ( priv
->timerEventSrc
== NULL
)
1757 priv
->timerEventSrc
= IOTimerEventSource::timerEventSource(this,
1758 PM_idle_timer_expired
);
1759 if ((!priv
->timerEventSrc
) ||
1760 (pm_vars
->PMworkloop
->addEventSource(priv
->timerEventSrc
) != kIOReturnSuccess
) )
1762 return kIOReturnError
;
1766 if ( priv
->activityLock
== NULL
)
1768 priv
->activityLock
= IOLockAlloc();
1771 start_PM_idle_timer();
1777 //*********************************************************************************
1778 // start_PM_idle_timer
1780 // The parameter is a pointer to us. Use it to call our timeout method.
1781 //*********************************************************************************
1782 void IOService::start_PM_idle_timer ( void )
1784 AbsoluteTime uptime
;
1790 IOLockLock(priv
->activityLock
);
1792 clock_get_uptime(&uptime
);
1794 // Calculate time difference using funky macro from clock.h.
1796 SUB_ABSOLUTETIME(&delta
, &(priv
->device_active_timestamp
));
1798 // Figure it in seconds.
1799 absolutetime_to_nanoseconds(delta
, &delta_ns
);
1800 delta_secs
= delta_ns
/ NSEC_PER_SEC
;
1802 // Be paranoid about delta somehow exceeding timer period.
1803 if (delta_secs
< priv
->idle_timer_period
)
1805 delay_secs
= priv
->idle_timer_period
- delta_secs
;
1807 delay_secs
= priv
->idle_timer_period
;
1810 priv
->timerEventSrc
->setTimeout(delay_secs
, NSEC_PER_SEC
);
1812 IOLockUnlock(priv
->activityLock
);
1817 //*********************************************************************************
1818 // PM_idle_timer_expired
1820 // The parameter is a pointer to us. Use it to call our timeout method.
1821 //*********************************************************************************
1823 void PM_idle_timer_expired(OSObject
* ourSelves
, IOTimerEventSource
*)
1825 ((IOService
*)ourSelves
)->PM_idle_timer_expiration();
1829 //*********************************************************************************
1830 // PM_idle_timer_expiration
1832 // The idle timer has expired. If there has been activity since the last
1833 // expiration, just restart the timer and return. If there has not been
1834 // activity, switch to the next lower power state and restart the timer.
1835 //*********************************************************************************
1837 void IOService::PM_idle_timer_expiration ( void )
1839 if ( ! initialized
)
1845 if ( priv
->idle_timer_period
> 0 )
1847 IOTakeLock(priv
->activityLock
);
1848 if ( priv
->device_active
)
1850 priv
->device_active
= false;
1851 IOUnlock(priv
->activityLock
);
1852 start_PM_idle_timer();
1855 if ( pm_vars
->myCurrentState
> 0 )
1857 IOUnlock(priv
->activityLock
);
1858 changePowerStateToPriv(pm_vars
->myCurrentState
- 1);
1859 start_PM_idle_timer();
1862 IOUnlock(priv
->activityLock
);
1863 start_PM_idle_timer();
1868 // **********************************************************************************
1871 // We are un-idling a device due to its activity tickle. This routine runs on the
1872 // PM workloop, and is initiated by IOService::activityTickle.
1873 // We process all activityTickle state requests on the list.
1874 // **********************************************************************************
1875 void IOService::command_received ( void *statePtr
, void *, void * , void * )
1877 unsigned long stateNumber
;
1879 stateNumber
= (unsigned long)statePtr
;
1881 // If not initialized, we're unloading
1882 if ( ! initialized
) return;
1884 if ( (pm_vars
->myCurrentState
< stateNumber
) &&
1885 (priv
->imminentState
< stateNumber
) )
1887 changePowerStateToPriv(stateNumber
);
1892 //*********************************************************************************
1893 // setAggressiveness
1895 // Pass on the input parameters to all power domain children. All those which are
1896 // power domains will pass it on to their children, etc.
1897 //*********************************************************************************
1899 IOReturn
IOService::setAggressiveness ( unsigned long type
, unsigned long newLevel
)
1903 IOPowerConnection
*connection
;
1906 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogSetAggressiveness
,type
, newLevel
);
1908 if ( type
<= kMaxType
)
1910 pm_vars
->current_aggressiveness_values
[type
] = newLevel
;
1911 pm_vars
->current_aggressiveness_valid
[type
] = true;
1914 iter
= getChildIterator(gIOPowerPlane
);
1918 while ( (next
= iter
->getNextObject()) )
1920 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1922 child
= ((IOService
*)(connection
->copyChildEntry(gIOPowerPlane
)));
1925 child
->setAggressiveness(type
, newLevel
);
1936 //*********************************************************************************
1937 // getAggressiveness
1939 // Called by the user client.
1940 //*********************************************************************************
1942 IOReturn
IOService::getAggressiveness ( unsigned long type
, unsigned long * currentLevel
)
1944 // if ( type > kMaxType )
1945 // return kIOReturnBadArgument;
1947 if ( !pm_vars
->current_aggressiveness_valid
[type
] )
1948 return kIOReturnInvalid
;
1950 *currentLevel
= pm_vars
->current_aggressiveness_values
[type
];
1952 return kIOReturnSuccess
;
1955 //*********************************************************************************
1958 // Pass this to all power domain children. All those which are
1959 // power domains will pass it on to their children, etc.
1960 //*********************************************************************************
1962 IOReturn
IOService::systemWake ( void )
1966 IOPowerConnection
*connection
;
1967 IOService
*theChild
;
1969 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogSystemWake
,0, 0);
1971 iter
= getChildIterator(gIOPowerPlane
);
1975 while ( (next
= iter
->getNextObject()) )
1977 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
1979 theChild
= (IOService
*)connection
->copyChildEntry(gIOPowerPlane
);
1982 theChild
->systemWake();
1983 theChild
->release();
1990 if ( pm_vars
->theControllingDriver
!= NULL
)
1992 if ( pm_vars
->theControllingDriver
->didYouWakeSystem() )
2002 //*********************************************************************************
2003 // temperatureCriticalForZone
2005 //*********************************************************************************
2007 IOReturn
IOService::temperatureCriticalForZone ( IOService
* whichZone
)
2009 IOService
*theParent
;
2012 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogCriticalTemp
,0,0);
2014 if ( inPlane(gIOPowerPlane
) && !(priv
->we_are_root
) )
2016 theNub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
2019 theParent
= (IOService
*)theNub
->copyParentEntry(gIOPowerPlane
);
2023 theParent
->temperatureCriticalForZone(whichZone
);
2024 theParent
->release();
2032 //*********************************************************************************
2033 // powerOverrideOnPriv
2035 //*********************************************************************************
2038 IOReturn
IOService::powerOverrideOnPriv ( void )
2040 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogOverrideOn
,0,0);
2042 // turn on the override
2043 priv
->device_overrides
= true;
2044 computeDesiredState();
2046 // change state if that changed something
2047 return changeState();
2051 //*********************************************************************************
2052 // powerOverrideOffPriv
2054 //*********************************************************************************
2055 IOReturn
IOService::powerOverrideOffPriv ( void )
2057 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogOverrideOff
,0,0);
2059 // turn off the override
2060 priv
->device_overrides
= false;
2061 computeDesiredState();
2064 return makeUsable();
2066 // change state if that changed something
2067 return changeState();
2072 //*********************************************************************************
2073 // enqueuePowerChange
2075 // Allocate a new state change notification, initialize it with fields from the
2076 // caller, and add it to the tail of the list of pending power changes.
2078 // If it is early enough in the list, and almost all the time it is the only one in
2079 // the list, start the power change.
2081 // In rare instances, this change will preempt the previous change in the list.
2082 // If the previous change is un-actioned in any way (because we are still
2083 // processing an even earlier power change), and if both the previous change
2084 // in the list and this change are initiated by us (not the parent), then we
2085 // needn't perform the previous change, so we collapse the list a little.
2086 //*********************************************************************************
2088 IOReturn
IOService::enqueuePowerChange ( unsigned long flags
, unsigned long whatStateOrdinal
, unsigned long domainState
, IOPowerConnection
* whichParent
, unsigned long singleParentState
)
2093 // Create and initialize the new change note
2095 IOLockLock(priv
->queue_lock
);
2096 newNote
= priv
->changeList
->createChangeNote();
2097 if ( newNote
== -1 ) {
2098 // uh-oh, our list is full
2099 IOLockUnlock(priv
->queue_lock
);
2100 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogEnqueueErr
,0,0);
2101 return IOPMAckImplied
;
2104 priv
->changeList
->changeNote
[newNote
].newStateNumber
= whatStateOrdinal
;
2105 priv
->changeList
->changeNote
[newNote
].outputPowerCharacter
= pm_vars
->thePowerStates
[whatStateOrdinal
].outputPowerCharacter
;
2106 priv
->changeList
->changeNote
[newNote
].inputPowerRequirement
= pm_vars
->thePowerStates
[whatStateOrdinal
].inputPowerRequirement
;
2107 priv
->changeList
->changeNote
[newNote
].capabilityFlags
= pm_vars
->thePowerStates
[whatStateOrdinal
].capabilityFlags
;
2108 priv
->changeList
->changeNote
[newNote
].flags
= flags
;
2109 priv
->changeList
->changeNote
[newNote
].parent
= NULL
;
2110 if (flags
& IOPMParentInitiated
)
2112 priv
->changeList
->changeNote
[newNote
].domainState
= domainState
;
2113 priv
->changeList
->changeNote
[newNote
].parent
= whichParent
;
2114 whichParent
->retain();
2115 priv
->changeList
->changeNote
[newNote
].singleParentState
= singleParentState
;
2118 previousNote
= priv
->changeList
->previousChangeNote(newNote
);
2120 if ( previousNote
== -1 )
2123 // Queue is empty, we can start this change.
2125 if (flags
& IOPMWeInitiated
)
2127 IOLockUnlock(priv
->queue_lock
);
2128 start_our_change(newNote
);
2131 IOLockUnlock(priv
->queue_lock
);
2132 return start_parent_change(newNote
);
2136 // The queue is not empty. Try to collapse this new change and the previous one in queue into one change.
2137 // This is possible only if both changes are initiated by us, and neither has been started yet.
2138 // Do this more than once if possible.
2140 // (A change is started iff it is at the head of the queue)
2142 while ( (previousNote
!= priv
->head_note
) && (previousNote
!= -1) &&
2143 (priv
->changeList
->changeNote
[newNote
].flags
& priv
->changeList
->changeNote
[previousNote
].flags
& IOPMWeInitiated
) )
2145 priv
->changeList
->changeNote
[previousNote
].outputPowerCharacter
= priv
->changeList
->changeNote
[newNote
].outputPowerCharacter
;
2146 priv
->changeList
->changeNote
[previousNote
].inputPowerRequirement
= priv
->changeList
->changeNote
[newNote
].inputPowerRequirement
;
2147 priv
->changeList
->changeNote
[previousNote
].capabilityFlags
=priv
-> changeList
->changeNote
[newNote
].capabilityFlags
;
2148 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogCollapseQueue
,priv
->changeList
->changeNote
[newNote
].newStateNumber
,
2149 priv
->changeList
->changeNote
[previousNote
].newStateNumber
);
2150 priv
->changeList
->changeNote
[previousNote
].newStateNumber
= priv
->changeList
->changeNote
[newNote
].newStateNumber
;
2151 priv
->changeList
->releaseTailChangeNote();
2152 newNote
= previousNote
;
2153 previousNote
= priv
->changeList
->previousChangeNote(newNote
);
2155 IOLockUnlock(priv
->queue_lock
);
2156 // in any case, we can't start yet
2157 return IOPMWillAckLater
;
2160 //*********************************************************************************
2163 // Notify all interested parties either that a change is impending or that the
2164 // previously-notified change is done and power has settled.
2165 // The parameter identifies whether this is the
2166 // pre-change notification or the post-change notification.
2168 //*********************************************************************************
2170 IOReturn
IOService::notifyAll ( bool is_prechange
)
2172 IOPMinformee
* nextObject
;
2175 IOPowerConnection
* connection
;
2177 // To prevent acknowledgePowerChange from finishing the change note and removing it from the queue if
2178 // some driver calls it, we inflate the number of pending acks so it cannot become zero. We'll fix it later.
2180 priv
->head_note_pendingAcks
=1;
2182 // OK, we will go through the lists of interested drivers and power domain children
2183 // and notify each one of this change.
2185 nextObject
= priv
->interestedDrivers
->firstInList();
2186 while ( nextObject
!= NULL
) {
2187 priv
->head_note_pendingAcks
+=1;
2188 if (! inform(nextObject
, is_prechange
) )
2191 nextObject
= priv
->interestedDrivers
->nextInList(nextObject
);
2194 if (! acquire_lock() ) {
2197 // did they all ack?
2198 if ( priv
->head_note_pendingAcks
> 1 ) {
2200 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2204 IOUnlock(priv
->our_lock
);
2207 iter
= getChildIterator(gIOPowerPlane
);
2208 // summing their power consumption
2209 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
= 0;
2213 while ( (next
= iter
->getNextObject()) )
2215 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
2217 priv
->head_note_pendingAcks
+=1;
2218 notifyChild(connection
, is_prechange
);
2224 if (! acquire_lock() ) {
2227 // now make this real
2228 priv
->head_note_pendingAcks
-= 1;
2230 if (priv
->head_note_pendingAcks
== 0 ) {
2232 IOUnlock(priv
->our_lock
);
2233 // return ack to parent
2234 return IOPMAckImplied
;
2238 IOUnlock(priv
->our_lock
);
2239 return IOPMWillAckLater
;
2243 //*********************************************************************************
2246 // Notify a power domain child of an upcoming power change.
2248 // If the object acknowledges the current change, we return TRUE.
2249 //*********************************************************************************
2251 bool IOService::notifyChild ( IOPowerConnection
* theNub
, bool is_prechange
)
2253 IOReturn k
= IOPMAckImplied
;
2254 unsigned long childPower
;
2255 IOService
*theChild
= (IOService
*)(theNub
->copyChildEntry(gIOPowerPlane
));
2257 theNub
->setAwaitingAck(true); // in case they don't ack
2266 k
= theChild
->powerDomainWillChangeTo(priv
->head_note_outputFlags
,theNub
);
2268 k
= theChild
->powerDomainDidChangeTo(priv
->head_note_outputFlags
,theNub
);
2271 // did the return code ack?
2272 if ( k
== IOPMAckImplied
)
2275 priv
->head_note_pendingAcks
-=1;
2276 theNub
->setAwaitingAck(false);
2277 childPower
= theChild
->currentPowerConsumption();
2278 if ( childPower
== kIOPMUnknown
)
2280 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
= kIOPMUnknown
;
2282 if ( pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
!= kIOPMUnknown
)
2284 pm_vars
->thePowerStates
[priv
->head_note_state
].staticPower
+= childPower
;
2287 theChild
->release();
2290 theChild
->release();
2295 //*********************************************************************************
2298 // Notify an interested driver of an upcoming power change.
2300 // If the object acknowledges the current change, we return TRUE.
2301 //*********************************************************************************
2303 bool IOService::inform ( IOPMinformee
* nextObject
, bool is_prechange
)
2305 IOReturn k
= IOPMAckImplied
;
2308 nextObject
->timer
= -1;
2312 pm_vars
->thePlatform
->PMLog (pm_vars
->ourName
,PMlogInformDriverPreChange
,
2313 (unsigned long)priv
->head_note_capabilityFlags
,(unsigned long)priv
->head_note_state
);
2314 k
= nextObject
->whatObject
->powerStateWillChangeTo( priv
->head_note_capabilityFlags
,priv
->head_note_state
,this);
2316 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogInformDriverPostChange
,
2317 (unsigned long)priv
->head_note_capabilityFlags
,(unsigned long)priv
->head_note_state
);
2318 k
= nextObject
->whatObject
->powerStateDidChangeTo(priv
->head_note_capabilityFlags
,priv
->head_note_state
,this);
2321 // did it ack behind our back?
2322 if ( nextObject
->timer
== 0 )
2328 // no, did the return code ack?
2329 if ( k
==IOPMAckImplied
)
2332 nextObject
->timer
= 0;
2333 priv
->head_note_pendingAcks
-= 1;
2339 nextObject
->timer
= 0;
2340 priv
-> head_note_pendingAcks
-= 1;
2345 nextObject
->timer
= (k
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
2351 //*********************************************************************************
2352 // OurChangeTellClientsPowerDown
2354 // All registered applications and kernel clients have positively acknowledged our
2355 // intention of lowering power. Here we notify them all that we will definitely
2356 // lower the power. If we don't have to wait for any of them to acknowledge, we
2357 // carry on by notifying interested drivers. Otherwise, we do wait.
2358 //*********************************************************************************
2360 void IOService::OurChangeTellClientsPowerDown ( void )
2363 priv
->machine_state
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
2365 // are we waiting for responses?
2366 if ( tellChangeDown1(priv
->head_note_state
) )
2368 // no, notify priority clients
2369 OurChangeTellPriorityClientsPowerDown();
2371 // If we are waiting for responses, execution will resume via
2372 // allowCancelCommon() or ack timeout
2376 //*********************************************************************************
2377 // OurChangeTellPriorityClientsPowerDown
2379 // All registered applications and kernel clients have positively acknowledged our
2380 // intention of lowering power. Here we notify "priority" clients that we are
2381 // lowering power. If we don't have to wait for any of them to acknowledge, we
2382 // carry on by notifying interested drivers. Otherwise, we do wait.
2383 //*********************************************************************************
2385 void IOService::OurChangeTellPriorityClientsPowerDown ( void )
2388 priv
->machine_state
= kIOPM_OurChangeNotifyInterestedDriversWillChange
;
2389 // are we waiting for responses?
2390 if ( tellChangeDown2(priv
->head_note_state
) )
2392 // no, notify interested drivers
2393 return OurChangeNotifyInterestedDriversWillChange();
2395 // If we are waiting for responses, execution will resume via
2396 // allowCancelCommon() or ack timeout
2400 //*********************************************************************************
2401 // OurChangeNotifyInterestedDriversWillChange
2403 // All registered applications and kernel clients have acknowledged our notification
2404 // that we are lowering power. Here we notify interested drivers. If we don't have
2405 // to wait for any of them to acknowledge, we instruct our power driver to make the change.
2406 // Otherwise, we do wait.
2407 //*********************************************************************************
2409 void IOService::OurChangeNotifyInterestedDriversWillChange ( void )
2411 // no, in case they don't all ack
2412 priv
->machine_state
= kIOPM_OurChangeSetPowerState
;
2413 if ( notifyAll(true) == IOPMAckImplied
)
2415 // not waiting for responses
2416 OurChangeSetPowerState();
2418 // If we are waiting for responses, execution will resume via
2419 // all_acked() or ack timeout
2423 //*********************************************************************************
2424 // OurChangeSetPowerState
2426 // All interested drivers have acknowledged our pre-change notification of a power
2427 // change we initiated. Here we instruct our controlling driver to make
2428 // the change to the hardware. If it does so, we continue processing
2429 // (waiting for settle and notifying interested parties post-change.)
2430 // If it doesn't, we have to wait for it to acknowledge and then continue.
2431 //*********************************************************************************
2433 void IOService::OurChangeSetPowerState ( void )
2435 priv
->machine_state
= kIOPM_OurChangeWaitForPowerSettle
;
2437 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2439 // it's done, carry on
2440 OurChangeWaitForPowerSettle();
2442 // it's not, wait for it
2443 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2445 // execution will resume via ack_timer_ticked()
2450 //*********************************************************************************
2451 // OurChangeWaitForPowerSettle
2453 // Our controlling driver has changed power state on the hardware
2454 // during a power change we initiated. Here we see if we need to wait
2455 // for power to settle before continuing. If not, we continue processing
2456 // (notifying interested parties post-change). If so, we wait and
2458 //*********************************************************************************
2460 void IOService::OurChangeWaitForPowerSettle ( void )
2462 priv
->settle_time
= compute_settle_time();
2463 if ( priv
->settle_time
== 0 )
2465 OurChangeNotifyInterestedDriversDidChange();
2467 priv
->machine_state
= kIOPM_OurChangeNotifyInterestedDriversDidChange
;
2468 startSettleTimer(priv
->settle_time
);
2473 //*********************************************************************************
2474 // OurChangeNotifyInterestedDriversDidChange
2476 // Power has settled on a power change we initiated. Here we notify
2477 // all our interested parties post-change. If they all acknowledge, we're
2478 // done with this change note, and we can start on the next one.
2479 // Otherwise we have to wait for acknowledgements and finish up later.
2480 //*********************************************************************************
2482 void IOService::OurChangeNotifyInterestedDriversDidChange ( void )
2484 // in case they don't all ack
2485 priv
->machine_state
= kIOPM_OurChangeFinish
;
2486 if ( notifyAll(false) == IOPMAckImplied
)
2488 // not waiting for responses
2491 // If we are waiting for responses, execution will resume via
2492 // all_acked() or ack timeout
2496 //*********************************************************************************
2499 // Power has settled on a power change we initiated, and
2500 // all our interested parties have acknowledged. We're
2501 // done with this change note, and we can start on the next one.
2502 //*********************************************************************************
2504 void IOService::OurChangeFinish ( void )
2510 //*********************************************************************************
2511 // ParentDownTellPriorityClientsPowerDown_Immediate
2513 // All applications and kernel clients have been notified of a power lowering
2514 // initiated by the parent and we didn't have to wait for any responses. Here
2515 // we notify any priority clients. If they all ack, we continue with the power change.
2516 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2517 //*********************************************************************************
2519 IOReturn
IOService::ParentDownTellPriorityClientsPowerDown_Immediate ( void )
2521 // in case they don't all ack
2522 priv
->machine_state
= kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
;
2523 // are we waiting for responses?
2524 if ( tellChangeDown2(priv
->head_note_state
) )
2526 // no, notify interested drivers
2527 return ParentDownNotifyInterestedDriversWillChange_Immediate();
2529 // If we are waiting for responses, execution will resume via
2530 // allowCancelCommon() or ack timeout
2531 return IOPMWillAckLater
;
2535 //*********************************************************************************
2536 // ParentDownTellPriorityClientsPowerDown_Immediate2
2538 // All priority kernel clients have been notified of a power lowering
2539 // initiated by the parent and we didn't have to wait for any responses. Here
2540 // we notify any interested drivers and power domain children. If they all ack,
2541 // we continue with the power change.
2542 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2543 //*********************************************************************************
2545 IOReturn
IOService::ParentDownNotifyInterestedDriversWillChange_Immediate ( void )
2547 // in case they don't all ack
2548 priv
->machine_state
= kIOPM_ParentDownSetPowerState_Delayed
;
2549 if ( notifyAll(true) == IOPMAckImplied
)
2552 return ParentDownSetPowerState_Immediate();
2554 // If we are waiting for responses, execution will resume via
2555 // all_acked() or ack timeout
2556 return IOPMWillAckLater
;
2560 //*********************************************************************************
2561 // ParentDownTellPriorityClientsPowerDown_Immediate4
2563 // All applications and kernel clients have been notified of a power lowering
2564 // initiated by the parent and we had to wait for responses. Here
2565 // we notify any priority clients. If they all ack, we continue with the power change.
2566 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2567 //*********************************************************************************
2569 void IOService::ParentDownTellPriorityClientsPowerDown_Delayed ( void )
2571 // in case they don't all ack
2572 priv
->machine_state
= kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
;
2574 // are we waiting for responses?
2575 if ( tellChangeDown2(priv
->head_note_state
) )
2577 // no, notify interested drivers
2578 ParentDownNotifyInterestedDriversWillChange_Delayed();
2580 // If we are waiting for responses, execution will resume via
2581 // allowCancelCommon() or ack timeout
2585 //*********************************************************************************
2586 // ParentDownTellPriorityClientsPowerDown_Immediate5
2588 // All applications and kernel clients have been notified of a power lowering
2589 // initiated by the parent and we had to wait for their responses. Here we notify
2590 // any interested drivers and power domain children. If they all ack, we continue
2591 // with the power change.
2592 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2593 //*********************************************************************************
2595 void IOService::ParentDownNotifyInterestedDriversWillChange_Delayed ( void )
2597 // in case they don't all ack
2598 priv
->machine_state
= kIOPM_ParentDownSetPowerState_Delayed
;
2599 if ( notifyAll(true) == IOPMAckImplied
)
2602 ParentDownSetPowerState_Delayed();
2604 // If we are waiting for responses, execution will resume via
2605 // all_acked() or ack timeout
2609 //*********************************************************************************
2610 // ParentDownSetPowerState_Immediate
2612 // All parties have acknowledged our pre-change notification of a power
2613 // lowering initiated by the parent. Here we instruct our controlling driver
2614 // to put the hardware in the state it needs to be in when the domain is
2615 // lowered. If it does so, we continue processing
2616 // (waiting for settle and acknowledging the parent.)
2617 // If it doesn't, we have to wait for it to acknowledge and then continue.
2618 //*********************************************************************************
2620 IOReturn
IOService::ParentDownSetPowerState_Immediate ( void )
2622 priv
->machine_state
= kIOPM_ParentDownWaitForPowerSettle_Delayed
;
2624 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2626 // it's done, carry on
2627 return ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate();
2629 // it's not, wait for it
2630 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2632 return IOPMWillAckLater
;
2636 //*********************************************************************************
2637 // ParentDownSetPowerState_Delayed
2639 // We had to wait for it, but all parties have acknowledged our pre-change
2640 // notification of a power lowering initiated by the parent.
2641 // Here we instruct our controlling driver
2642 // to put the hardware in the state it needs to be in when the domain is
2643 // lowered. If it does so, we continue processing
2644 // (waiting for settle and acknowledging the parent.)
2645 // If it doesn't, we have to wait for it to acknowledge and then continue.
2646 //*********************************************************************************
2648 void IOService::ParentDownSetPowerState_Delayed ( void )
2650 priv
-> machine_state
= kIOPM_ParentDownWaitForPowerSettle_Delayed
;
2652 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2654 // it's done, carry on
2655 ParentDownWaitForPowerSettle_Delayed();
2657 // it's not, wait for it
2658 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2664 //*********************************************************************************
2665 // ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate
2667 // Our controlling driver has changed power state on the hardware
2668 // during a power change initiated by our parent. Here we see if we need
2669 // to wait for power to settle before continuing. If not, we continue
2670 // processing (acknowledging our preparedness to the parent).
2671 // If so, we wait and continue later.
2672 //*********************************************************************************
2674 IOReturn
IOService::ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate ( void )
2678 priv
->settle_time
= compute_settle_time();
2679 if ( priv
->settle_time
== 0 )
2681 // store current state in case they don't all ack
2682 priv
->machine_state
= kIOPM_ParentDownAcknowledgeChange_Delayed
;
2683 if ( notifyAll(false) == IOPMAckImplied
)
2685 // not waiting for responses
2686 nub
= priv
->head_note_parent
;
2690 return IOPMAckImplied
;
2692 // If we are waiting for responses, execution will resume via
2693 // all_acked() or ack timeout
2694 return IOPMWillAckLater
;
2696 // let settle time elapse, then notify interest drivers of our power state change in ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
2697 priv
->machine_state
= kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
;
2698 startSettleTimer(priv
->settle_time
);
2699 return IOPMWillAckLater
;
2704 //*********************************************************************************
2705 // ParentDownWaitForPowerSettle_Delayed
2707 // Our controlling driver has changed power state on the hardware
2708 // during a power change initiated by our parent. We have had to wait
2709 // for acknowledgement from interested parties, or we have had to wait
2710 // for the controlling driver to change the state. Here we see if we need
2711 // to wait for power to settle before continuing. If not, we continue
2712 // processing (acknowledging our preparedness to the parent).
2713 // If so, we wait and continue later.
2714 //*********************************************************************************
2716 void IOService::ParentDownWaitForPowerSettle_Delayed ( void )
2718 priv
->settle_time
= compute_settle_time();
2719 if ( priv
->settle_time
== 0 )
2721 ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed();
2723 priv
->machine_state
= kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
;
2724 startSettleTimer(priv
->settle_time
);
2729 //*********************************************************************************
2730 // ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
2732 // Power has settled on a power change initiated by our parent. Here we
2733 // notify interested parties.
2734 //*********************************************************************************
2736 void IOService::ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed ( void )
2738 IORegistryEntry
*nub
;
2741 // in case they don't all ack
2742 priv
->machine_state
= kIOPM_ParentDownAcknowledgeChange_Delayed
;
2743 if ( notifyAll(false) == IOPMAckImplied
) {
2744 nub
= priv
->head_note_parent
;
2747 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
2749 parent
->acknowledgePowerChange((IOService
*)nub
);
2754 // If we are waiting for responses, execution will resume via
2755 // all_acked() or ack timeout in ParentDownAcknowledgeChange_Delayed.
2756 // Notice the duplication of code just above and in ParentDownAcknowledgeChange_Delayed.
2760 //*********************************************************************************
2761 // ParentDownAcknowledgeChange_Delayed
2763 // We had to wait for it, but all parties have acknowledged our post-change
2764 // notification of a power lowering initiated by the parent.
2765 // Here we acknowledge the parent.
2766 // We are done with this change note, and we can start on the next one.
2767 //*********************************************************************************
2769 void IOService::ParentDownAcknowledgeChange_Delayed ( void )
2771 IORegistryEntry
*nub
;
2774 nub
= priv
->head_note_parent
;
2777 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
2780 parent
->acknowledgePowerChange((IOService
*)nub
);
2787 //*********************************************************************************
2788 // ParentUpSetPowerState_Delayed
2790 // Our parent has informed us via powerStateDidChange that it has
2791 // raised the power in our power domain, and we have had to wait
2792 // for some interested party to acknowledge our notification.
2793 // Here we instruct our controlling
2794 // driver to program the hardware to take advantage of the higher domain
2795 // power. If it does so, we continue processing
2796 // (waiting for settle and notifying interested parties post-change.)
2797 // If it doesn't, we have to wait for it to acknowledge and then continue.
2798 //*********************************************************************************
2800 void IOService::ParentUpSetPowerState_Delayed ( void )
2802 priv
->machine_state
= kIOPM_ParentUpWaitForSettleTime_Delayed
;
2804 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2806 // it did it, carry on
2807 ParentUpWaitForSettleTime_Delayed();
2809 // it didn't, wait for it
2810 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2816 //*********************************************************************************
2817 // ParentUpSetPowerState_Immediate
2819 // Our parent has informed us via powerStateDidChange that it has
2820 // raised the power in our power domain. Here we instruct our controlling
2821 // driver to program the hardware to take advantage of the higher domain
2822 // power. If it does so, we continue processing
2823 // (waiting for settle and notifying interested parties post-change.)
2824 // If it doesn't, we have to wait for it to acknowledge and then continue.
2825 //*********************************************************************************
2827 IOReturn
IOService::ParentUpSetPowerState_Immediate ( void )
2829 priv
->machine_state
= kIOPM_ParentUpWaitForSettleTime_Delayed
;
2831 if ( instruct_driver(priv
->head_note_state
) == IOPMAckImplied
)
2833 // it did it, carry on
2834 return ParentUpWaitForSettleTime_Immediate();
2837 // it didn't, wait for it
2838 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,0,0);
2840 return IOPMWillAckLater
;
2845 //*********************************************************************************
2846 // ParentUpWaitForSettleTime_Immediate
2848 // Our controlling driver has changed power state on the hardware
2849 // during a power raise initiated by the parent. Here we see if we need to wait
2850 // for power to settle before continuing. If not, we continue processing
2851 // (notifying interested parties post-change). If so, we wait and
2853 //*********************************************************************************
2855 IOReturn
IOService::ParentUpWaitForSettleTime_Immediate ( void )
2857 priv
->settle_time
= compute_settle_time();
2858 if ( priv
->settle_time
== 0 )
2860 return ParentUpNotifyInterestedDriversDidChange_Immediate();
2862 priv
->machine_state
= kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed
;
2863 startSettleTimer(priv
->settle_time
);
2864 return IOPMWillAckLater
;
2869 //*********************************************************************************
2870 // ParentUpWaitForSettleTime_Delayed
2872 // Our controlling driver has changed power state on the hardware
2873 // during a power raise initiated by the parent, but we had to wait for it.
2874 // Here we see if we need to wait for power to settle before continuing.
2875 // If not, we continue processing (notifying interested parties post-change).
2876 // If so, we wait and continue later.
2877 //*********************************************************************************
2879 void IOService::ParentUpWaitForSettleTime_Delayed ( void )
2881 priv
->settle_time
= compute_settle_time();
2882 if ( priv
->settle_time
== 0 )
2884 ParentUpNotifyInterestedDriversDidChange_Delayed();
2886 priv
->machine_state
= kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed
;
2887 startSettleTimer(priv
->settle_time
);
2892 //*********************************************************************************
2893 // ParentUpNotifyInterestedDriversDidChange_Immediate
2895 // No power settling was required on a power raise initiated by the parent.
2896 // Here we notify all our interested parties post-change. If they all acknowledge,
2897 // we're done with this change note, and we can start on the next one.
2898 // Otherwise we have to wait for acknowledgements and finish up later.
2899 //*********************************************************************************
2901 IOReturn
IOService::ParentUpNotifyInterestedDriversDidChange_Immediate ( void )
2905 // in case they don't all ack
2906 priv
->machine_state
= kIOPM_ParentUpAcknowledgePowerChange_Delayed
;
2907 if ( notifyAll(false) == IOPMAckImplied
)
2909 nub
= priv
->head_note_parent
;
2913 return IOPMAckImplied
;
2915 // If we are waiting for responses, execution will resume via
2916 // all_acked() or ack timeout in ParentUpAcknowledgePowerChange_Delayed.
2917 return IOPMWillAckLater
;
2921 //*********************************************************************************
2922 // ParentUpNotifyInterestedDriversDidChange_Delayed
2924 // Power has settled on a power raise initiated by the parent.
2925 // Here we notify all our interested parties post-change. If they all acknowledge,
2926 // we're done with this change note, and we can start on the next one.
2927 // Otherwise we have to wait for acknowledgements and finish up later.
2928 //*********************************************************************************
2930 void IOService::ParentUpNotifyInterestedDriversDidChange_Delayed ( void )
2932 // in case they don't all ack
2933 priv
->machine_state
= kIOPM_ParentUpAcknowledgePowerChange_Delayed
;
2934 if ( notifyAll(false) == IOPMAckImplied
)
2936 ParentUpAcknowledgePowerChange_Delayed();
2938 // If we are waiting for responses, execution will resume via
2939 // all_acked() or ack timeout in ParentUpAcknowledgePowerChange_Delayed.
2943 //*********************************************************************************
2944 // ParentUpAcknowledgePowerChange_Delayed
2946 // All parties have acknowledged our post-change notification of a power
2947 // raising initiated by the parent. Here we acknowledge the parent.
2948 // We are done with this change note, and we can start on the next one.
2949 //*********************************************************************************
2951 void IOService::ParentUpAcknowledgePowerChange_Delayed ( void )
2953 IORegistryEntry
*nub
;
2956 nub
= priv
->head_note_parent
;
2959 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
2962 parent
->acknowledgePowerChange((IOService
*)nub
);
2969 //*********************************************************************************
2972 // A power change is complete, and the used post-change note is at
2973 // the head of the queue. Remove it and set myCurrentState to the result
2974 // of the change. Start up the next change in queue.
2975 //*********************************************************************************
2977 void IOService::all_done ( void )
2979 unsigned long previous_state
;
2980 IORegistryEntry
*nub
;
2983 priv
->machine_state
= kIOPM_Finished
;
2986 if ( priv
->head_note_flags
& IOPMWeInitiated
)
2988 // could our driver switch to the new state?
2989 if ( !( priv
->head_note_flags
& IOPMNotDone
) )
2991 // yes, did power raise?
2992 if ( pm_vars
->myCurrentState
< priv
->head_note_state
)
2994 // yes, inform clients and apps
2995 tellChangeUp (priv
->head_note_state
);
2997 // no, if this lowers our
2998 if ( ! priv
->we_are_root
)
3000 // power requirements, tell the parent
3001 ask_parent(priv
->head_note_state
);
3004 previous_state
= pm_vars
->myCurrentState
;
3006 pm_vars
->myCurrentState
= priv
->head_note_state
;
3007 priv
->imminentState
= pm_vars
->myCurrentState
;
3008 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeDone
,(unsigned long)pm_vars
->myCurrentState
,0);
3009 // inform subclass policy-maker
3010 powerChangeDone(previous_state
);
3014 // parent's power change
3015 if ( priv
->head_note_flags
& IOPMParentInitiated
)
3017 if ( ((priv
->head_note_flags
& IOPMDomainWillChange
) && (pm_vars
->myCurrentState
>= priv
->head_note_state
)) ||
3018 ((priv
->head_note_flags
& IOPMDomainDidChange
) && (pm_vars
->myCurrentState
< priv
->head_note_state
)) )
3021 if ( pm_vars
->myCurrentState
< priv
->head_note_state
)
3023 // yes, inform clients and apps
3024 tellChangeUp (priv
->head_note_state
);
3027 previous_state
= pm_vars
->myCurrentState
;
3028 pm_vars
->myCurrentState
= priv
->head_note_state
;
3029 priv
->imminentState
= pm_vars
->myCurrentState
;
3030 pm_vars
->maxCapability
= pm_vars
->theControllingDriver
->maxCapabilityForDomainState(priv
->head_note_domainState
);
3032 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogChangeDone
,(unsigned long)pm_vars
->myCurrentState
,0);
3033 // inform subclass policy-maker
3034 powerChangeDone(previous_state
);
3038 IOLockLock(priv
->queue_lock
);
3039 // we're done with this
3040 priv
->changeList
->releaseHeadChangeNote();
3042 // start next one in queue
3043 priv
->head_note
= priv
->changeList
->currentChange();
3044 if ( priv
->head_note
!= -1 )
3047 IOLockUnlock(priv
->queue_lock
);
3048 if (priv
->changeList
->changeNote
[priv
->head_note
].flags
& IOPMWeInitiated
)
3050 start_our_change(priv
->head_note
);
3052 nub
= priv
->changeList
->changeNote
[priv
->head_note
].parent
;
3053 if ( start_parent_change(priv
->head_note
) == IOPMAckImplied
)
3055 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
3058 parent
->acknowledgePowerChange((IOService
*)nub
);
3064 IOLockUnlock(priv
->queue_lock
);
3070 //*********************************************************************************
3073 // A driver or child has acknowledged our notification of an upcoming power
3074 // change, and this acknowledgement is the last one pending
3075 // before we change power or after changing power.
3077 //*********************************************************************************
3079 void IOService::all_acked ( void )
3081 switch (priv
->machine_state
) {
3082 case kIOPM_OurChangeSetPowerState
:
3083 OurChangeSetPowerState();
3085 case kIOPM_OurChangeFinish
:
3088 case kIOPM_ParentDownSetPowerState_Delayed
:
3089 ParentDownSetPowerState_Delayed();
3091 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3092 ParentDownAcknowledgeChange_Delayed();
3094 case kIOPM_ParentUpSetPowerState_Delayed
:
3095 ParentUpSetPowerState_Delayed();
3097 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3098 ParentUpAcknowledgePowerChange_Delayed();
3103 //*********************************************************************************
3104 // settleTimerExpired
3106 // Power has settled after our last change. Notify interested parties that
3107 // there is a new power state.
3108 //*********************************************************************************
3110 void IOService::settleTimerExpired ( void )
3112 if ( ! initialized
)
3118 switch (priv
->machine_state
) {
3119 case kIOPM_OurChangeNotifyInterestedDriversDidChange
:
3120 OurChangeNotifyInterestedDriversDidChange();
3122 case kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
:
3123 ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed();
3125 case kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed
:
3126 ParentUpNotifyInterestedDriversDidChange_Delayed();
3132 //*********************************************************************************
3133 // compute_settle_time
3135 // Compute the power-settling delay in microseconds for the
3136 // change from myCurrentState to head_note_state.
3137 //*********************************************************************************
3139 unsigned long IOService::compute_settle_time ( void )
3141 unsigned long totalTime
;
3144 // compute total time to attain the new state
3146 i
= pm_vars
->myCurrentState
;
3148 // we're lowering power
3149 if ( priv
->head_note_state
< pm_vars
->myCurrentState
)
3151 while ( i
> priv
->head_note_state
)
3153 totalTime
+= pm_vars
->thePowerStates
[i
].settleDownTime
;
3158 // we're raising power
3159 if ( priv
->head_note_state
> pm_vars
->myCurrentState
)
3161 while ( i
< priv
->head_note_state
)
3163 totalTime
+= pm_vars
->thePowerStates
[i
+1].settleUpTime
;
3172 //*********************************************************************************
3175 // Enter with a power-settling delay in microseconds and start a nano-second
3176 // timer for that delay.
3177 //*********************************************************************************
3179 IOReturn
IOService::startSettleTimer ( unsigned long delay
)
3181 AbsoluteTime deadline
;
3183 clock_interval_to_deadline(delay
, kMicrosecondScale
, &deadline
);
3185 thread_call_enter_delayed(priv
->settleTimer
, deadline
);
3190 //*********************************************************************************
3193 // The acknowledgement timeout periodic timer has ticked.
3194 // If we are awaiting acks for a power change notification,
3195 // we decrement the timer word of each interested driver which hasn't acked.
3196 // If a timer word becomes zero, we pretend the driver aknowledged.
3197 // If we are waiting for the controlling driver to change the power
3198 // state of the hardware, we decrement its timer word, and if it becomes
3199 // zero, we pretend the driver acknowledged.
3200 //*********************************************************************************
3202 void IOService::ack_timer_ticked ( void )
3204 IOPMinformee
* nextObject
;
3206 if ( ! initialized
)
3212 if (! acquire_lock() )
3217 switch (priv
->machine_state
) {
3218 case kIOPM_OurChangeWaitForPowerSettle
:
3219 case kIOPM_ParentDownWaitForPowerSettle_Delayed
:
3220 case kIOPM_ParentUpWaitForSettleTime_Delayed
:
3221 // are we waiting for our driver to make its change?
3222 if ( priv
->driver_timer
!= 0 ) {
3224 priv
->driver_timer
-= 1;
3225 // it's tardy, we'll go on without it
3226 if ( priv
->driver_timer
== 0 )
3228 IOUnlock(priv
->our_lock
);
3229 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogCtrlDriverTardy
,0,0);
3232 // still waiting, set timer again
3234 IOUnlock(priv
->our_lock
);
3238 IOUnlock(priv
->our_lock
);
3242 case kIOPM_OurChangeSetPowerState
:
3243 case kIOPM_OurChangeFinish
:
3244 case kIOPM_ParentDownSetPowerState_Delayed
:
3245 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3246 case kIOPM_ParentUpSetPowerState_Delayed
:
3247 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3248 // are we waiting for interested parties to acknowledge?
3249 if (priv
->head_note_pendingAcks
!= 0 )
3251 // yes, go through the list of interested drivers
3252 nextObject
= priv
->interestedDrivers
->firstInList();
3253 // and check each one
3254 while ( nextObject
!= NULL
)
3256 if ( nextObject
->timer
> 0 )
3258 nextObject
->timer
-= 1;
3259 // this one should have acked by now
3260 if ( nextObject
->timer
== 0 )
3262 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogIntDriverTardy
,0,0);
3263 //kprintf("interested driver tardy: %s\n",nextObject->whatObject->getName());
3264 priv
->head_note_pendingAcks
-= 1;
3267 nextObject
= priv
->interestedDrivers
->nextInList(nextObject
);
3270 // is that the last?
3271 if ( priv
->head_note_pendingAcks
== 0 )
3273 IOUnlock(priv
->our_lock
);
3274 // yes, we can continue
3277 // no, set timer again
3279 IOUnlock(priv
->our_lock
);
3282 IOUnlock(priv
->our_lock
);
3286 // apps didn't respond to parent-down notification
3287 case kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate
:
3288 IOUnlock(priv
->our_lock
);
3289 IOLockLock(priv
->flags_lock
);
3290 if (pm_vars
->responseFlags
)
3292 // get rid of this stuff
3293 pm_vars
->responseFlags
->release();
3294 pm_vars
->responseFlags
= NULL
;
3296 IOLockUnlock(priv
->flags_lock
);
3297 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,5);
3298 // carry on with the change
3299 ParentDownTellPriorityClientsPowerDown_Delayed();
3302 case kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
:
3303 IOUnlock(priv
->our_lock
);
3304 IOLockLock(priv
->flags_lock
);
3305 if (pm_vars
->responseFlags
)
3307 // get rid of this stuff
3308 pm_vars
->responseFlags
->release();
3309 pm_vars
->responseFlags
= NULL
;
3311 IOLockUnlock(priv
->flags_lock
);
3312 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,1);
3313 // carry on with the change
3314 ParentDownNotifyInterestedDriversWillChange_Delayed();
3317 case kIOPM_OurChangeTellClientsPowerDown
:
3318 // apps didn't respond to our power-down request
3319 IOUnlock(priv
->our_lock
);
3320 IOLockLock(priv
->flags_lock
);
3321 if (pm_vars
->responseFlags
)
3323 // get rid of this stuff
3324 pm_vars
->responseFlags
->release();
3325 pm_vars
->responseFlags
= NULL
;
3327 IOLockUnlock(priv
->flags_lock
);
3328 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,2);
3329 // rescind the request
3330 tellNoChangeDown(priv
->head_note_state
);
3331 // mark the change note un-actioned
3332 priv
->head_note_flags
|= IOPMNotDone
;
3337 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
3338 // clients didn't respond to our power-down note
3339 IOUnlock(priv
->our_lock
);
3340 IOLockLock(priv
->flags_lock
);
3341 if (pm_vars
->responseFlags
)
3343 // get rid of this stuff
3344 pm_vars
->responseFlags
->release();
3345 pm_vars
->responseFlags
= NULL
;
3347 IOLockUnlock(priv
->flags_lock
);
3348 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,4);
3349 // carry on with the change
3350 OurChangeTellPriorityClientsPowerDown();
3353 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
3354 // apps didn't respond to our power-down notification
3355 IOUnlock(priv
->our_lock
);
3356 IOLockLock(priv
->flags_lock
);
3357 if (pm_vars
->responseFlags
)
3359 // get rid of this stuff
3360 pm_vars
->responseFlags
->release();
3361 pm_vars
->responseFlags
= NULL
;
3363 IOLockUnlock(priv
->flags_lock
);
3364 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientTardy
,0,3);
3365 // carry on with the change
3366 OurChangeNotifyInterestedDriversWillChange();
3370 // not waiting for acks
3371 IOUnlock(priv
->our_lock
);
3377 //*********************************************************************************
3380 //*********************************************************************************
3382 void IOService::start_ack_timer ( void )
3384 AbsoluteTime deadline
;
3386 clock_interval_to_deadline(ACK_TIMER_PERIOD
, kNanosecondScale
, &deadline
);
3388 thread_call_enter_delayed(priv
->ackTimer
, deadline
);
3392 //*********************************************************************************
3395 //*********************************************************************************
3397 void IOService::stop_ack_timer ( void )
3399 thread_call_cancel(priv
->ackTimer
);
3403 //*********************************************************************************
3404 // c-language timer expiration functions
3406 //*********************************************************************************
3408 static void ack_timer_expired ( thread_call_param_t us
)
3410 ((IOService
*)us
)->ack_timer_ticked();
3414 static void settle_timer_expired ( thread_call_param_t us
)
3416 ((IOService
*)us
)->settleTimerExpired();
3420 //*********************************************************************************
3421 // add_child_to_active_change
3423 // A child has just registered with us. If there is
3424 // currently a change in progress, get the new party involved: if we
3425 // have notified all parties and are waiting for acks, notify the new
3427 //*********************************************************************************
3429 IOReturn
IOService::add_child_to_active_change ( IOPowerConnection
* newObject
)
3431 if (! acquire_lock() )
3436 switch (priv
->machine_state
)
3438 case kIOPM_OurChangeSetPowerState
:
3439 case kIOPM_ParentDownSetPowerState_Delayed
:
3440 case kIOPM_ParentUpSetPowerState_Delayed
:
3441 // one for this child and one to prevent
3442 priv
->head_note_pendingAcks
+= 2;
3443 // incoming acks from changing our state
3444 IOUnlock(priv
->our_lock
);
3445 notifyChild(newObject
, true);
3446 if (! acquire_lock() )
3449 --priv
->head_note_pendingAcks
;
3452 // are we still waiting for acks?
3453 if ( --priv
->head_note_pendingAcks
== 0 )
3455 // no, stop the timer
3457 IOUnlock(priv
->our_lock
);
3459 // and now we can continue
3464 case kIOPM_OurChangeFinish
:
3465 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3466 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3467 // one for this child and one to prevent
3468 priv
->head_note_pendingAcks
+= 2;
3469 // incoming acks from changing our state
3470 IOUnlock(priv
->our_lock
);
3471 notifyChild(newObject
, false);
3472 if (! acquire_lock() )
3475 --priv
->head_note_pendingAcks
;
3478 // are we still waiting for acks?
3479 if ( --priv
->head_note_pendingAcks
== 0 )
3481 // no, stop the timer
3483 IOUnlock(priv
->our_lock
);
3485 // and now we can continue
3491 IOUnlock(priv
->our_lock
);
3496 //*********************************************************************************
3497 // add_driver_to_active_change
3499 // An interested driver has just registered with us. If there is
3500 // currently a change in progress, get the new party involved: if we
3501 // have notified all parties and are waiting for acks, notify the new
3503 //*********************************************************************************
3505 IOReturn
IOService::add_driver_to_active_change ( IOPMinformee
* newObject
)
3507 if (! acquire_lock() )
3512 switch (priv
->machine_state
) {
3513 case kIOPM_OurChangeSetPowerState
:
3514 case kIOPM_ParentDownSetPowerState_Delayed
:
3515 case kIOPM_ParentUpSetPowerState_Delayed
:
3516 // one for this driver and one to prevent
3517 priv
->head_note_pendingAcks
+= 2;
3518 // incoming acks from changing our state
3519 IOUnlock(priv
->our_lock
);
3520 // inform the driver
3521 inform(newObject
, true);
3522 if (! acquire_lock() )
3525 --priv
->head_note_pendingAcks
;
3528 // are we still waiting for acks?
3529 if ( --priv
->head_note_pendingAcks
== 0 )
3531 // no, stop the timer
3533 IOUnlock(priv
->our_lock
);
3535 // and now we can continue
3540 case kIOPM_OurChangeFinish
:
3541 case kIOPM_ParentDownAcknowledgeChange_Delayed
:
3542 case kIOPM_ParentUpAcknowledgePowerChange_Delayed
:
3543 // one for this driver and one to prevent
3544 priv
->head_note_pendingAcks
+= 2;
3545 // incoming acks from changing our state
3546 IOUnlock(priv
->our_lock
);
3547 // inform the driver
3548 inform(newObject
, false);
3549 if (! acquire_lock() ) {
3551 --priv
->head_note_pendingAcks
;
3554 // are we still waiting for acks?
3555 if ( --priv
->head_note_pendingAcks
== 0 ) {
3556 // no, stop the timer
3558 IOUnlock(priv
->our_lock
);
3560 // and now we can continue
3566 IOUnlock(priv
->our_lock
);
3571 //*********************************************************************************
3572 // start_parent_change
3574 // Here we begin the processing of a change note initiated by our parent
3575 // which is at the head of the queue.
3577 // It is possible for the change to be processed to completion and removed from the queue.
3578 // There are several possible interruptions to the processing, though, and they are:
3579 // we may have to wait for interested parties to acknowledge our pre-change notification,
3580 // we may have to wait for our controlling driver to change the hardware power state,
3581 // there may be a settling time after changing the hardware power state,
3582 // we may have to wait for interested parties to acknowledge our post-change notification,
3583 // we may have to wait for the acknowledgement timer expiration to substitute for the
3584 // acknowledgement from a failing driver.
3585 //*********************************************************************************
3587 IOReturn
IOService::start_parent_change ( unsigned long queue_head
)
3589 priv
->head_note
= queue_head
;
3590 priv
->head_note_flags
= priv
-> changeList
->changeNote
[priv
->head_note
].flags
;
3591 priv
->head_note_state
= priv
->changeList
->changeNote
[priv
->head_note
].newStateNumber
;
3592 priv
->imminentState
= priv
->head_note_state
;
3593 priv
->head_note_outputFlags
= priv
->changeList
->changeNote
[priv
->head_note
].outputPowerCharacter
;
3594 priv
->head_note_domainState
= priv
->changeList
->changeNote
[priv
->head_note
].domainState
;
3595 priv
->head_note_parent
= priv
->changeList
->changeNote
[priv
->head_note
].parent
;
3596 priv
->head_note_capabilityFlags
= priv
->changeList
->changeNote
[priv
->head_note
].capabilityFlags
;
3598 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartParentChange
,
3599 (unsigned long)priv
->head_note_state
,(unsigned long)pm_vars
->myCurrentState
);
3601 // if we need something and haven't told the parent, do so
3602 ask_parent( priv
->ourDesiredPowerState
);
3604 // power domain is lowering
3605 if ( priv
->head_note_state
< pm_vars
->myCurrentState
)
3607 setParentInfo(priv
->changeList
->changeNote
[priv
->head_note
].singleParentState
,priv
->head_note_parent
);
3608 priv
->initial_change
= false;
3609 // tell apps and kernel clients
3610 priv
->machine_state
= kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate
;
3612 // are we waiting for responses?
3613 if ( tellChangeDown1(priv
->head_note_state
) )
3615 // no, notify priority clients
3616 return ParentDownTellPriorityClientsPowerDown_Immediate();
3619 return IOPMWillAckLater
;
3622 // parent is raising power, we may or may not
3623 if ( priv
->head_note_state
> pm_vars
->myCurrentState
)
3625 if ( priv
->ourDesiredPowerState
> pm_vars
->myCurrentState
)
3627 if ( priv
->ourDesiredPowerState
< priv
->head_note_state
)
3629 // we do, but not all the way
3630 priv
->head_note_state
= priv
->ourDesiredPowerState
;
3631 priv
->imminentState
= priv
->head_note_state
;
3632 priv
->head_note_outputFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].outputPowerCharacter
;
3633 priv
->head_note_capabilityFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].capabilityFlags
;
3634 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAmendParentChange
,(unsigned long)priv
->head_note_state
,0);
3638 priv
->head_note_state
= pm_vars
->myCurrentState
;
3639 priv
->imminentState
= priv
->head_note_state
;
3640 priv
->head_note_outputFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].outputPowerCharacter
;
3641 priv
->head_note_capabilityFlags
= pm_vars
->thePowerStates
[priv
->head_note_state
].capabilityFlags
;
3642 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAmendParentChange
,(unsigned long)priv
->head_note_state
,0);
3646 if ( (priv
->head_note_state
> pm_vars
->myCurrentState
) &&
3647 (priv
->head_note_flags
& IOPMDomainDidChange
) )
3650 priv
->initial_change
= false;
3651 priv
->machine_state
= kIOPM_ParentUpSetPowerState_Delayed
;
3652 if ( notifyAll(true) == IOPMAckImplied
) {
3653 return ParentUpSetPowerState_Immediate();
3655 // they didn't all ack
3656 return IOPMWillAckLater
;
3660 // a null change or power will go up
3661 return IOPMAckImplied
;
3665 //*********************************************************************************
3668 // Here we begin the processing of a change note initiated by us
3669 // which is at the head of the queue.
3671 // It is possible for the change to be processed to completion and removed from the queue.
3672 // There are several possible interruptions to the processing, though, and they are:
3673 // we may have to wait for interested parties to acknowledge our pre-change notification,
3674 // changes initiated by the parent will wait in the middle for powerStateDidChange,
3675 // we may have to wait for our controlling driver to change the hardware power state,
3676 // there may be a settling time after changing the hardware power state,
3677 // we may have to wait for interested parties to acknowledge our post-change notification,
3678 // we may have to wait for the acknowledgement timer expiration to substitute for the
3679 // acknowledgement from a failing driver.
3680 //*********************************************************************************
3682 void IOService::start_our_change ( unsigned long queue_head
)
3684 priv
->head_note
= queue_head
;
3685 priv
->head_note_flags
= priv
->changeList
->changeNote
[priv
->head_note
].flags
;
3686 priv
->head_note_state
= priv
->changeList
->changeNote
[priv
->head_note
].newStateNumber
;
3687 priv
->imminentState
= priv
->head_note_state
;
3688 priv
->head_note_outputFlags
= priv
->changeList
->changeNote
[priv
->head_note
].outputPowerCharacter
;
3689 priv
->head_note_capabilityFlags
= priv
->changeList
->changeNote
[priv
->head_note
].capabilityFlags
;
3691 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartDeviceChange
,
3692 (unsigned long)priv
->head_note_state
,(unsigned long)pm_vars
->myCurrentState
);
3694 // can our driver switch to the new state?
3695 if ( priv
->head_note_capabilityFlags
& IOPMNotAttainable
)
3697 // no, ask the parent to do it then
3698 if ( ! priv
->we_are_root
)
3700 ask_parent(priv
->head_note_state
);
3702 // mark the change note un-actioned
3703 priv
-> head_note_flags
|= IOPMNotDone
;
3709 // is there enough power in the domain?
3710 if ( (pm_vars
->maxCapability
< priv
->head_note_state
) && (! priv
->we_are_root
) )
3712 // no, ask the parent to raise it
3713 if ( ! priv
->we_are_root
)
3715 ask_parent(priv
->head_note_state
);
3717 // no, mark the change note un-actioned
3718 priv
->head_note_flags
|= IOPMNotDone
;
3720 // till the parent raises power
3725 if ( ! priv
->initial_change
)
3727 if ( priv
->head_note_state
== pm_vars
->myCurrentState
)
3729 // we initiated a null change; forget it
3734 priv
->initial_change
= false;
3737 if ( priv
->head_note_state
< pm_vars
->myCurrentState
)
3739 // yes, in case we have to wait for acks
3740 priv
->machine_state
= kIOPM_OurChangeTellClientsPowerDown
;
3741 pm_vars
->doNotPowerDown
= false;
3743 // ask apps and kernel clients if we can drop power
3744 pm_vars
->outofbandparameter
= kNotifyApps
;
3745 if ( askChangeDown(priv
->head_note_state
) )
3747 // don't have to wait, did any clients veto?
3748 if ( pm_vars
->doNotPowerDown
)
3750 // yes, rescind the warning
3751 tellNoChangeDown(priv
->head_note_state
);
3752 // mark the change note un-actioned
3753 priv
-> head_note_flags
|= IOPMNotDone
;
3757 // no, tell'em we're dropping power
3758 OurChangeTellClientsPowerDown();
3762 // we are raising power
3763 if ( ! priv
->we_are_root
)
3765 // if this changes our power requirement, tell the parent
3766 ask_parent(priv
->head_note_state
);
3768 // in case they don't all ack
3769 priv
->machine_state
= kIOPM_OurChangeSetPowerState
;
3771 // notify interested drivers and children
3772 if ( notifyAll(true) == IOPMAckImplied
)
3774 OurChangeSetPowerState();
3780 //*********************************************************************************
3783 // Call the power domain parent to ask for a higher power state in the domain
3784 // or to suggest a lower power state.
3785 //*********************************************************************************
3787 IOReturn
IOService::ask_parent ( unsigned long requestedState
)
3791 IOPowerConnection
*connection
;
3793 unsigned long ourRequest
= pm_vars
->thePowerStates
[requestedState
].inputPowerRequirement
;
3795 if ( pm_vars
->thePowerStates
[requestedState
].capabilityFlags
& (kIOPMChildClamp
| kIOPMPreventIdleSleep
) )
3797 ourRequest
|= kIOPMPreventIdleSleep
;
3799 if ( pm_vars
->thePowerStates
[requestedState
].capabilityFlags
& (kIOPMChildClamp2
| kIOPMPreventSystemSleep
) )
3801 ourRequest
|= kIOPMPreventSystemSleep
;
3804 // is this a new desire?
3805 if ( priv
->previousRequest
== ourRequest
)
3807 // no, the parent knows already, just return
3811 if ( priv
->we_are_root
)
3815 priv
->previousRequest
= ourRequest
;
3817 iter
= getParentIterator(gIOPowerPlane
);
3821 while ( (next
= iter
->getNextObject()) )
3823 if ( (connection
= OSDynamicCast(IOPowerConnection
,next
)) )
3825 parent
= (IOService
*)connection
->copyParentEntry(gIOPowerPlane
);
3827 if ( parent
->requestPowerDomainState(ourRequest
,connection
,IOPMLowestState
)!= IOPMNoErr
)
3829 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogRequestDenied
,
3830 (unsigned long)priv
->previousRequest
,0);
3843 //*********************************************************************************
3846 // Call the controlling driver and have it change the power state of the
3847 // hardware. If it returns IOPMAckImplied, the change is complete, and
3848 // we return IOPMAckImplied. Otherwise, it will ack when the change
3849 // is done; we return IOPMWillAckLater.
3850 //*********************************************************************************
3851 IOReturn
IOService::instruct_driver ( unsigned long newState
)
3853 IOReturn return_code
;
3855 // can our driver switch to the desired state?
3856 if ( pm_vars
->thePowerStates
[newState
].capabilityFlags
& IOPMNotAttainable
)
3859 return IOPMAckImplied
;
3862 priv
->driver_timer
= -1;
3863 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogProgramHardware
,newState
,0);
3866 ioSPMTraceStart(IOPOWER_STATE
, * (int *) this, (int) newState
);
3867 return_code
= pm_vars
->theControllingDriver
->setPowerState( newState
,this );
3868 ioSPMTraceEnd(IOPOWER_STATE
, * (int *) this, (int) newState
, (int) return_code
);
3871 if ( return_code
== IOPMAckImplied
)
3873 priv
->driver_timer
= 0;
3874 return IOPMAckImplied
;
3877 // it acked behind our back
3878 if ( priv
->driver_timer
== 0 )
3880 return IOPMAckImplied
;
3884 if ( return_code
< 0 )
3886 return IOPMAckImplied
;
3890 priv
->driver_timer
= (return_code
/ ( ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
3891 return IOPMWillAckLater
;
3895 //*********************************************************************************
3898 // We are acquiring the lock we use to protect our queue head from
3899 // simutaneous access by a thread which calls acknowledgePowerStateChange
3900 // or acknowledgeSetPowerState and the ack timer expiration thread.
3901 // Return TRUE if we acquire the lock, and the queue head didn't change
3902 // while we were acquiring the lock (and maybe blocked).
3903 // If there is no queue head, or it changes while we are blocked,
3904 // return FALSE with the lock unlocked.
3905 //*********************************************************************************
3907 bool IOService::acquire_lock ( void )
3909 long current_change_note
;
3911 current_change_note
= priv
->head_note
;
3912 if ( current_change_note
== -1 ) {
3916 IOTakeLock(priv
->our_lock
);
3917 if ( current_change_note
== priv
->head_note
)
3921 // we blocked and something changed radically
3922 // so there's nothing to do any more
3923 IOUnlock(priv
->our_lock
);
3929 //*********************************************************************************
3932 // Ask registered applications and kernel clients if we can change to a lower
3935 // Subclass can override this to send a different message type. Parameter is
3936 // the destination state number.
3938 // Return true if we don't have to wait for acknowledgements
3939 //*********************************************************************************
3941 bool IOService::askChangeDown ( unsigned long stateNum
)
3943 return tellClientsWithResponse(kIOMessageCanDevicePowerOff
);
3947 //*********************************************************************************
3950 // Notify registered applications and kernel clients that we are definitely
3953 // Return true if we don't have to wait for acknowledgements
3954 //*********************************************************************************
3956 bool IOService::tellChangeDown1 ( unsigned long stateNum
)
3958 pm_vars
->outofbandparameter
= kNotifyApps
;
3959 return tellChangeDown(stateNum
);
3963 //*********************************************************************************
3966 // Notify priority clients that we are definitely dropping power.
3968 // Return true if we don't have to wait for acknowledgements
3969 //*********************************************************************************
3971 bool IOService::tellChangeDown2 ( unsigned long stateNum
)
3973 pm_vars
->outofbandparameter
= kNotifyPriority
;
3974 return tellChangeDown(stateNum
);
3978 //*********************************************************************************
3981 // Notify registered applications and kernel clients that we are definitely
3984 // Subclass can override this to send a different message type. Parameter is
3985 // the destination state number.
3987 // Return true if we don't have to wait for acknowledgements
3988 //*********************************************************************************
3990 bool IOService::tellChangeDown ( unsigned long stateNum
)
3992 return tellClientsWithResponse(kIOMessageDeviceWillPowerOff
);
3996 //*********************************************************************************
3997 // tellClientsWithResponse
3999 // Notify registered applications and kernel clients that we are definitely
4002 // Return true if we don't have to wait for acknowledgements
4003 //*********************************************************************************
4005 bool IOService::tellClientsWithResponse ( int messageType
)
4007 struct context theContext
;
4008 AbsoluteTime deadline
;
4011 pm_vars
->responseFlags
= OSArray::withCapacity( 1 );
4012 pm_vars
->serialNumber
+= 1;
4014 theContext
.responseFlags
= pm_vars
->responseFlags
;
4015 theContext
.serialNumber
= pm_vars
->serialNumber
;
4016 theContext
.flags_lock
= priv
->flags_lock
;
4017 theContext
.counter
= 1;
4018 theContext
.msgType
= messageType
;
4019 theContext
.us
= this;
4020 theContext
.maxTimeRequested
= 0;
4021 theContext
.stateNumber
= priv
->head_note_state
;
4022 theContext
.stateFlags
= priv
->head_note_capabilityFlags
;
4024 IOLockLock(priv
->flags_lock
);
4026 // position zero is false to
4027 // prevent allowCancelCommon from succeeding
4028 aBool
= OSBoolean::withBoolean(false);
4029 theContext
.responseFlags
->setObject(0,aBool
);
4031 IOLockUnlock(priv
->flags_lock
);
4033 switch ( pm_vars
->outofbandparameter
) {
4035 applyToInterested(gIOAppPowerStateInterest
,tellAppWithResponse
,(void *)&theContext
);
4036 applyToInterested(gIOGeneralInterest
,tellClientWithResponse
,(void *)&theContext
);
4038 case kNotifyPriority
:
4039 applyToInterested(gIOPriorityPowerStateInterest
,tellClientWithResponse
,(void *)&theContext
);
4043 if (! acquire_lock() )
4047 IOLockLock(priv
->flags_lock
);
4048 // now fix position zero
4049 aBool
= OSBoolean::withBoolean(true);
4050 theContext
.responseFlags
->replaceObject(0,aBool
);
4052 IOLockUnlock(priv
->flags_lock
);
4054 // do we have to wait for somebody?
4055 if ( ! checkForDone() )
4057 // yes, start the ackTimer
4058 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogStartAckTimer
,theContext
.maxTimeRequested
,0);
4059 clock_interval_to_deadline(theContext
.maxTimeRequested
/ 1000, kMillisecondScale
, &deadline
);
4061 thread_call_enter_delayed(priv
->ackTimer
, deadline
);
4063 IOUnlock(priv
->our_lock
);
4067 IOUnlock(priv
->our_lock
);
4068 IOLockLock(priv
->flags_lock
);
4070 // everybody responded
4071 pm_vars
->responseFlags
->release();
4072 pm_vars
->responseFlags
= NULL
;
4073 IOLockUnlock(priv
->flags_lock
);
4079 //*********************************************************************************
4080 // tellAppWithResponse
4082 // We send a message to an application, and we expect a response, so we compute a
4083 // cookie we can identify the response with.
4084 //*********************************************************************************
4085 void tellAppWithResponse ( OSObject
* object
, void * context
)
4087 struct context
*theContext
= (struct context
*)context
;
4091 if( OSDynamicCast( IOService
, object
) )
4093 IOLockLock(theContext
->flags_lock
);
4094 aBool
= OSBoolean::withBoolean(true);
4095 theContext
->responseFlags
->setObject(theContext
->counter
,aBool
);
4097 IOLockUnlock(theContext
->flags_lock
);
4099 refcon
= ((theContext
->serialNumber
& 0xFFFF)<<16) + (theContext
->counter
& 0xFFFF);
4100 IOLockLock(theContext
->flags_lock
);
4101 aBool
= OSBoolean::withBoolean(false);
4102 theContext
->responseFlags
->setObject(theContext
->counter
,aBool
);
4104 IOLockUnlock(theContext
->flags_lock
);
4105 theContext
->us
->messageClient(theContext
->msgType
,object
,(void *)refcon
);
4106 if ( theContext
->maxTimeRequested
< k30seconds
)
4108 theContext
->maxTimeRequested
= k30seconds
;
4111 theContext
->counter
+= 1;
4115 //*********************************************************************************
4116 // tellClientWithResponse
4118 // We send a message to an in-kernel client, and we expect a response, so we compute a
4119 // cookie we can identify the response with.
4120 // If it doesn't understand the notification (it is not power-management savvy)
4121 // we won't wait for it to prepare for sleep. If it tells us via a return code
4122 // in the passed struct that it is currently ready, we won't wait for it to prepare.
4123 // If it tells us via the return code in the struct that it does need time, we will chill.
4124 //*********************************************************************************
4125 void tellClientWithResponse ( OSObject
* object
, void * context
)
4127 struct context
*theContext
= (struct context
*)context
;
4128 IOPowerStateChangeNotification notify
;
4134 refcon
= ((theContext
->serialNumber
& 0xFFFF)<<16) + (theContext
->counter
& 0xFFFF);
4135 IOLockLock(theContext
->flags_lock
);
4136 aBool
= OSBoolean::withBoolean(false);
4137 theContext
->responseFlags
->setObject(theContext
->counter
,aBool
);
4139 IOLockUnlock(theContext
->flags_lock
);
4141 notify
.powerRef
= (void *)refcon
;
4142 notify
.returnValue
= 0;
4143 notify
.stateNumber
= theContext
->stateNumber
;
4144 notify
.stateFlags
= theContext
->stateFlags
;
4145 retCode
= theContext
->us
->messageClient(theContext
->msgType
,object
,(void *)¬ify
);
4146 if ( retCode
== kIOReturnSuccess
)
4148 if ( notify
.returnValue
== 0 )
4150 // client doesn't want time to respond
4151 IOLockLock(theContext
->flags_lock
);
4152 aBool
= OSBoolean::withBoolean(true);
4153 // so set its flag true
4154 theContext
->responseFlags
->replaceObject(theContext
->counter
,aBool
);
4156 IOLockUnlock(theContext
->flags_lock
);
4158 IOLockLock(theContext
->flags_lock
);
4160 // it does want time, and it hasn't responded yet
4161 theFlag
= theContext
->responseFlags
->getObject(theContext
->counter
);
4164 if ( ((OSBoolean
*)theFlag
)->isFalse() )
4166 // so note its time requirement
4167 if ( theContext
->maxTimeRequested
< notify
.returnValue
)
4169 theContext
->maxTimeRequested
= notify
.returnValue
;
4173 IOLockUnlock(theContext
->flags_lock
);
4176 // not a client of ours
4177 IOLockLock(theContext
->flags_lock
);
4178 // so we won't be waiting for response
4179 aBool
= OSBoolean::withBoolean(true);
4180 theContext
->responseFlags
->replaceObject(theContext
->counter
,aBool
);
4182 IOLockUnlock(theContext
->flags_lock
);
4184 theContext
->counter
+= 1;
4188 //*********************************************************************************
4191 // Notify registered applications and kernel clients that we are not
4194 // Subclass can override this to send a different message type. Parameter is
4195 // the aborted destination state number.
4196 //*********************************************************************************
4198 void IOService::tellNoChangeDown ( unsigned long )
4200 return tellClients(kIOMessageDeviceWillNotPowerOff
);
4204 //*********************************************************************************
4207 // Notify registered applications and kernel clients that we are raising power.
4209 // Subclass can override this to send a different message type. Parameter is
4210 // the aborted destination state number.
4211 //*********************************************************************************
4213 void IOService::tellChangeUp ( unsigned long )
4215 return tellClients(kIOMessageDeviceHasPoweredOn
);
4219 //*********************************************************************************
4222 // Notify registered applications and kernel clients of something.
4223 //*********************************************************************************
4225 void IOService::tellClients ( int messageType
)
4227 struct context theContext
;
4229 theContext
.msgType
= messageType
;
4230 theContext
.us
= this;
4231 theContext
.stateNumber
= priv
->head_note_state
;
4232 theContext
.stateFlags
= priv
->head_note_capabilityFlags
;
4234 applyToInterested(gIOAppPowerStateInterest
,tellClient
,(void *)&theContext
);
4235 applyToInterested(gIOGeneralInterest
,tellClient
,(void *)&theContext
);
4239 //*********************************************************************************
4242 // Notify a registered application or kernel client of something.
4243 //*********************************************************************************
4244 void tellClient ( OSObject
* object
, void * context
)
4246 struct context
*theContext
= (struct context
*)context
;
4247 IOPowerStateChangeNotification notify
;
4249 notify
.powerRef
= (void *) 0;
4250 notify
.returnValue
= 0;
4251 notify
.stateNumber
= theContext
->stateNumber
;
4252 notify
.stateFlags
= theContext
->stateFlags
;
4254 theContext
->us
->messageClient(theContext
->msgType
,object
, ¬ify
);
4258 // **********************************************************************************
4261 // **********************************************************************************
4262 bool IOService::checkForDone ( void )
4267 IOLockLock(priv
->flags_lock
);
4268 if ( pm_vars
->responseFlags
== NULL
)
4270 IOLockUnlock(priv
->flags_lock
);
4274 for ( i
= 0; ; i
++ )
4276 theFlag
= pm_vars
->responseFlags
->getObject(i
);
4277 if ( theFlag
== NULL
)
4281 if ( ((OSBoolean
*)theFlag
)->isFalse() )
4283 IOLockUnlock(priv
->flags_lock
);
4287 IOLockUnlock(priv
->flags_lock
);
4292 // **********************************************************************************
4295 // **********************************************************************************
4296 bool IOService::responseValid ( unsigned long x
)
4298 UInt16 serialComponent
;
4299 UInt16 ordinalComponent
;
4301 unsigned long refcon
= (unsigned long)x
;
4304 serialComponent
= (refcon
>>16) & 0xFFFF;
4305 ordinalComponent
= refcon
& 0xFFFF;
4307 if ( serialComponent
!= pm_vars
->serialNumber
)
4312 IOLockLock(priv
->flags_lock
);
4313 if ( pm_vars
->responseFlags
== NULL
)
4315 IOLockUnlock(priv
->flags_lock
);
4319 theFlag
= pm_vars
->responseFlags
->getObject(ordinalComponent
);
4323 IOLockUnlock(priv
->flags_lock
);
4327 if ( ((OSBoolean
*)theFlag
)->isFalse() )
4329 aBool
= OSBoolean::withBoolean(true);
4330 pm_vars
->responseFlags
->replaceObject(ordinalComponent
,aBool
);
4334 IOLockUnlock(priv
->flags_lock
);
4339 // **********************************************************************************
4342 // Our power state is about to lower, and we have notified applications
4343 // and kernel clients, and one of them has acknowledged. If this is the last to do
4344 // so, and all acknowledgements are positive, we continue with the power change.
4346 // We serialize this processing with timer expiration with a command gate on the
4347 // power management workloop, which the timer expiration is command gated to as well.
4348 // **********************************************************************************
4349 IOReturn
IOService::allowPowerChange ( unsigned long refcon
)
4351 if ( ! initialized
)
4354 return kIOReturnSuccess
;
4357 return pm_vars
->PMcommandGate
->runAction(serializedAllowPowerChange
,(void *)refcon
);
4361 IOReturn
serializedAllowPowerChange ( OSObject
*owner
, void * refcon
, void *, void *, void *)
4363 return ((IOService
*)owner
)->serializedAllowPowerChange2((unsigned long)refcon
);
4366 IOReturn
IOService::serializedAllowPowerChange2 ( unsigned long refcon
)
4369 if ( ! responseValid(refcon
) )
4371 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr5
,refcon
,0);
4373 return kIOReturnSuccess
;
4375 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientAcknowledge
,refcon
,0);
4377 return allowCancelCommon();
4381 // **********************************************************************************
4382 // cancelPowerChange
4384 // Our power state is about to lower, and we have notified applications
4385 // and kernel clients, and one of them has vetoed the change. If this is the last
4386 // client to respond, we abandon the power change.
4388 // We serialize this processing with timer expiration with a command gate on the
4389 // power management workloop, which the timer expiration is command gated to as well.
4390 // **********************************************************************************
4391 IOReturn
IOService::cancelPowerChange ( unsigned long refcon
)
4393 if ( ! initialized
)
4396 return kIOReturnSuccess
;
4399 return pm_vars
->PMcommandGate
->runAction(serializedCancelPowerChange
,(void *)refcon
);
4403 IOReturn
serializedCancelPowerChange ( OSObject
*owner
, void * refcon
, void *, void *, void *)
4405 return ((IOService
*)owner
)->serializedCancelPowerChange2((unsigned long)refcon
);
4408 IOReturn
IOService::serializedCancelPowerChange2 ( unsigned long refcon
)
4411 if ( ! responseValid(refcon
) )
4413 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogAcknowledgeErr5
,refcon
,0);
4415 return kIOReturnSuccess
;
4417 pm_vars
->thePlatform
->PMLog(pm_vars
->ourName
,PMlogClientCancel
,refcon
,0);
4419 pm_vars
->doNotPowerDown
= true;
4421 return allowCancelCommon();
4425 // **********************************************************************************
4426 // allowCancelCommon
4428 // **********************************************************************************
4429 IOReturn
IOService::allowCancelCommon ( void )
4431 if (! acquire_lock() )
4433 return kIOReturnSuccess
;
4436 // is this the last response?
4437 if ( checkForDone() )
4439 // yes, stop the timer
4441 IOUnlock(priv
->our_lock
);
4442 IOLockLock(priv
->flags_lock
);
4443 if ( pm_vars
->responseFlags
)
4445 pm_vars
->responseFlags
->release();
4446 pm_vars
->responseFlags
= NULL
;
4448 IOLockUnlock(priv
->flags_lock
);
4449 switch (priv
->machine_state
) {
4450 case kIOPM_OurChangeTellClientsPowerDown
:
4451 // our change, was it vetoed?
4452 if ( ! pm_vars
->doNotPowerDown
)
4454 // no, we can continue
4455 OurChangeTellClientsPowerDown();
4457 // yes, rescind the warning
4458 tellNoChangeDown(priv
->head_note_state
);
4459 // mark the change note un-actioned
4460 priv
->head_note_flags
|= IOPMNotDone
;
4466 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
4467 OurChangeTellPriorityClientsPowerDown();
4469 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
4470 // our change, continue
4471 OurChangeNotifyInterestedDriversWillChange();
4473 case kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate
:
4474 // parent change, continue
4475 ParentDownTellPriorityClientsPowerDown_Delayed();
4477 case kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed
:
4478 // parent change, continue
4479 ParentDownNotifyInterestedDriversWillChange_Delayed();
4484 IOUnlock(priv
->our_lock
);
4487 return kIOReturnSuccess
;
4491 //*********************************************************************************
4494 // Set to highest available power state for a minimum of duration milliseconds
4495 //*********************************************************************************
4497 #define kFiveMinutesInNanoSeconds (300 * NSEC_PER_SEC)
4499 void IOService::clampPowerOn (unsigned long duration
)
4502 changePowerStateToPriv (pm_vars->theNumberOfPowerStates-1);
4504 if ( priv->clampTimerEventSrc == NULL ) {
4505 priv->clampTimerEventSrc = IOTimerEventSource::timerEventSource(this,
4506 c_PM_Clamp_Timer_Expired);
4508 IOWorkLoop * workLoop = getPMworkloop ();
4510 if ( !priv->clampTimerEventSrc || !workLoop ||
4511 ( workLoop->addEventSource( priv->clampTimerEventSrc) != kIOReturnSuccess) ) {
4516 priv->clampTimerEventSrc->setTimeout(300*USEC_PER_SEC, USEC_PER_SEC);
4520 //*********************************************************************************
4521 // PM_Clamp_Timer_Expired
4523 // called when clamp timer expires...set power state to 0.
4524 //*********************************************************************************
4526 void IOService::PM_Clamp_Timer_Expired (void)
4528 if ( ! initialized
)
4534 changePowerStateToPriv (0);
4537 //*********************************************************************************
4538 // c_PM_clamp_Timer_Expired (C Func)
4540 // Called when our clamp timer expires...we will call the object method.
4541 //*********************************************************************************
4543 void c_PM_Clamp_Timer_Expired (OSObject
* client
, IOTimerEventSource
*)
4546 ((IOService
*)client
)->PM_Clamp_Timer_Expired ();
4550 //*********************************************************************************
4553 // Does nothing here. This should be implemented in a subclass driver.
4554 //*********************************************************************************
4556 IOReturn
IOService::setPowerState ( unsigned long powerStateOrdinal
, IOService
* whatDevice
)
4562 //*********************************************************************************
4563 // maxCapabilityForDomainState
4565 // Finds the highest power state in the array whose input power
4566 // requirement is equal to the input parameter. Where a more intelligent
4567 // decision is possible, override this in the subclassed driver.
4568 //*********************************************************************************
4570 unsigned long IOService::maxCapabilityForDomainState ( IOPMPowerFlags domainState
)
4574 if (pm_vars
->theNumberOfPowerStates
== 0 )
4578 for ( i
= (pm_vars
->theNumberOfPowerStates
)-1; i
>= 0; i
-- )
4580 if ( (domainState
& pm_vars
->thePowerStates
[i
].inputPowerRequirement
) == pm_vars
->thePowerStates
[i
].inputPowerRequirement
)
4589 //*********************************************************************************
4590 // initialPowerStateForDomainState
4592 // Finds the highest power state in the array whose input power
4593 // requirement is equal to the input parameter. Where a more intelligent
4594 // decision is possible, override this in the subclassed driver.
4595 //*********************************************************************************
4597 unsigned long IOService::initialPowerStateForDomainState ( IOPMPowerFlags domainState
)
4601 if (pm_vars
->theNumberOfPowerStates
== 0 )
4605 for ( i
= (pm_vars
->theNumberOfPowerStates
)-1; i
>= 0; i
-- )
4607 if ( (domainState
& pm_vars
->thePowerStates
[i
].inputPowerRequirement
) == pm_vars
->thePowerStates
[i
].inputPowerRequirement
)
4616 //*********************************************************************************
4617 // powerStateForDomainState
4619 // Finds the highest power state in the array whose input power
4620 // requirement is equal to the input parameter. Where a more intelligent
4621 // decision is possible, override this in the subclassed driver.
4622 //*********************************************************************************
4624 unsigned long IOService::powerStateForDomainState ( IOPMPowerFlags domainState
)
4628 if (pm_vars
->theNumberOfPowerStates
== 0 )
4632 for ( i
= (pm_vars
->theNumberOfPowerStates
)-1; i
>= 0; i
-- )
4634 if ( (domainState
& pm_vars
->thePowerStates
[i
].inputPowerRequirement
) == pm_vars
->thePowerStates
[i
].inputPowerRequirement
)
4643 //*********************************************************************************
4646 // Does nothing here. This should be implemented in a subclass driver.
4647 //*********************************************************************************
4649 bool IOService::didYouWakeSystem ( void )
4655 //*********************************************************************************
4656 // powerStateWillChangeTo
4658 // Does nothing here. This should be implemented in a subclass driver.
4659 //*********************************************************************************
4661 IOReturn
IOService::powerStateWillChangeTo ( IOPMPowerFlags
, unsigned long, IOService
*)
4667 //*********************************************************************************
4668 // powerStateDidChangeTo
4670 // Does nothing here. This should be implemented in a subclass driver.
4671 //*********************************************************************************
4673 IOReturn
IOService::powerStateDidChangeTo ( IOPMPowerFlags
, unsigned long, IOService
*)
4679 //*********************************************************************************
4682 // Does nothing here. This should be implemented in a subclass policy-maker.
4683 //*********************************************************************************
4685 void IOService::powerChangeDone ( unsigned long )
4690 //*********************************************************************************
4693 // Does nothing here. This should be implemented in a subclass driver.
4694 //*********************************************************************************
4696 IOReturn
IOService::newTemperature ( long currentTemp
, IOService
* whichZone
)
4704 #define super OSObject
4706 OSDefineMetaClassAndStructors(IOPMprot
, OSObject
)
4707 //*********************************************************************************
4710 // Serialize protected instance variables for debug output.
4711 //*********************************************************************************
4712 bool IOPMprot::serialize(OSSerialize
*s
) const
4714 OSString
* theOSString
;
4720 buffer
= ptr
= IONew(char, 2000);
4724 ptr
+= sprintf(ptr
,"{ theNumberOfPowerStates = %d, ",(unsigned int)theNumberOfPowerStates
);
4726 if ( theNumberOfPowerStates
!= 0 ) {
4727 ptr
+= sprintf(ptr
,"version %d, ",(unsigned int)thePowerStates
[0].version
);
4730 if ( theNumberOfPowerStates
!= 0 ) {
4731 for ( i
= 0; i
< (int)theNumberOfPowerStates
; i
++ ) {
4732 ptr
+= sprintf(ptr
,"power state %d = { ",i
);
4733 ptr
+= sprintf(ptr
,"capabilityFlags %08x, ",(unsigned int)thePowerStates
[i
].capabilityFlags
);
4734 ptr
+= sprintf(ptr
,"outputPowerCharacter %08x, ",(unsigned int)thePowerStates
[i
].outputPowerCharacter
);
4735 ptr
+= sprintf(ptr
,"inputPowerRequirement %08x, ",(unsigned int)thePowerStates
[i
].inputPowerRequirement
);
4736 ptr
+= sprintf(ptr
,"staticPower %d, ",(unsigned int)thePowerStates
[i
].staticPower
);
4737 ptr
+= sprintf(ptr
,"unbudgetedPower %d, ",(unsigned int)thePowerStates
[i
].unbudgetedPower
);
4738 ptr
+= sprintf(ptr
,"powerToAttain %d, ",(unsigned int)thePowerStates
[i
].powerToAttain
);
4739 ptr
+= sprintf(ptr
,"timeToAttain %d, ",(unsigned int)thePowerStates
[i
].timeToAttain
);
4740 ptr
+= sprintf(ptr
,"settleUpTime %d, ",(unsigned int)thePowerStates
[i
].settleUpTime
);
4741 ptr
+= sprintf(ptr
,"timeToLower %d, ",(unsigned int)thePowerStates
[i
].timeToLower
);
4742 ptr
+= sprintf(ptr
,"settleDownTime %d, ",(unsigned int)thePowerStates
[i
].settleDownTime
);
4743 ptr
+= sprintf(ptr
,"powerDomainBudget %d }, ",(unsigned int)thePowerStates
[i
].powerDomainBudget
);
4747 ptr
+= sprintf(ptr
,"aggressiveness = %d, ",(unsigned int)aggressiveness
);
4748 ptr
+= sprintf(ptr
,"myCurrentState = %d, ",(unsigned int)myCurrentState
);
4749 ptr
+= sprintf(ptr
,"parentsCurrentPowerFlags = %08x, ",(unsigned int)parentsCurrentPowerFlags
);
4750 ptr
+= sprintf(ptr
,"maxCapability = %d }",(unsigned int)maxCapability
);
4752 theOSString
= OSString::withCString(buffer
);
4753 rtn_code
= theOSString
->serialize(s
);
4754 theOSString
->release();
4755 IODelete(buffer
, char, 2000);
4762 #define super OSObject
4764 OSDefineMetaClassAndStructors(IOPMpriv
, OSObject
)
4765 //*********************************************************************************
4768 // Serialize private instance variables for debug output.
4769 //*********************************************************************************
4770 bool IOPMpriv::serialize(OSSerialize
*s
) const
4772 OSString
* theOSString
;
4776 IOPMinformee
* nextObject
;
4778 buffer
= ptr
= IONew(char, 2000);
4782 ptr
+= sprintf(ptr
,"{ this object = %08x",(unsigned int)owner
);
4783 if ( we_are_root
) {
4784 ptr
+= sprintf(ptr
," (root)");
4786 ptr
+= sprintf(ptr
,", ");
4788 nextObject
= interestedDrivers
->firstInList(); // display interested drivers
4789 while ( nextObject
!= NULL
) {
4790 ptr
+= sprintf(ptr
,"interested driver = %08x, ",(unsigned int)nextObject
->whatObject
);
4791 nextObject
= interestedDrivers
->nextInList(nextObject
);
4794 if ( machine_state
!= kIOPM_Finished
) {
4795 ptr
+= sprintf(ptr
,"machine_state = %d, ",(unsigned int)machine_state
);
4796 ptr
+= sprintf(ptr
,"driver_timer = %d, ",(unsigned int)driver_timer
);
4797 ptr
+= sprintf(ptr
,"settle_time = %d, ",(unsigned int)settle_time
);
4798 ptr
+= sprintf(ptr
,"head_note_flags = %08x, ",(unsigned int)head_note_flags
);
4799 ptr
+= sprintf(ptr
,"head_note_state = %d, ",(unsigned int)head_note_state
);
4800 ptr
+= sprintf(ptr
,"head_note_outputFlags = %08x, ",(unsigned int)head_note_outputFlags
);
4801 ptr
+= sprintf(ptr
,"head_note_domainState = %08x, ",(unsigned int)head_note_domainState
);
4802 ptr
+= sprintf(ptr
,"head_note_capabilityFlags = %08x, ",(unsigned int)head_note_capabilityFlags
);
4803 ptr
+= sprintf(ptr
,"head_note_pendingAcks = %d, ",(unsigned int)head_note_pendingAcks
);
4806 if ( device_overrides
) {
4807 ptr
+= sprintf(ptr
,"device overrides, ");
4809 ptr
+= sprintf(ptr
,"driverDesire = %d, ",(unsigned int)driverDesire
);
4810 ptr
+= sprintf(ptr
,"deviceDesire = %d, ",(unsigned int)deviceDesire
);
4811 ptr
+= sprintf(ptr
,"ourDesiredPowerState = %d, ",(unsigned int)ourDesiredPowerState
);
4812 ptr
+= sprintf(ptr
,"previousRequest = %d }",(unsigned int)previousRequest
);
4814 theOSString
= OSString::withCString(buffer
);
4815 rtn_code
= theOSString
->serialize(s
);
4816 theOSString
->release();
4817 IODelete(buffer
, char, 2000);