]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOServicePM.cpp
a915f1b4c6c4fa2acc1d32da5988abf50e3e8900
[apple/xnu.git] / iokit / Kernel / IOServicePM.cpp
1 /*
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
29 */
30
31 #include <IOKit/assert.h>
32
33 #include <IOKit/IOCommandGate.h>
34 #include <IOKit/IOKitDebug.h>
35 #include <IOKit/IOLib.h>
36 #include <IOKit/IOMessage.h>
37 #include <IOKit/IOPlatformExpert.h>
38 #include <IOKit/IOService.h>
39 #include <IOKit/IOTimerEventSource.h>
40 #include <IOKit/IOWorkLoop.h>
41
42 #include <IOKit/pwr_mgt/IOPMchangeNoteList.h>
43 #include <IOKit/pwr_mgt/IOPMinformee.h>
44 #include <IOKit/pwr_mgt/IOPMinformeeList.h>
45 #include <IOKit/pwr_mgt/IOPMlog.h>
46 #include <IOKit/pwr_mgt/IOPowerConnection.h>
47 #include <IOKit/pwr_mgt/RootDomain.h>
48
49 #include "IOPMWorkArbiter.h"
50
51 // Required for notification instrumentation
52 #include "IOServicePrivate.h"
53
54 #define super IORegistryEntry
55
56 #define OUR_PMLog(t, a, b) \
57 do { pm_vars->thePlatform->PMLog(pm_vars->ourName, t, a, b); } while(0)
58
59 static void ack_timer_expired(thread_call_param_t);
60 static void settle_timer_expired(thread_call_param_t);
61 static void PM_idle_timer_expired(OSObject *, IOTimerEventSource *);
62 void tellAppWithResponse ( OSObject * object, void * context);
63 void tellClientWithResponse ( OSObject * object, void * context);
64 void tellClient ( OSObject * object, void * context);
65 IOReturn serializedAllowPowerChange ( OSObject *, void *, void *, void *, void *);
66 IOReturn serializedCancelPowerChange ( OSObject *, void *, void *, void *, void *);
67
68 extern const IORegistryPlane * gIOPowerPlane;
69
70
71 // and there's 1000 nanoseconds in a microsecond:
72 #define ns_per_us 1000
73
74
75 // The current change note is processed by a state machine.
76 // Inputs are acks from interested parties, ack from the controlling driver,
77 // ack timeouts, settle timeout, and powerStateDidChange from the parent.
78 // These are the states:
79 enum {
80 kIOPM_OurChangeTellClientsPowerDown = 1,
81 kIOPM_OurChangeTellPriorityClientsPowerDown,
82 kIOPM_OurChangeNotifyInterestedDriversWillChange,
83 kIOPM_OurChangeSetPowerState,
84 kIOPM_OurChangeWaitForPowerSettle,
85 kIOPM_OurChangeNotifyInterestedDriversDidChange,
86 kIOPM_OurChangeFinish,
87 kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate,
88 kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed,
89 kIOPM_ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate,
90 kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed,
91 kIOPM_ParentDownSetPowerState_Delayed,
92 kIOPM_ParentDownWaitForPowerSettle_Delayed,
93 kIOPM_ParentDownAcknowledgeChange_Delayed,
94 kIOPM_ParentUpSetPowerState_Delayed,
95 kIOPM_ParentUpSetPowerState_Immediate,
96 kIOPM_ParentUpWaitForSettleTime_Delayed,
97 kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed,
98 kIOPM_ParentUpAcknowledgePowerChange_Delayed,
99 kIOPM_Finished
100 };
101
102 // values of outofbandparameter
103 enum {
104 kNotifyApps,
105 kNotifyPriority
106 };
107
108
109 // used for applyToInterested
110 struct context {
111 OSArray * responseFlags;
112 UInt16 serialNumber;
113 UInt16 counter;
114 UInt32 maxTimeRequested;
115 int msgType;
116 IOService * us;
117 IOLock * flags_lock;
118 unsigned long stateNumber;
119 IOPMPowerFlags stateFlags;
120 };
121
122 // five minutes in microseconds
123 #define FIVE_MINUTES 5*60*1000000
124 #define k30seconds 30*1000000
125
126 /*
127 There are two different kinds of power state changes. One is initiated by a subclassed device object which has either
128 decided to change power state, or its controlling driver has suggested it, or some other driver wants to use the
129 idle device and has asked it to become usable. The second kind of power state change is initiated by the power
130 domain parent. The two are handled slightly differently.
131
132 There is a queue of so-called change notifications, or change notes for short. Usually the queue is empty, and when
133 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
134 at one time, a queue is implemented. Example: the subclass device decides it's idle and initiates a change to a lower
135 power state. This causes interested parties to be notified, but they don't all acknowledge right away. This causes the
136 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
137 wants to raise power back up again. This change can't be started, however, because the previous one isn't complete yet,
138 so the second one waits in the queue. During this time, the parent decides to lower or raise the power state of the entire
139 power domain and notifies the device, and that notification goes into the queue, too, and can't be actioned until the
140 others are.
141
142 This is how a power change initiated by the subclass device is handled:
143 First, all interested parties are notified of the change via their powerStateWillChangeTo method. If they all don't
144 acknowledge via return code, then we have to wait. If they do, or when they finally all acknowledge via our
145 acknowledgePowerChange method, then we can continue. We call the controlling driver, instructing it to change to
146 the new state. Then we wait for power to settle. If there is no settling-time, or after it has passed, we notify
147 interested parties again, this time via their powerStateDidChangeTo methods. When they have all acked, we're done.
148 If we lowered power and don't need the power domain to be in its current power state, we suggest to the parent that
149 it lower the power domain state.
150
151 This is how a change to a lower power domain state initiated by the parent is handled:
152 First, we figure out what power state we will be in when the new domain state is reached. Then all interested parties are
153 notified that we are moving to that new state. When they have acknowledged, we call the controlling driver to assume
154 that state and we wait for power to settle. Then we acknowledge our preparedness to our parent. When all its interested
155 parties have acknowledged, it lowers power and then notifies its interested parties again. When we get this call, we notify
156 our interested parties that the power state has changed, and when they have all acknowledged, we're done.
157
158 This is how a change to a higher power domain state initiated by the parent is handled:
159 We figure out what power state we will be in when the new domain state is reached. If it is different from our current
160 state we acknowledge the parent. When all the parent's interested parties have acknowledged, it raises power in the
161 domain and waits for power to settle. Then it notifies everyone that the new state has been reached. When we get this call,
162 we call the controlling driver, instructing it to assume the new state, and wait for power to settle. Then we notify our interested
163 parties. When they all acknowledge we are done.
164
165 In either of the two cases above, it is possible that we will not be changing state even though the domain is. Examples:
166 A change to a lower domain state may not affect us because we are already in a low enough state, and
167 We will not take advantage of a change to a higher domain state, because we have no need of the higher power.
168 In such a case, there is nothing to do but acknowledge the parent. So when the parent calls our powerDomainWillChange
169 method, and we decide that we will not be changing state, we merely acknowledge the parent, via return code, and wait.
170 When the parent subsequently calls powerStateDidChange, we acknowledge again via return code, and the change is complete.
171
172 Power state changes are processed in a state machine, and since there are four varieties of power state changes, there are
173 four major paths through the state machine:
174
175 The fourth is nearly trivial. In this path, the parent is changing the domain state, but we are not changing the device state.
176 The change starts when the parent calls powerDomainWillChange. All we do is acknowledge the parent.
177 When the parent calls powerStateDidChange, we acknowledge the parent again, and we're done.
178
179 The first is fairly simple. It starts when a power domain child calls requestPowerDomainState and we decide to change power states
180 to accomodate the child, or if our power-controlling driver calls changePowerStateTo, or if some other driver which is using our
181 device calls makeUsable, or if a subclassed object calls changePowerStateToPriv. These are all power changes initiated by us, not
182 forced upon us by the parent. We start by notifying interested parties. If they all acknowledge via return code, we can go
183 on to state "OurChangeSetPowerState". Otherwise, we start the ack timer and wait for the stragglers to acknowlege by calling
184 acknowledgePowerChange. We move on to state "OurChangeSetPowerState" when all the stragglers have acknowledged,
185 or when the ack timer expires on all those which didn't acknowledge. In "OurChangeSetPowerState" we call the power-controlling
186 driver to change the power state of the hardware. If it returns saying it has done so, we go on to state "OurChangeWaitForPowerSettle".
187 Otherwise, we have to wait for it, so we set the ack timer and wait. When it calls acknowledgeSetPowerState, or when the
188 ack timer expires, we go on. In "OurChangeWaitForPowerSettle", we look in the power state array to see if there is any settle time required
189 when changing from our current state to the new state. If not, we go right away to "OurChangeNotifyInterestedDriversDidChange". Otherwise, we
190 set the settle timer and wait. When it expires, we move on. In "OurChangeNotifyInterestedDriversDidChange" state, we notify all our interested parties
191 via their powerStateDidChange methods that we have finished changing power state. If they all acknowledge via return
192 code, we move on to "OurChangeFinish". Otherwise we set the ack timer and wait. When they have all acknowledged, or
193 when the ack timer has expired for those that didn't, we move on to "OurChangeFinish", where we remove the used
194 change note from the head of the queue and start the next one if one exists.
195
196 Parent-initiated changes are more complex in the state machine. First, power going up and power going down are handled
197 differently, so they have different paths throught the state machine. Second, we can acknowledge the parent's notification
198 in two different ways, so each of the parent paths is really two.
199
200 When the parent calls our powerDomainWillChange method, notifying us that it will lower power in the domain, we decide
201 what state that will put our device in. Then we embark on the state machine path "IOPMParentDownSetPowerState_Immediate"
202 and "kIOPM_ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate", in which we notify interested parties of the upcoming change, instruct our driver to make
203 the change, check for settle time, and notify interested parties of the completed change. If we get to the end of this path without
204 stalling due to an interested party which didn't acknowledge via return code, due to the controlling driver not able to change
205 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.
206 If we do stall in any of those states, we return IOPMWillAckLater to the parent and enter the parallel path "kIOPM_ParentDownSetPowerState_Delayed"
207 "kIOPM_ParentDownWaitForPowerSettle_Delayed", and "kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed", where we continue with the same processing, except that at the end we
208 acknowledge the parent explicitly via acknowledgePowerChange, and we're done with the change.
209 Then when the parent calls us at powerStateDidChange we acknowledging via return code, because we have already made
210 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.
211
212 The case of the parent raising power in the domain is handled similarly in that there are parallel paths, one for no-stall
213 that ends in implicit acknowleging the parent, and one that has stalled at least once that ends in explicit acknowledging
214 the parent. This case is different, though in that our device changes state in the second half, after the parent calls
215 powerStateDidChange rather than before, as in the power-lowering case.
216
217 When the parent calls our powerDomainWillChange method, notifying us that it will raise power in the domain, we acknowledge
218 via return code, because there's really nothing we can do until the power is actually raised in the domain.
219 When the parent calls us at powerStateDidChange, we start by notifying our interested parties. If they all acknowledge via return code,
220 we go on to" kIOPM_ParentUpSetPowerState_Immediate" to instruct the driver to raise its power level. After that, we check for any
221 necessary settling time in "IOPMParentUpWaitForSettleTime_Immediate", and we notify all interested parties that power has changed
222 in "IOPMParentUpNotifyInterestedDriversDidChange_Immediate". If none of these operations stall, we acknowledge the parent via return code, release
223 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",
224 "kIOPM_ParentUpWaitForSettleTime_Delayed", "kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed", and "kIOPM_ParentUpAcknowledgePowerChange_Delayed", which ends with
225 our explicit acknowledgement to the parent.
226
227 */
228
229
230 const char priv_key[ ] = "Power Management private data";
231 const char prot_key[ ] = "Power Management protected data";
232
233
234 void IOService::PMinit ( void )
235 {
236 if ( ! initialized ) {
237
238 // make space for our variables
239 pm_vars = new IOPMprot;
240 priv = new IOPMpriv;
241 pm_vars->init();
242 priv->init();
243
244
245 // add pm_vars & priv to the properties
246 setProperty(prot_key, (OSObject *) pm_vars);
247 setProperty(priv_key, (OSObject *) priv);
248
249 // then initialize them
250 priv->owner = this;
251 pm_vars->theNumberOfPowerStates = 0;
252 priv->we_are_root = false;
253 pm_vars->theControllingDriver = NULL;
254 priv->our_lock = IOLockAlloc();
255 priv->flags_lock = IOLockAlloc();
256 priv->queue_lock = IOLockAlloc();
257 pm_vars->childLock = IOLockAlloc();
258 pm_vars->parentLock = IOLockAlloc();
259 priv->interestedDrivers = new IOPMinformeeList;
260 priv->interestedDrivers->initialize();
261 priv->changeList = new IOPMchangeNoteList;
262 priv->changeList->initialize();
263 pm_vars->aggressiveness = 0;
264 for (unsigned int i = 0; i <= kMaxType; i++)
265 {
266 pm_vars->current_aggressiveness_values[i] = 0;
267 pm_vars->current_aggressiveness_valid[i] = false;
268 }
269 pm_vars->myCurrentState = 0;
270 priv->imminentState = 0;
271 priv->ourDesiredPowerState = 0;
272 pm_vars->parentsCurrentPowerFlags = 0;
273 pm_vars->maxCapability = 0;
274 priv->driverDesire = 0;
275 priv->deviceDesire = 0;
276 priv->initial_change = true;
277 priv->need_to_become_usable = false;
278 priv->previousRequest = 0;
279 priv->device_overrides = false;
280 priv->machine_state = kIOPM_Finished;
281 priv->timerEventSrc = NULL;
282 priv->clampTimerEventSrc = NULL;
283 pm_vars->PMworkloop = NULL;
284 priv->activityLock = NULL;
285 pm_vars->ourName = getName();
286 pm_vars->thePlatform = getPlatform();
287 pm_vars->parentsKnowState = false;
288 assert( pm_vars->thePlatform != 0 );
289 priv->clampOn = false;
290 pm_vars->serialNumber = 0;
291 pm_vars->responseFlags = NULL;
292 pm_vars->doNotPowerDown = true;
293 pm_vars->PMcommandGate = NULL;
294 priv->ackTimer = thread_call_allocate(
295 (thread_call_func_t)ack_timer_expired,
296 (thread_call_param_t)this);
297 priv->settleTimer = thread_call_allocate(
298 (thread_call_func_t)settle_timer_expired,
299 (thread_call_param_t)this);
300
301 initialized = true;
302 }
303 }
304
305
306 //*********************************************************************************
307 // PMfree
308 //
309 // Free up the data created in PMinit, if it exists.
310 //*********************************************************************************
311 void IOService::PMfree ( void )
312 {
313 if ( priv ) {
314 if ( priv->clampTimerEventSrc != NULL ) {
315 getPMworkloop()->removeEventSource(priv->clampTimerEventSrc);
316 priv->clampTimerEventSrc->release();
317 priv->clampTimerEventSrc = NULL;
318 }
319 if ( priv->timerEventSrc != NULL ) {
320 pm_vars->PMworkloop->removeEventSource(priv->timerEventSrc);
321 priv->timerEventSrc->release();
322 priv->timerEventSrc = NULL;
323 }
324 if ( priv->settleTimer ) {
325 thread_call_cancel(priv->settleTimer);
326 thread_call_free(priv->settleTimer);
327 priv->settleTimer = NULL;
328 }
329 if ( priv->ackTimer ) {
330 thread_call_cancel(priv->ackTimer);
331 thread_call_free(priv->ackTimer);
332 priv->ackTimer = NULL;
333 }
334 if ( priv->our_lock ) {
335 IOLockFree(priv->our_lock);
336 priv->our_lock = NULL;
337 }
338 if ( priv->flags_lock ) {
339 IOLockFree(priv->flags_lock);
340 priv->flags_lock = NULL;
341 }
342 if ( priv->activityLock ) {
343 IOLockFree(priv->activityLock);
344 priv->activityLock = NULL;
345 }
346 priv->interestedDrivers->release();
347 priv->changeList->release();
348 // remove instance variables
349 priv->release();
350 }
351
352 if ( pm_vars ) {
353 if ( pm_vars->PMcommandGate ) {
354 if(pm_vars->PMworkloop)
355 pm_vars->PMworkloop->removeEventSource(pm_vars->PMcommandGate);
356 pm_vars->PMcommandGate->release();
357 pm_vars->PMcommandGate = NULL;
358 }
359 if ( pm_vars->PMworkloop ) {
360 // The work loop object returned from getPMworkLoop() is
361 // never retained, therefore it should not be released.
362 // pm_vars->PMworkloop->release();
363 pm_vars->PMworkloop = NULL;
364 }
365 if ( pm_vars->responseFlags ) {
366 pm_vars->responseFlags->release();
367 pm_vars->responseFlags = NULL;
368 }
369 // remove instance variables
370 pm_vars->release();
371 }
372 }
373
374
375 //*********************************************************************************
376 // PMstop
377 //
378 // Disconnect the node from its parents and children in the Power Plane.
379 //*********************************************************************************
380 void IOService::PMstop ( void )
381 {
382 OSIterator * iter;
383 OSObject * next;
384 IOPowerConnection * connection;
385 IOService * theChild;
386 IOService * theParent;
387
388 // remove the properties
389 removeProperty(prot_key);
390 removeProperty(priv_key);
391
392 // detach parents
393 iter = getParentIterator(gIOPowerPlane);
394
395 if ( iter )
396 {
397 while ( (next = iter->getNextObject()) )
398 {
399 if ( (connection = OSDynamicCast(IOPowerConnection,next)) )
400 {
401 theParent = (IOService *)connection->copyParentEntry(gIOPowerPlane);
402 if ( theParent )
403 {
404 theParent->removePowerChild(connection);
405 theParent->release();
406 }
407 }
408 }
409 iter->release();
410 }
411
412 // detach IOConnections
413 detachAbove( gIOPowerPlane );
414
415 if ( pm_vars )
416 {
417 // no more power state changes
418 pm_vars->parentsKnowState = false;
419 }
420
421 // detach children
422 iter = getChildIterator(gIOPowerPlane);
423
424 if ( iter )
425 {
426 while ( (next = iter->getNextObject()) )
427 {
428 if ( (connection = OSDynamicCast(IOPowerConnection,next)) )
429 {
430 theChild = ((IOService *)(connection->copyChildEntry(gIOPowerPlane)));
431 if ( theChild )
432 {
433 // detach nub from child
434 connection->detachFromChild(theChild,gIOPowerPlane);
435 theChild->release();
436 }
437 // detach us from nub
438 detachFromChild(connection,gIOPowerPlane);
439 }
440 }
441 iter->release();
442 }
443
444 // Remove all interested drivers from the list, including the power
445 // controlling driver.
446 //
447 // Usually, the controlling driver and the policy-maker functionality
448 // are implemented by the same object, and without the deregistration,
449 // the object will be holding an extra retain on itself, and cannot
450 // be freed.
451
452 if ( priv && priv->interestedDrivers )
453 {
454 IOPMinformee * informee;
455
456 while (( informee = priv->interestedDrivers->firstInList() ))
457 deRegisterInterestedDriver( informee->whatObject );
458 }
459 }
460
461
462 //*********************************************************************************
463 // joinPMtree
464 //
465 // A policy-maker calls its nub here when initializing, to be attached into
466 // the power management hierarchy. The default function is to call the
467 // platform expert, which knows how to do it. This method is overridden
468 // by a nub subclass which may either know how to do it, or may need
469 // to take other action.
470 //
471 // This may be the only "power management" method used in a nub,
472 // meaning it may not be initialized for power management.
473 //*********************************************************************************
474 void IOService::joinPMtree ( IOService * driver )
475 {
476 IOPlatformExpert * thePlatform;
477
478 thePlatform = getPlatform();
479 assert(thePlatform != 0 );
480 thePlatform->PMRegisterDevice(this,driver);
481 }
482
483
484 //*********************************************************************************
485 // youAreRoot
486 //
487 // Power Managment is informing us that we are the root power domain.
488 // The only difference between us and any other power domain is that
489 // we have no parent and therefore never call it.
490 //*********************************************************************************
491 IOReturn IOService::youAreRoot ( void )
492 {
493 priv-> we_are_root = true;
494 pm_vars->parentsKnowState = true;
495 attachToParent( getRegistryRoot(),gIOPowerPlane );
496
497 return IOPMNoErr;
498 }
499
500
501 //*********************************************************************************
502 // setPowerParent
503 //
504 // Power Management is informing us who our parent is.
505 // If we have a controlling driver, find out, given our newly-informed
506 // power domain state, what state it would be in, and then tell it
507 // to assume that state.
508 //*********************************************************************************
509 IOReturn IOService::setPowerParent ( IOPowerConnection * theParent, bool stateKnown, IOPMPowerFlags currentState )
510 {
511 OSIterator * iter;
512 OSObject * next;
513 IOPowerConnection * connection;
514 unsigned long tempDesire;
515
516 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogSetParent,stateKnown,currentState);
517
518 IOLockLock(pm_vars->parentLock);
519
520 if ( stateKnown && ((pm_vars->PMworkloop == NULL) || (pm_vars->PMcommandGate == NULL)) )
521 {
522 // we have a path to the root
523 // find out the workloop
524 getPMworkloop();
525 if ( pm_vars->PMworkloop != NULL )
526 {
527 if ( pm_vars->PMcommandGate == NULL )
528 {
529 // and make our command gate
530 pm_vars->PMcommandGate = IOCommandGate::commandGate((OSObject *)this);
531 if ( pm_vars->PMcommandGate != NULL )
532 {
533 pm_vars->PMworkloop->addEventSource(pm_vars->PMcommandGate);
534 }
535 }
536 }
537 }
538
539 IOLockUnlock(pm_vars->parentLock);
540
541 // set our connection data
542 theParent->setParentCurrentPowerFlags(currentState);
543 theParent->setParentKnowsState(stateKnown);
544
545 // combine parent knowledge
546 pm_vars->parentsKnowState = true;
547 pm_vars->parentsCurrentPowerFlags = 0;
548
549 iter = getParentIterator(gIOPowerPlane);
550
551 if ( iter )
552 {
553 while ( (next = iter->getNextObject()) )
554 {
555 if ( (connection = OSDynamicCast(IOPowerConnection,next)) )
556 {
557 pm_vars->parentsKnowState &= connection->parentKnowsState();
558 pm_vars->parentsCurrentPowerFlags |= connection->parentCurrentPowerFlags();
559 }
560 }
561 iter->release();
562 }
563
564 if ( (pm_vars->theControllingDriver != NULL) &&
565 (pm_vars->parentsKnowState) )
566 {
567 pm_vars->maxCapability = pm_vars->theControllingDriver->maxCapabilityForDomainState(pm_vars->parentsCurrentPowerFlags);
568 // initially change into the state we are already in
569 tempDesire = priv->deviceDesire;
570 priv->deviceDesire = pm_vars->theControllingDriver->initialPowerStateForDomainState(pm_vars->parentsCurrentPowerFlags);
571 computeDesiredState();
572 priv->previousRequest = 0xffffffff;
573 changeState();
574 // put this back like before
575 priv->deviceDesire = tempDesire;
576 }
577
578 return IOPMNoErr;
579 }
580
581
582 //*********************************************************************************
583 // addPowerChild
584 //
585 // Power Management is informing us who our children are.
586 //*********************************************************************************
587 IOReturn IOService::addPowerChild ( IOService * theChild )
588 {
589 IOPowerConnection *connection;
590 unsigned int i;
591
592 if ( ! initialized )
593 {
594 // we're not a power-managed IOService
595 return IOPMNotYetInitialized;
596 }
597
598 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogAddChild,0,0);
599
600 // Put ourselves into a usable power state.
601 // We must be in an "on" power state, as our children must be able to access
602 // our hardware after joining the power plane.
603 temporaryMakeUsable();
604
605 // make a nub
606 connection = new IOPowerConnection;
607
608 connection->init();
609 connection->start(this);
610 connection->setAwaitingAck(false);
611
612 // connect it up
613 attachToChild( connection,gIOPowerPlane );
614 connection->attachToChild( theChild,gIOPowerPlane );
615 connection->release();
616
617 // tell it the current state of the power domain
618 if ( (pm_vars->theControllingDriver == NULL) ||
619 ! (inPlane(gIOPowerPlane)) ||
620 ! (pm_vars->parentsKnowState) )
621 {
622 theChild->setPowerParent(connection,false,0);
623 if ( inPlane(gIOPowerPlane) )
624 {
625 for (i = 0; i <= kMaxType; i++) {
626 if ( pm_vars->current_aggressiveness_valid[i] )
627 {
628 theChild->setAggressiveness (i, pm_vars->current_aggressiveness_values[i]);
629 }
630 }
631 }
632 } else {
633 theChild->setPowerParent(connection,true,pm_vars->thePowerStates[pm_vars->myCurrentState].outputPowerCharacter);
634 for (i = 0; i <= kMaxType; i++)
635 {
636 if ( pm_vars->current_aggressiveness_valid[i] )
637 {
638 theChild->setAggressiveness (i, pm_vars->current_aggressiveness_values[i]);
639 }
640 }
641 // catch it up if change is in progress
642 add_child_to_active_change(connection);
643 }
644
645 return IOPMNoErr;
646 }
647
648
649 //******************************************************************************
650 // removePowerChild
651 //
652 //******************************************************************************
653 IOReturn IOService::removePowerChild ( IOPowerConnection * theNub )
654 {
655 IORegistryEntry *theChild;
656
657 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogRemoveChild,0,0);
658
659 theNub->retain();
660
661 // detach nub from child
662 theChild = theNub->copyChildEntry(gIOPowerPlane);
663 if ( theChild )
664 {
665 theNub->detachFromChild(theChild, gIOPowerPlane);
666 theChild->release();
667 }
668 // detach from the nub
669 detachFromChild(theNub,gIOPowerPlane);
670
671 // are we awaiting an ack from this child?
672 if ( theNub->getAwaitingAck() )
673 {
674 // yes, pretend we got one
675 theNub->setAwaitingAck(false);
676 if ( acquire_lock() )
677 {
678 if (priv->head_note_pendingAcks != 0 )
679 {
680 // that's one fewer ack to worry about
681 OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
682 // is that the last?
683 if ( priv->head_note_pendingAcks == 0 )
684 {
685 // yes, stop the timer
686 stop_ack_timer();
687 IOUnlock(priv->our_lock);
688 // and now we can continue our power change
689 all_acked();
690 } else {
691 IOUnlock(priv->our_lock);
692 }
693 } else {
694 IOUnlock(priv->our_lock);
695 }
696 }
697 }
698
699 theNub->release();
700
701 // if not fully initialized
702 if ( (pm_vars->theControllingDriver == NULL) ||
703 !(inPlane(gIOPowerPlane)) ||
704 !(pm_vars->parentsKnowState) )
705 {
706 // we can do no more
707 return IOPMNoErr;
708 }
709
710 // Perhaps the departing child was holding up idle or system sleep - we
711 // need to re-evaluate our childrens' requests.
712 // Clear and re-calculate our kIOPMChildClamp and kIOPMChildClamp2 bits.
713 rebuildChildClampBits();
714
715 // Change state if we can now tolerate lower power
716 computeDesiredState();
717 changeState();
718
719 return IOPMNoErr;
720 }
721
722
723 //*********************************************************************************
724 // registerPowerDriver
725 //
726 // A driver has called us volunteering to control power to our device.
727 // If the power state array it provides is richer than the one we already
728 // know about (supplied by an earlier volunteer), then accept the offer.
729 // Notify all interested parties of our power state, which we now know.
730 //*********************************************************************************
731
732 IOReturn IOService::registerPowerDriver ( IOService * controllingDriver, IOPMPowerState* powerStates, unsigned long numberOfStates )
733 {
734 unsigned long i;
735 unsigned long tempDesire;
736
737 if ( (numberOfStates > pm_vars->theNumberOfPowerStates)
738 && (numberOfStates > 1) )
739 {
740 if ( priv->changeList->currentChange() == -1 )
741 {
742 if ( controllingDriver != NULL )
743 {
744 if ( numberOfStates <= IOPMMaxPowerStates )
745 {
746 switch ( powerStates[0].version )
747 {
748 case 1:
749 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogControllingDriver,
750 (unsigned long)numberOfStates, (unsigned long)powerStates[0].version);
751 for ( i = 0; i < numberOfStates; i++ )
752 {
753 pm_vars->thePowerStates[i] = powerStates[i];
754 }
755 break;
756 case 2:
757 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogControllingDriver,
758 (unsigned long) numberOfStates,(unsigned long) powerStates[0].version);
759 for ( i = 0; i < numberOfStates; i++ )
760 {
761 pm_vars->thePowerStates[i].version = powerStates[i].version;
762 pm_vars->thePowerStates[i].capabilityFlags = powerStates[i].capabilityFlags;
763 pm_vars->thePowerStates[i].outputPowerCharacter = powerStates[i].outputPowerCharacter;
764 pm_vars->thePowerStates[i].inputPowerRequirement = powerStates[i].inputPowerRequirement;
765 pm_vars->thePowerStates[i].staticPower = powerStates[i].staticPower;
766 pm_vars->thePowerStates[i].unbudgetedPower = powerStates[i].unbudgetedPower;
767 pm_vars->thePowerStates[i].powerToAttain = powerStates[i].powerToAttain;
768 pm_vars->thePowerStates[i].timeToAttain = powerStates[i].timeToAttain;
769 pm_vars->thePowerStates[i].settleUpTime = powerStates[i].settleUpTime;
770 pm_vars->thePowerStates[i].timeToLower = powerStates[i].timeToLower;
771 pm_vars->thePowerStates[i].settleDownTime = powerStates[i].settleDownTime;
772 pm_vars->thePowerStates[i].powerDomainBudget = powerStates[i].powerDomainBudget;
773 }
774 break;
775 default:
776 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogControllingDriverErr1,
777 (unsigned long)powerStates[0].version,0);
778 return IOPMNoErr;
779 }
780
781 // make a mask of all the character bits we know about
782 pm_vars->myCharacterFlags = 0;
783 for ( i = 0; i < numberOfStates; i++ ) {
784 pm_vars->myCharacterFlags |= pm_vars->thePowerStates[i].outputPowerCharacter;
785 }
786
787 pm_vars->theNumberOfPowerStates = numberOfStates;
788 pm_vars->theControllingDriver = controllingDriver;
789 if ( priv->interestedDrivers->findItem(controllingDriver) == NULL )
790 {
791 // register it as interested, unless already done
792 registerInterestedDriver (controllingDriver );
793 }
794 if ( priv->need_to_become_usable ) {
795 priv->need_to_become_usable = false;
796 priv->deviceDesire = pm_vars->theNumberOfPowerStates - 1;
797 }
798
799 if ( inPlane(gIOPowerPlane) &&
800 (pm_vars->parentsKnowState) ) {
801 pm_vars->maxCapability = pm_vars->theControllingDriver->maxCapabilityForDomainState(pm_vars->parentsCurrentPowerFlags);
802 // initially change into the state we are already in
803 tempDesire = priv->deviceDesire;
804 priv->deviceDesire = pm_vars->theControllingDriver->initialPowerStateForDomainState(pm_vars->parentsCurrentPowerFlags);
805 computeDesiredState();
806 changeState();
807 // put this back like before
808 priv->deviceDesire = tempDesire;
809 }
810 } else {
811 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogControllingDriverErr2,(unsigned long)numberOfStates,0);
812 }
813 } else {
814 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogControllingDriverErr4,0,0);
815 }
816 }
817 }
818 else {
819 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogControllingDriverErr5,(unsigned long)numberOfStates,0);
820 }
821 return IOPMNoErr;
822 }
823
824 //*********************************************************************************
825 // registerInterestedDriver
826 //
827 // Add the caller to our list of interested drivers and return our current
828 // power state. If we don't have a power-controlling driver yet, we will
829 // call this interested driver again later when we do get a driver and find
830 // out what the current power state of the device is.
831 //*********************************************************************************
832
833 IOPMPowerFlags IOService::registerInterestedDriver ( IOService * theDriver )
834 {
835 IOPMinformee *newInformee;
836 IOPMPowerFlags futureCapability;
837
838 if (theDriver == NULL ) {
839 return 0;
840 }
841
842 // make new driver node
843 newInformee = new IOPMinformee;
844 newInformee->initialize(theDriver);
845 // add it to list of drivers
846 priv->interestedDrivers->addToList(newInformee);
847
848 if ( (pm_vars->theControllingDriver == NULL) ||
849 !(inPlane(gIOPowerPlane)) ||
850 !(pm_vars->parentsKnowState) )
851 {
852 // can't tell it a state yet
853 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogInterestedDriver,IOPMNotPowerManaged,0);
854 return IOPMNotPowerManaged;
855 }
856
857 // can we notify new driver of a change in progress?
858 switch (priv->machine_state) {
859 case kIOPM_OurChangeSetPowerState:
860 case kIOPM_OurChangeFinish:
861 case kIOPM_ParentDownSetPowerState_Delayed:
862 case kIOPM_ParentDownAcknowledgeChange_Delayed:
863 case kIOPM_ParentUpSetPowerState_Delayed:
864 case kIOPM_ParentUpAcknowledgePowerChange_Delayed:
865 // yes, remember what we tell it
866 futureCapability = priv->head_note_capabilityFlags;
867 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogInterestedDriver,(unsigned long)futureCapability,1);
868 // notify it
869 add_driver_to_active_change(newInformee);
870 // and return the same thing
871 return futureCapability;
872 }
873
874 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogInterestedDriver,
875 (unsigned long) pm_vars->thePowerStates[pm_vars->myCurrentState].capabilityFlags,2);
876
877 // no, return current capability
878 return pm_vars->thePowerStates[pm_vars->myCurrentState].capabilityFlags;
879 }
880
881
882 //*********************************************************************************
883 // deRegisterInterestedDriver
884 //
885 //*********************************************************************************
886 IOReturn IOService::deRegisterInterestedDriver ( IOService * theDriver )
887 {
888 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogRemoveDriver,0,0);
889
890 // remove the departing driver
891 priv->interestedDrivers->removeFromList(theDriver);
892
893 return IOPMNoErr;
894 }
895
896
897 //*********************************************************************************
898 // acknowledgePowerChange
899 //
900 // After we notified one of the interested drivers or a power-domain child
901 // of an impending change in power, it has called to say it is now
902 // prepared for the change. If this object is the last to
903 // acknowledge this change, we take whatever action we have been waiting
904 // for.
905 // That may include acknowledging to our parent. In this case, we do it
906 // last of all to insure that this doesn't cause the parent to call us some-
907 // where else and alter data we are relying on here (like the very existance
908 // of a "current change note".)
909 //*********************************************************************************
910
911 IOReturn IOService::acknowledgePowerChange ( IOService * whichObject )
912 {
913 IOPMinformee *ackingObject;
914 unsigned long childPower = kIOPMUnknown;
915 IOService *theChild;
916
917 // one of our interested drivers?
918 ackingObject = priv->interestedDrivers->findItem(whichObject);
919 if ( ackingObject == NULL )
920 {
921 if ( ! isChild(whichObject,gIOPowerPlane) )
922 {
923 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogAcknowledgeErr1,0,0);
924 //kprintf("errant driver: %s\n",whichObject->getName());
925 // no, just return
926 return IOPMNoErr;
927 } else {
928 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogChildAcknowledge,priv->head_note_pendingAcks,0);
929 }
930 } else {
931 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogDriverAcknowledge,priv->head_note_pendingAcks,0);
932 }
933
934 if (! acquire_lock() )
935 {
936 return IOPMNoErr;
937 }
938
939 if (priv->head_note_pendingAcks != 0 )
940 {
941 // yes, make sure we're expecting acks
942 if ( ackingObject != NULL )
943 {
944 // it's an interested driver
945 // make sure we're expecting this ack
946 if ( ackingObject->timer != 0 )
947 {
948 // mark it acked
949 ackingObject->timer = 0;
950 // that's one fewer to worry about
951 OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
952 // is that the last?
953 if ( priv->head_note_pendingAcks == 0 )
954 {
955 // yes, stop the timer
956 stop_ack_timer();
957 IOUnlock(priv->our_lock);
958 // and now we can continue
959 all_acked();
960 return IOPMNoErr;
961 }
962 } else {
963 // this driver has already acked
964 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogAcknowledgeErr2,0,0);
965 //kprintf("errant driver: %s\n",whichObject->getName());
966 }
967 } else {
968 // it's a child
969 // make sure we're expecting this ack
970 if ( ((IOPowerConnection *)whichObject)->getAwaitingAck() )
971 {
972 // that's one fewer to worry about
973 OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
974 ((IOPowerConnection *)whichObject)->setAwaitingAck(false);
975 theChild = (IOService *)whichObject->copyChildEntry(gIOPowerPlane);
976 if ( theChild )
977 {
978 childPower = theChild->currentPowerConsumption();
979 theChild->release();
980 }
981 if ( childPower == kIOPMUnknown )
982 {
983 pm_vars->thePowerStates[priv->head_note_state].staticPower = kIOPMUnknown;
984 } else {
985 if ( pm_vars->thePowerStates[priv->head_note_state].staticPower != kIOPMUnknown )
986 {
987 pm_vars->thePowerStates[priv->head_note_state].staticPower += childPower;
988 }
989 }
990 // is that the last?
991 if ( priv->head_note_pendingAcks == 0 ) {
992 // yes, stop the timer
993 stop_ack_timer();
994 IOUnlock(priv->our_lock);
995 // and now we can continue
996 all_acked();
997 return IOPMNoErr;
998 }
999 }
1000 }
1001 } else {
1002 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogAcknowledgeErr3,0,0); // not expecting anybody to ack
1003 //kprintf("errant driver: %s\n",whichObject->getName());
1004 }
1005 IOUnlock(priv->our_lock);
1006 return IOPMNoErr;
1007 }
1008
1009 //*********************************************************************************
1010 // acknowledgeSetPowerState
1011 //
1012 // After we instructed our controlling driver to change power states,
1013 // it has called to say it has finished doing so.
1014 // We continue to process the power state change.
1015 //*********************************************************************************
1016
1017 IOReturn IOService::acknowledgeSetPowerState ( void )
1018 {
1019 if (!acquire_lock())
1020 return IOPMNoErr;
1021
1022 IOReturn timer = priv->driver_timer;
1023 if ( timer == -1 ) {
1024 // driver is acking instead of using return code
1025 OUR_PMLog(kPMLogDriverAcknowledgeSet, (UInt32) this, timer);
1026 priv->driver_timer = 0;
1027 }
1028 else if ( timer > 0 ) { // are we expecting this?
1029 // yes, stop the timer
1030 stop_ack_timer();
1031 priv->driver_timer = 0;
1032 OUR_PMLog(kPMLogDriverAcknowledgeSet, (UInt32) this, timer);
1033 IOUnlock(priv->our_lock);
1034 driver_acked();
1035 return IOPMNoErr;
1036 } else {
1037 // not expecting this
1038 OUR_PMLog(kPMLogAcknowledgeErr4, (UInt32) this, 0);
1039 }
1040
1041 IOUnlock(priv->our_lock);
1042 return IOPMNoErr;
1043 }
1044
1045
1046 //*********************************************************************************
1047 // driver_acked
1048 //
1049 // Either the controlling driver has called acknowledgeSetPowerState
1050 // or the acknowledgement timer has expired while waiting for that.
1051 // We carry on processing the current change note.
1052 //*********************************************************************************
1053
1054 void IOService::driver_acked ( void )
1055 {
1056 getPMRootDomain()->getPMArbiter()->driverAckedOccurred(this);
1057 return;
1058 }
1059
1060
1061 void IOService::driver_acked_threaded ( void )
1062 {
1063
1064 switch (priv->machine_state) {
1065 case kIOPM_OurChangeWaitForPowerSettle:
1066 OurChangeWaitForPowerSettle();
1067 break;
1068 case kIOPM_ParentDownWaitForPowerSettle_Delayed:
1069 ParentDownWaitForPowerSettle_Delayed();
1070 break;
1071 case kIOPM_ParentUpWaitForSettleTime_Delayed:
1072 ParentUpWaitForSettleTime_Delayed();
1073 break;
1074 }
1075 }
1076
1077
1078 //*********************************************************************************
1079 // powerDomainWillChangeTo
1080 //
1081 // Called by the power-hierarchy parent notifying of a new power state
1082 // in the power domain.
1083 // We enqueue a parent power-change to our queue of power changes.
1084 // This may or may not cause us to change power, depending on what
1085 // kind of change is occuring in the domain.
1086 //*********************************************************************************
1087
1088 IOReturn IOService::powerDomainWillChangeTo ( IOPMPowerFlags newPowerStateFlags, IOPowerConnection * whichParent )
1089 {
1090 OSIterator *iter;
1091 OSObject *next;
1092 IOPowerConnection *connection;
1093 unsigned long newStateNumber;
1094 IOPMPowerFlags combinedPowerFlags;
1095
1096 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogWillChange,(unsigned long)newPowerStateFlags,0);
1097
1098 if ( ! inPlane(gIOPowerPlane) )
1099 {
1100 // somebody goofed
1101 return IOPMAckImplied;
1102 }
1103
1104 IOLockLock(pm_vars->parentLock);
1105
1106 if ( (pm_vars->PMworkloop == NULL) || (pm_vars->PMcommandGate == NULL) )
1107 {
1108 // we have a path to the root
1109 getPMworkloop();
1110 // so find out the workloop
1111 if ( pm_vars->PMworkloop != NULL )
1112 {
1113 // and make our command gate
1114 if ( pm_vars->PMcommandGate == NULL )
1115 {
1116 pm_vars->PMcommandGate = IOCommandGate::commandGate((OSObject *)this);
1117 if ( pm_vars->PMcommandGate != NULL )
1118 {
1119 pm_vars->PMworkloop->addEventSource(pm_vars->PMcommandGate);
1120 }
1121 }
1122 }
1123 }
1124
1125 IOLockUnlock(pm_vars->parentLock);
1126
1127 // combine parents' power states
1128 // to determine our maximum state within the new power domain
1129 combinedPowerFlags = 0;
1130
1131 iter = getParentIterator(gIOPowerPlane);
1132
1133 if ( iter )
1134 {
1135 while ( (next = iter->getNextObject()) )
1136 {
1137 if ( (connection = OSDynamicCast(IOPowerConnection,next)) )
1138 {
1139 if ( connection == whichParent ){
1140 combinedPowerFlags |= newPowerStateFlags;
1141 } else {
1142 combinedPowerFlags |= connection->parentCurrentPowerFlags();
1143 }
1144 }
1145 }
1146 iter->release();
1147 }
1148
1149 if ( pm_vars->theControllingDriver == NULL )
1150 {
1151 // we can't take any more action
1152 return IOPMAckImplied;
1153 }
1154 newStateNumber = pm_vars->theControllingDriver->maxCapabilityForDomainState(combinedPowerFlags);
1155 // make the change
1156 return enqueuePowerChange(IOPMParentInitiated | IOPMDomainWillChange,
1157 newStateNumber,combinedPowerFlags,whichParent,newPowerStateFlags);
1158 }
1159
1160
1161 //*********************************************************************************
1162 // powerDomainDidChangeTo
1163 //
1164 // Called by the power-hierarchy parent after the power state of the power domain
1165 // has settled at a new level.
1166 // We enqueue a parent power-change to our queue of power changes.
1167 // This may or may not cause us to change power, depending on what
1168 // kind of change is occuring in the domain.
1169 //*********************************************************************************
1170
1171 IOReturn IOService::powerDomainDidChangeTo ( IOPMPowerFlags newPowerStateFlags, IOPowerConnection * whichParent )
1172 {
1173 unsigned long newStateNumber;
1174
1175 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogDidChange,newPowerStateFlags,0);
1176
1177 setParentInfo(newPowerStateFlags,whichParent);
1178
1179 if ( pm_vars->theControllingDriver == NULL ) {
1180 return IOPMAckImplied;
1181 }
1182
1183 newStateNumber = pm_vars->theControllingDriver->maxCapabilityForDomainState(pm_vars->parentsCurrentPowerFlags);
1184 // tell interested parties about it
1185 return enqueuePowerChange(IOPMParentInitiated | IOPMDomainDidChange,
1186 newStateNumber,pm_vars->parentsCurrentPowerFlags,whichParent,0);
1187 }
1188
1189
1190 //*********************************************************************************
1191 // setParentInfo
1192 //
1193 // Set our connection data for one specific parent, and then combine all the parent
1194 // data together.
1195 //*********************************************************************************
1196
1197 void IOService::setParentInfo ( IOPMPowerFlags newPowerStateFlags, IOPowerConnection * whichParent )
1198 {
1199 OSIterator *iter;
1200 OSObject *next;
1201 IOPowerConnection *connection;
1202
1203 // set our connection data
1204 whichParent->setParentCurrentPowerFlags(newPowerStateFlags);
1205 whichParent->setParentKnowsState(true);
1206
1207 IOLockLock(pm_vars->parentLock);
1208
1209 // recompute our parent info
1210 pm_vars->parentsCurrentPowerFlags = 0;
1211 pm_vars->parentsKnowState = true;
1212
1213 iter = getParentIterator(gIOPowerPlane);
1214
1215 if ( iter )
1216 {
1217 while ( (next = iter->getNextObject()) )
1218 {
1219 if ( (connection = OSDynamicCast(IOPowerConnection,next)) )
1220 {
1221 pm_vars->parentsKnowState &= connection->parentKnowsState();
1222 pm_vars->parentsCurrentPowerFlags |= connection->parentCurrentPowerFlags();
1223 }
1224 }
1225 iter->release();
1226 }
1227 IOLockUnlock(pm_vars->parentLock);
1228 }
1229
1230 //*********************************************************************************
1231 // rebuildChildClampBits
1232 //
1233 // The ChildClamp bits (kIOPMChildClamp & kIOPMChildClamp2) in our capabilityFlags
1234 // indicate that one of our children (or grandchildren or great-grandchildren or ...)
1235 // doesn't support idle or system sleep in its current state. Since we don't track the
1236 // origin of each bit, every time any child changes state we have to clear these bits
1237 // and rebuild them.
1238 //*********************************************************************************
1239
1240 void IOService::rebuildChildClampBits(void)
1241 {
1242 unsigned long i;
1243 OSIterator *iter;
1244 OSObject *next;
1245 IOPowerConnection *connection;
1246
1247
1248 // A child's desires has changed. We need to rebuild the child-clamp bits in our
1249 // power state array. Start by clearing the bits in each power state.
1250
1251 for ( i = 0; i < pm_vars->theNumberOfPowerStates; i++ )
1252 {
1253 pm_vars->thePowerStates[i].capabilityFlags &= ~(kIOPMChildClamp | kIOPMChildClamp2);
1254 }
1255
1256 // Now loop through the children. When we encounter the calling child, save
1257 // the computed state as this child's desire. And while we're at it, set the ChildClamp bits
1258 // in any of our states that some child has requested with clamp on.
1259
1260 iter = getChildIterator(gIOPowerPlane);
1261
1262 if ( iter )
1263 {
1264 while ( (next = iter->getNextObject()) )
1265 {
1266 if ( (connection = OSDynamicCast(IOPowerConnection,next)) )
1267 {
1268 if ( connection->getPreventIdleSleepFlag() )
1269 pm_vars->thePowerStates[connection->getDesiredDomainState()].capabilityFlags |= kIOPMChildClamp;
1270 if ( connection->getPreventSystemSleepFlag() )
1271 pm_vars->thePowerStates[connection->getDesiredDomainState()].capabilityFlags |= kIOPMChildClamp2;
1272 }
1273 }
1274 iter->release();
1275 }
1276
1277 }
1278
1279
1280 //*********************************************************************************
1281 // requestPowerDomainState
1282 //
1283 // The kIOPMPreventIdleSleep and/or kIOPMPreventIdleSleep bits may be be set in the parameter.
1284 // It is not considered part of the state specification.
1285 //*********************************************************************************
1286 IOReturn IOService::requestPowerDomainState ( IOPMPowerFlags desiredState, IOPowerConnection * whichChild, unsigned long specification )
1287 {
1288 unsigned long i;
1289 unsigned long computedState;
1290 unsigned long theDesiredState = desiredState & ~(kIOPMPreventIdleSleep | kIOPMPreventSystemSleep);
1291 OSIterator *iter;
1292 OSObject *next;
1293 IOPowerConnection *connection;
1294
1295 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogRequestDomain,
1296 (unsigned long)desiredState,(unsigned long)specification);
1297
1298 if ( pm_vars->theControllingDriver == NULL)
1299 {
1300 return IOPMNotYetInitialized;
1301 }
1302
1303 switch (specification) {
1304 case IOPMLowestState:
1305 i = 0;
1306 while ( i < pm_vars->theNumberOfPowerStates )
1307 {
1308 if ( ( pm_vars->thePowerStates[i].outputPowerCharacter & theDesiredState) == (theDesiredState & pm_vars->myCharacterFlags) )
1309 {
1310 break;
1311 }
1312 i++;
1313 }
1314 if ( i >= pm_vars->theNumberOfPowerStates )
1315 {
1316 return IOPMNoSuchState;
1317 }
1318 break;
1319
1320 case IOPMNextLowerState:
1321 i = pm_vars->myCurrentState - 1;
1322 while ( (int) i >= 0 )
1323 {
1324 if ( ( pm_vars->thePowerStates[i].outputPowerCharacter & theDesiredState) == (theDesiredState & pm_vars->myCharacterFlags) )
1325 {
1326 break;
1327 }
1328 i--;
1329 }
1330 if ( (int) i < 0 )
1331 {
1332 return IOPMNoSuchState;
1333 }
1334 break;
1335
1336 case IOPMHighestState:
1337 i = pm_vars->theNumberOfPowerStates;
1338 while ( (int) i >= 0 )
1339 {
1340 i--;
1341 if ( ( pm_vars->thePowerStates[i].outputPowerCharacter & theDesiredState) == (theDesiredState & pm_vars->myCharacterFlags) )
1342 {
1343 break;
1344 }
1345 }
1346 if ( (int) i < 0 )
1347 {
1348 return IOPMNoSuchState;
1349 }
1350 break;
1351
1352 case IOPMNextHigherState:
1353 i = pm_vars->myCurrentState + 1;
1354 while ( i < pm_vars->theNumberOfPowerStates )
1355 {
1356 if ( ( pm_vars->thePowerStates[i].outputPowerCharacter & theDesiredState) == (theDesiredState & pm_vars->myCharacterFlags) )
1357 {
1358 break;
1359 }
1360 i++;
1361 }
1362 if ( i == pm_vars->theNumberOfPowerStates )
1363 {
1364 return IOPMNoSuchState;
1365 }
1366 break;
1367
1368 default:
1369 return IOPMBadSpecification;
1370 }
1371
1372 computedState = i;
1373
1374 IOLockLock(pm_vars->childLock);
1375
1376 // Now loop through the children. When we encounter the calling child, save
1377 // the computed state as this child's desire.
1378 iter = getChildIterator(gIOPowerPlane);
1379
1380 if ( iter )
1381 {
1382 while ( (next = iter->getNextObject()) )
1383 {
1384 if ( (connection = OSDynamicCast(IOPowerConnection,next)) )
1385 {
1386 if ( connection == whichChild )
1387 {
1388 connection->setDesiredDomainState(computedState);
1389 connection->setPreventIdleSleepFlag(desiredState & kIOPMPreventIdleSleep);
1390 connection->setPreventSystemSleepFlag(desiredState & kIOPMPreventSystemSleep);
1391 connection->setChildHasRequestedPower();
1392 }
1393 }
1394 }
1395 iter->release();
1396 }
1397
1398 // Since a child's power requirements may have changed, clear and rebuild
1399 // kIOPMChildClamp and kIOPMChildClamp2 (idle and system sleep clamps)
1400 rebuildChildClampBits();
1401
1402 IOLockUnlock(pm_vars->childLock);
1403
1404 // this may be different now
1405 computeDesiredState();
1406
1407 if ( inPlane(gIOPowerPlane) &&
1408 (pm_vars->parentsKnowState) ) {
1409 // change state if all children can now tolerate lower power
1410 changeState();
1411 }
1412
1413 // are we clamped on, waiting for this child?
1414 if ( priv->clampOn ) {
1415 // yes, remove the clamp
1416 priv->clampOn = false;
1417 changePowerStateToPriv(0);
1418 }
1419
1420 return IOPMNoErr;
1421 }
1422
1423
1424 //*********************************************************************************
1425 // temporaryPowerClampOn
1426 //
1427 // A power domain wants to clamp its power on till it has children which
1428 // will thendetermine the power domain state.
1429 //
1430 // We enter the highest state until addPowerChild is called.
1431 //*********************************************************************************
1432
1433 IOReturn IOService::temporaryPowerClampOn ( void )
1434 {
1435 priv->clampOn = true;
1436 makeUsable();
1437 return IOPMNoErr;
1438 }
1439
1440
1441 //*********************************************************************************
1442 // makeUsable
1443 //
1444 // Some client of our device is asking that we become usable. Although
1445 // this has not come from a subclassed device object, treat it exactly
1446 // as if it had. In this way, subsequent requests for lower power from
1447 // a subclassed device object will pre-empt this request.
1448 //
1449 // We treat this as a subclass object request to switch to the
1450 // highest power state.
1451 //*********************************************************************************
1452
1453 IOReturn IOService::makeUsable ( void )
1454 {
1455 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogMakeUsable,0,0);
1456
1457 if ( pm_vars->theControllingDriver == NULL )
1458 {
1459 priv->need_to_become_usable = true;
1460 return IOPMNoErr;
1461 }
1462 priv->deviceDesire = pm_vars->theNumberOfPowerStates - 1;
1463 computeDesiredState();
1464 if ( inPlane(gIOPowerPlane) && (pm_vars->parentsKnowState) )
1465 {
1466 return changeState();
1467 }
1468 return IOPMNoErr;
1469 }
1470
1471 //******************************************************************************
1472 // temporaryMakeUsable
1473 //
1474 // Private function, called by IOService::addPowerChild to ensure that the
1475 // device is temporarily in a usable power state so that attached power
1476 // children may properly initialize.
1477 //******************************************************************************
1478
1479 IOReturn IOService::temporaryMakeUsable ( void )
1480 {
1481 IOReturn ret = kIOReturnSuccess;
1482 unsigned long tempDesire;
1483
1484 pm_vars->thePlatform->PMLog( pm_vars->ourName,
1485 PMlogMakeUsable,
1486 PMlogMakeUsable,
1487 priv->deviceDesire);
1488
1489 if ( pm_vars->theControllingDriver == NULL )
1490 {
1491 priv->need_to_become_usable = true;
1492 return IOPMNoErr;
1493 }
1494 tempDesire = priv->deviceDesire;
1495 priv->deviceDesire = pm_vars->theNumberOfPowerStates - 1;
1496 computeDesiredState();
1497 if ( inPlane(gIOPowerPlane) && (pm_vars->parentsKnowState) )
1498 {
1499 ret = changeState();
1500 }
1501 priv->deviceDesire = tempDesire;
1502 return ret;
1503 }
1504
1505
1506 //*********************************************************************************
1507 // currentCapability
1508 //
1509 //*********************************************************************************
1510
1511 IOPMPowerFlags IOService::currentCapability ( void )
1512 {
1513 if ( pm_vars->theControllingDriver == NULL )
1514 {
1515 return 0;
1516 } else {
1517 return pm_vars->thePowerStates[pm_vars->myCurrentState].capabilityFlags;
1518 }
1519 }
1520
1521
1522 //*********************************************************************************
1523 // changePowerStateTo
1524 //
1525 // For some reason, our power-controlling driver has decided it needs to change
1526 // power state. We enqueue the power change so that appropriate parties
1527 // will be notified, and then we will instruct the driver to make the change.
1528 //*********************************************************************************
1529
1530 IOReturn IOService::changePowerStateTo ( unsigned long ordinal )
1531 {
1532 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogChangeStateTo,ordinal,0);
1533
1534 if ( ordinal >= pm_vars->theNumberOfPowerStates )
1535 {
1536 return IOPMParameterError;
1537 }
1538 priv->driverDesire = ordinal;
1539 computeDesiredState();
1540 if ( inPlane(gIOPowerPlane) && (pm_vars->parentsKnowState) )
1541 {
1542 return changeState();
1543 }
1544
1545 return IOPMNoErr;
1546 }
1547
1548 //*********************************************************************************
1549 // changePowerStateToPriv
1550 //
1551 // For some reason, a subclassed device object has decided it needs to change
1552 // power state. We enqueue the power change so that appropriate parties
1553 // will be notified, and then we will instruct the driver to make the change.
1554 //*********************************************************************************
1555
1556 IOReturn IOService::changePowerStateToPriv ( unsigned long ordinal )
1557 {
1558 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogChangeStateToPriv,ordinal,0);
1559
1560 if ( pm_vars->theControllingDriver == NULL)
1561 {
1562 return IOPMNotYetInitialized;
1563 }
1564 if ( ordinal >= pm_vars->theNumberOfPowerStates )
1565 {
1566 return IOPMParameterError;
1567 }
1568 priv->deviceDesire = ordinal;
1569 computeDesiredState();
1570 if ( inPlane(gIOPowerPlane) && (pm_vars->parentsKnowState) )
1571 {
1572 return changeState();
1573 }
1574
1575 return IOPMNoErr;
1576 }
1577
1578
1579 //*********************************************************************************
1580 // computeDesiredState
1581 //
1582 //*********************************************************************************
1583
1584 void IOService::computeDesiredState ( void )
1585 {
1586 OSIterator *iter;
1587 OSObject *next;
1588 IOPowerConnection *connection;
1589 unsigned long newDesiredState = 0;
1590
1591 // Compute the maximum of our children's desires, our controlling driver's desire, and the subclass device's desire.
1592 if ( ! priv->device_overrides )
1593 {
1594 iter = getChildIterator(gIOPowerPlane);
1595
1596 if ( iter )
1597 {
1598 while ( (next = iter->getNextObject()) )
1599 {
1600 if ( (connection = OSDynamicCast(IOPowerConnection,next)) )
1601 {
1602 if ( connection->getDesiredDomainState() > newDesiredState )
1603 {
1604 newDesiredState = connection->getDesiredDomainState();
1605 }
1606 }
1607 }
1608 iter->release();
1609 }
1610
1611 if ( priv->driverDesire > newDesiredState )
1612 {
1613 newDesiredState = priv->driverDesire;
1614 }
1615 }
1616
1617 if ( priv->deviceDesire > newDesiredState )
1618 {
1619 newDesiredState = priv->deviceDesire;
1620 }
1621
1622 priv->ourDesiredPowerState = newDesiredState;
1623 }
1624
1625
1626 //*********************************************************************************
1627 // changeState
1628 //
1629 // A subclass object, our controlling driver, or a power domain child
1630 // has asked for a different power state. Here we compute what new
1631 // state we should enter and enqueue the change (or start it).
1632 //*********************************************************************************
1633
1634 IOReturn IOService::changeState ( void )
1635 {
1636 // if not fully initialized
1637 if ( (pm_vars->theControllingDriver == NULL) ||
1638 !(inPlane(gIOPowerPlane)) ||
1639 !(pm_vars->parentsKnowState) )
1640 {
1641 // we can do no more
1642 return IOPMNoErr;
1643 }
1644
1645 return enqueuePowerChange(IOPMWeInitiated,priv->ourDesiredPowerState,0,0,0);
1646 }
1647
1648
1649 //*********************************************************************************
1650 // currentPowerConsumption
1651 //
1652 //*********************************************************************************
1653
1654 unsigned long IOService::currentPowerConsumption ( void )
1655 {
1656 if ( pm_vars->theControllingDriver == NULL )
1657 {
1658 return kIOPMUnknown;
1659 }
1660 if ( pm_vars->thePowerStates[pm_vars->myCurrentState].capabilityFlags & kIOPMStaticPowerValid )
1661 {
1662 return pm_vars->thePowerStates[pm_vars->myCurrentState].staticPower;
1663 }
1664 return kIOPMUnknown;
1665 }
1666
1667 //*********************************************************************************
1668 // activityTickle
1669 //
1670 // The activity tickle with parameter kIOPMSubclassPolicyis not handled
1671 // here and should have been intercepted by the subclass.
1672 // The tickle with parameter kIOPMSuperclassPolicy1 causes the activity
1673 // flag to be set, and the device state checked. If the device has been
1674 // powered down, it is powered up again.
1675 //*********************************************************************************
1676
1677 bool IOService::activityTickle ( unsigned long type, unsigned long stateNumber )
1678 {
1679 IOPMrootDomain *pmRootDomain;
1680 AbsoluteTime uptime;
1681
1682 if ( type == kIOPMSuperclassPolicy1 )
1683 {
1684 if ( pm_vars->theControllingDriver == NULL )
1685 {
1686 return true;
1687 }
1688
1689 if( priv->activityLock == NULL )
1690 {
1691 priv->activityLock = IOLockAlloc();
1692 }
1693
1694 IOTakeLock(priv->activityLock);
1695 priv->device_active = true;
1696
1697 clock_get_uptime(&uptime);
1698 priv->device_active_timestamp = uptime;
1699
1700 if ( pm_vars->myCurrentState >= stateNumber)
1701 {
1702 IOUnlock(priv->activityLock);
1703 return true;
1704 }
1705 IOUnlock(priv->activityLock);
1706
1707 // Transfer execution to the PM workloop
1708 if( (pmRootDomain = getPMRootDomain()) )
1709 pmRootDomain->unIdleDevice(this, stateNumber);
1710
1711 return false;
1712 }
1713 return true;
1714 }
1715
1716 //*********************************************************************************
1717 // getPMworkloop
1718 //
1719 // A child is calling to get a pointer to the Power Management workloop.
1720 // We got it or get it from one of our parents.
1721 //*********************************************************************************
1722
1723 IOWorkLoop * IOService::getPMworkloop ( void )
1724 {
1725 IOService *nub;
1726 IOService *parent;
1727
1728 if ( ! inPlane(gIOPowerPlane) )
1729 {
1730 return NULL;
1731 }
1732 // we have no workloop yet
1733 if ( pm_vars->PMworkloop == NULL )
1734 {
1735 nub = (IOService *)copyParentEntry(gIOPowerPlane);
1736 if ( nub )
1737 {
1738 parent = (IOService *)nub->copyParentEntry(gIOPowerPlane);
1739 nub->release();
1740 // ask one of our parents for the workloop
1741 if ( parent )
1742 {
1743 pm_vars->PMworkloop = parent->getPMworkloop();
1744 parent->release();
1745 }
1746 }
1747 }
1748 return pm_vars->PMworkloop;
1749 }
1750
1751
1752 //*********************************************************************************
1753 // setIdleTimerPeriod
1754 //
1755 // A subclass policy-maker is going to use our standard idleness
1756 // detection service. Make a command queue and an idle timer and
1757 // connect them to the power management workloop. Finally,
1758 // start the timer.
1759 //*********************************************************************************
1760
1761 IOReturn IOService::setIdleTimerPeriod ( unsigned long period )
1762 {
1763 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMsetIdleTimerPeriod,period, 0);
1764
1765 priv->idle_timer_period = period;
1766
1767 if ( period > 0 )
1768 {
1769 if ( getPMworkloop() == NULL )
1770 {
1771 return kIOReturnError;
1772 }
1773
1774 // make the timer event
1775 if ( priv->timerEventSrc == NULL )
1776 {
1777 priv->timerEventSrc = IOTimerEventSource::timerEventSource(this,
1778 PM_idle_timer_expired);
1779 if ((!priv->timerEventSrc) ||
1780 (pm_vars->PMworkloop->addEventSource(priv->timerEventSrc) != kIOReturnSuccess) )
1781 {
1782 return kIOReturnError;
1783 }
1784 }
1785
1786 if ( priv->activityLock == NULL )
1787 {
1788 priv->activityLock = IOLockAlloc();
1789 }
1790
1791 start_PM_idle_timer();
1792 }
1793 return IOPMNoErr;
1794 }
1795
1796 //******************************************************************************
1797 // nextIdleTimeout
1798 //
1799 // Returns how many "seconds from now" the device should idle into its
1800 // next lowest power state.
1801 //******************************************************************************
1802 SInt32 IOService::nextIdleTimeout(
1803 AbsoluteTime currentTime,
1804 AbsoluteTime lastActivity,
1805 unsigned int powerState)
1806 {
1807 AbsoluteTime delta;
1808 UInt64 delta_ns;
1809 SInt32 delta_secs;
1810 SInt32 delay_secs;
1811
1812 // Calculate time difference using funky macro from clock.h.
1813 delta = currentTime;
1814 SUB_ABSOLUTETIME(&delta, &lastActivity);
1815
1816 // Figure it in seconds.
1817 absolutetime_to_nanoseconds(delta, &delta_ns);
1818 delta_secs = (SInt32)(delta_ns / NSEC_PER_SEC);
1819
1820 // Be paranoid about delta somehow exceeding timer period.
1821 if (delta_secs < (int) priv->idle_timer_period )
1822 delay_secs = (int) priv->idle_timer_period - delta_secs;
1823 else
1824 delay_secs = (int) priv->idle_timer_period;
1825
1826 return (SInt32)delay_secs;
1827 }
1828
1829 //******************************************************************************
1830 // start_PM_idle_timer
1831 //
1832 // The parameter is a pointer to us. Use it to call our timeout method.
1833 //******************************************************************************
1834 void IOService::start_PM_idle_timer ( void )
1835 {
1836 static const int maxTimeout = 100000;
1837 static const int minTimeout = 1;
1838 AbsoluteTime uptime;
1839 SInt32 idle_in = 0;
1840
1841 IOLockLock(priv->activityLock);
1842
1843 clock_get_uptime(&uptime);
1844
1845 // Subclasses may modify idle sleep algorithm
1846 idle_in = nextIdleTimeout(uptime,
1847 priv->device_active_timestamp,
1848 pm_vars->myCurrentState);
1849
1850 // Check for out-of range responses
1851 if(idle_in > maxTimeout)
1852 {
1853 // use standard implementation
1854 idle_in = IOService::nextIdleTimeout(uptime,
1855 priv->device_active_timestamp,
1856 pm_vars->myCurrentState);
1857 } else if(idle_in < minTimeout) {
1858 // fire immediately
1859 idle_in = 0;
1860 }
1861
1862 priv->timerEventSrc->setTimeout(idle_in, NSEC_PER_SEC);
1863
1864 IOLockUnlock(priv->activityLock);
1865 return;
1866 }
1867
1868
1869 //*********************************************************************************
1870 // PM_idle_timer_expired
1871 //
1872 // The parameter is a pointer to us. Use it to call our timeout method.
1873 //*********************************************************************************
1874
1875 void PM_idle_timer_expired(OSObject * ourSelves, IOTimerEventSource *)
1876 {
1877 ((IOService *)ourSelves)->PM_idle_timer_expiration();
1878 }
1879
1880
1881 //*********************************************************************************
1882 // PM_idle_timer_expiration
1883 //
1884 // The idle timer has expired. If there has been activity since the last
1885 // expiration, just restart the timer and return. If there has not been
1886 // activity, switch to the next lower power state and restart the timer.
1887 //*********************************************************************************
1888
1889 void IOService::PM_idle_timer_expiration ( void )
1890 {
1891 if ( ! initialized )
1892 {
1893 // we're unloading
1894 return;
1895 }
1896
1897 if ( priv->idle_timer_period > 0 )
1898 {
1899 IOTakeLock(priv->activityLock);
1900 if ( priv->device_active )
1901 {
1902 priv->device_active = false;
1903 IOUnlock(priv->activityLock);
1904 start_PM_idle_timer();
1905 return;
1906 }
1907 if ( pm_vars->myCurrentState > 0 )
1908 {
1909
1910 unsigned long newState = pm_vars->myCurrentState - 1;
1911
1912 IOUnlock(priv->activityLock);
1913 changePowerStateToPriv(newState);
1914 if ( newState >= priv->ourDesiredPowerState )
1915 start_PM_idle_timer();
1916 return;
1917 }
1918 IOUnlock(priv->activityLock);
1919 start_PM_idle_timer();
1920 }
1921 }
1922
1923
1924 // **********************************************************************************
1925 // command_received
1926 //
1927 // We are un-idling a device due to its activity tickle. This routine runs on the
1928 // PM workloop, and is initiated by IOService::activityTickle.
1929 // We process all activityTickle state requests on the list.
1930 // **********************************************************************************
1931 void IOService::command_received ( void *statePtr , void *, void * , void * )
1932 {
1933 unsigned long stateNumber;
1934
1935 stateNumber = (unsigned long)statePtr;
1936
1937 // If not initialized, we're unloading
1938 if ( ! initialized ) return;
1939
1940 if ( (pm_vars->myCurrentState < stateNumber) &&
1941 (priv->imminentState < stateNumber) )
1942 {
1943 changePowerStateToPriv(stateNumber);
1944
1945 // After we raise our state, re-schedule the idle timer.
1946 if(priv->timerEventSrc)
1947 start_PM_idle_timer();
1948 }
1949 }
1950
1951
1952 //*********************************************************************************
1953 // setAggressiveness
1954 //
1955 // Pass on the input parameters to all power domain children. All those which are
1956 // power domains will pass it on to their children, etc.
1957 //*********************************************************************************
1958
1959 IOReturn IOService::setAggressiveness ( unsigned long type, unsigned long newLevel )
1960 {
1961 OSIterator *iter;
1962 OSObject *next;
1963 IOPowerConnection *connection;
1964 IOService *child;
1965
1966 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogSetAggressiveness,type, newLevel);
1967
1968 if ( type <= kMaxType )
1969 {
1970 pm_vars->current_aggressiveness_values[type] = newLevel;
1971 pm_vars->current_aggressiveness_valid[type] = true;
1972 }
1973
1974 iter = getChildIterator(gIOPowerPlane);
1975
1976 if ( iter )
1977 {
1978 while ( (next = iter->getNextObject()) )
1979 {
1980 if ( (connection = OSDynamicCast(IOPowerConnection,next)) )
1981 {
1982 child = ((IOService *)(connection->copyChildEntry(gIOPowerPlane)));
1983 if ( child )
1984 {
1985 child->setAggressiveness(type, newLevel);
1986 child->release();
1987 }
1988 }
1989 }
1990 iter->release();
1991 }
1992
1993 return IOPMNoErr;
1994 }
1995
1996 //*********************************************************************************
1997 // getAggressiveness
1998 //
1999 // Called by the user client.
2000 //*********************************************************************************
2001
2002 IOReturn IOService::getAggressiveness ( unsigned long type, unsigned long * currentLevel )
2003 {
2004 if ( type > kMaxType )
2005 return kIOReturnBadArgument;
2006
2007 if ( !pm_vars->current_aggressiveness_valid[type] )
2008 return kIOReturnInvalid;
2009
2010 *currentLevel = pm_vars->current_aggressiveness_values[type];
2011
2012 return kIOReturnSuccess;
2013 }
2014
2015 //*********************************************************************************
2016 // systemWake
2017 //
2018 // Pass this to all power domain children. All those which are
2019 // power domains will pass it on to their children, etc.
2020 //*********************************************************************************
2021
2022 IOReturn IOService::systemWake ( void )
2023 {
2024 OSIterator *iter;
2025 OSObject *next;
2026 IOPowerConnection *connection;
2027 IOService *theChild;
2028
2029 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogSystemWake,0, 0);
2030
2031 iter = getChildIterator(gIOPowerPlane);
2032
2033 if ( iter )
2034 {
2035 while ( (next = iter->getNextObject()) )
2036 {
2037 if ( (connection = OSDynamicCast(IOPowerConnection,next)) )
2038 {
2039 theChild = (IOService *)connection->copyChildEntry(gIOPowerPlane);
2040 if ( theChild )
2041 {
2042 theChild->systemWake();
2043 theChild->release();
2044 }
2045 }
2046 }
2047 iter->release();
2048 }
2049
2050 if ( pm_vars->theControllingDriver != NULL )
2051 {
2052 if ( pm_vars->theControllingDriver->didYouWakeSystem() )
2053 {
2054 makeUsable();
2055 }
2056 }
2057
2058 return IOPMNoErr;
2059 }
2060
2061
2062 //*********************************************************************************
2063 // temperatureCriticalForZone
2064 //
2065 //*********************************************************************************
2066
2067 IOReturn IOService::temperatureCriticalForZone ( IOService * whichZone )
2068 {
2069 IOService *theParent;
2070 IOService *theNub;
2071
2072 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogCriticalTemp,0,0);
2073
2074 if ( inPlane(gIOPowerPlane) && !(priv->we_are_root) )
2075 {
2076 theNub = (IOService *)copyParentEntry(gIOPowerPlane);
2077 if ( theNub )
2078 {
2079 theParent = (IOService *)theNub->copyParentEntry(gIOPowerPlane);
2080 theNub->release();
2081 if ( theParent )
2082 {
2083 theParent->temperatureCriticalForZone(whichZone);
2084 theParent->release();
2085 }
2086 }
2087 }
2088 return IOPMNoErr;
2089 }
2090
2091
2092 //*********************************************************************************
2093 // powerOverrideOnPriv
2094 //
2095 //*********************************************************************************
2096
2097
2098 IOReturn IOService::powerOverrideOnPriv ( void )
2099 {
2100 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogOverrideOn,0,0);
2101
2102 // turn on the override
2103 priv->device_overrides = true;
2104 computeDesiredState();
2105
2106 // change state if that changed something
2107 return changeState();
2108 }
2109
2110
2111 //*********************************************************************************
2112 // powerOverrideOffPriv
2113 //
2114 //*********************************************************************************
2115 IOReturn IOService::powerOverrideOffPriv ( void )
2116 {
2117 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogOverrideOff,0,0);
2118
2119 // turn off the override
2120 priv->device_overrides = false;
2121 computeDesiredState();
2122 if( priv->clampOn)
2123 {
2124 return makeUsable();
2125 } else {
2126 // change state if that changed something
2127 return changeState();
2128 }
2129 }
2130
2131
2132 //*********************************************************************************
2133 // enqueuePowerChange
2134 //
2135 // Allocate a new state change notification, initialize it with fields from the
2136 // caller, and add it to the tail of the list of pending power changes.
2137 //
2138 // If it is early enough in the list, and almost all the time it is the only one in
2139 // the list, start the power change.
2140 //
2141 // In rare instances, this change will preempt the previous change in the list.
2142 // If the previous change is un-actioned in any way (because we are still
2143 // processing an even earlier power change), and if both the previous change
2144 // in the list and this change are initiated by us (not the parent), then we
2145 // needn't perform the previous change, so we collapse the list a little.
2146 //*********************************************************************************
2147
2148 IOReturn IOService::enqueuePowerChange (
2149 unsigned long flags,
2150 unsigned long whatStateOrdinal,
2151 unsigned long domainState,
2152 IOPowerConnection * whichParent,
2153 unsigned long singleParentState )
2154 {
2155 long newNote;
2156 long previousNote;
2157
2158 // Create and initialize the new change note
2159
2160 IOLockLock(priv->queue_lock);
2161 newNote = priv->changeList->createChangeNote();
2162 if ( newNote == -1 ) {
2163 // uh-oh, our list is full
2164 IOLockUnlock(priv->queue_lock);
2165 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogEnqueueErr,0,0);
2166 return IOPMAckImplied;
2167 }
2168
2169 priv->changeList->changeNote[newNote].newStateNumber = whatStateOrdinal;
2170 priv->changeList->changeNote[newNote].outputPowerCharacter = pm_vars->thePowerStates[whatStateOrdinal].outputPowerCharacter;
2171 priv->changeList->changeNote[newNote].inputPowerRequirement = pm_vars->thePowerStates[whatStateOrdinal].inputPowerRequirement;
2172 priv->changeList->changeNote[newNote].capabilityFlags = pm_vars->thePowerStates[whatStateOrdinal].capabilityFlags;
2173 priv->changeList->changeNote[newNote].flags = flags;
2174 priv->changeList->changeNote[newNote].parent = NULL;
2175 if (flags & IOPMParentInitiated )
2176 {
2177 priv->changeList->changeNote[newNote].domainState = domainState;
2178 priv->changeList->changeNote[newNote].parent = whichParent;
2179 whichParent->retain();
2180 priv->changeList->changeNote[newNote].singleParentState = singleParentState;
2181 }
2182
2183 previousNote = priv->changeList->previousChangeNote(newNote);
2184
2185 if ( previousNote == -1 )
2186 {
2187
2188 // Queue is empty, we can start this change.
2189
2190 if (flags & IOPMWeInitiated )
2191 {
2192 IOLockUnlock(priv->queue_lock);
2193 start_our_change(newNote);
2194 return 0;
2195 } else {
2196 IOLockUnlock(priv->queue_lock);
2197 return start_parent_change(newNote);
2198 }
2199 }
2200
2201 // The queue is not empty. Try to collapse this new change and the previous one in queue into one change.
2202 // This is possible only if both changes are initiated by us, and neither has been started yet.
2203 // Do this more than once if possible.
2204
2205 // (A change is started iff it is at the head of the queue)
2206
2207 while ( (previousNote != priv->head_note) && (previousNote != -1) &&
2208 (priv->changeList->changeNote[newNote].flags & priv->changeList->changeNote[previousNote].flags & IOPMWeInitiated) )
2209 {
2210 priv->changeList->changeNote[previousNote].outputPowerCharacter = priv->changeList->changeNote[newNote].outputPowerCharacter;
2211 priv->changeList->changeNote[previousNote].inputPowerRequirement = priv->changeList->changeNote[newNote].inputPowerRequirement;
2212 priv->changeList->changeNote[previousNote].capabilityFlags =priv-> changeList->changeNote[newNote].capabilityFlags;
2213 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogCollapseQueue,priv->changeList->changeNote[newNote].newStateNumber,
2214 priv->changeList->changeNote[previousNote].newStateNumber);
2215 priv->changeList->changeNote[previousNote].newStateNumber = priv->changeList->changeNote[newNote].newStateNumber;
2216 priv->changeList->releaseTailChangeNote();
2217 newNote = previousNote;
2218 previousNote = priv->changeList->previousChangeNote(newNote);
2219 }
2220 IOLockUnlock(priv->queue_lock);
2221 // in any case, we can't start yet
2222 return IOPMWillAckLater;
2223 }
2224
2225 //*********************************************************************************
2226 // notifyAll
2227 //
2228 // Notify all interested parties either that a change is impending or that the
2229 // previously-notified change is done and power has settled.
2230 // The parameter identifies whether this is the
2231 // pre-change notification or the post-change notification.
2232 //
2233 //*********************************************************************************
2234
2235 IOReturn IOService::notifyAll ( bool is_prechange )
2236 {
2237 IOPMinformee * nextObject;
2238 OSIterator * iter;
2239 OSObject * next;
2240 IOPowerConnection * connection;
2241
2242 // To prevent acknowledgePowerChange from finishing the change note and
2243 // removing it from the queue if
2244 // some driver calls it, we inflate the number of pending acks so it
2245 // cannot become zero. We'll fix it later.
2246
2247 if(!acquire_lock()) return IOPMAckImplied;
2248
2249 OSAddAtomic(1, (SInt32*)&priv->head_note_pendingAcks);
2250
2251 // OK, we will go through the lists of interested drivers and
2252 // power domain children and notify each one of this change.
2253
2254 nextObject = priv->interestedDrivers->firstInList();
2255 while ( nextObject != NULL ) {
2256
2257 OSAddAtomic(1, (SInt32*)&priv->head_note_pendingAcks);
2258
2259 IOUnlock(priv->our_lock);
2260
2261 inform(nextObject, is_prechange);
2262
2263 if(!acquire_lock())
2264 {
2265 goto exit;
2266 }
2267
2268 nextObject = priv->interestedDrivers->nextInList(nextObject);
2269 }
2270
2271 // did they all ack?
2272 if ( priv->head_note_pendingAcks > 1 ) {
2273 // no
2274 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogStartAckTimer,0,0);
2275 start_ack_timer();
2276 }
2277 // either way
2278 IOUnlock(priv->our_lock);
2279
2280 // notify children
2281 iter = getChildIterator(gIOPowerPlane);
2282 // summing their power consumption
2283 pm_vars->thePowerStates[priv->head_note_state].staticPower = 0;
2284
2285 if ( iter && acquire_lock())
2286 {
2287 while ( (next = iter->getNextObject()) )
2288 {
2289 if ( (connection = OSDynamicCast(IOPowerConnection,next)) )
2290 {
2291 OSAddAtomic(1, (SInt32*)&priv->head_note_pendingAcks);
2292
2293 IOUnlock(priv->our_lock);
2294
2295 notifyChild(connection, is_prechange);
2296
2297 if(!acquire_lock())
2298 {
2299 goto exit;
2300 }
2301 }
2302 }
2303 iter->release();
2304 IOUnlock(priv->our_lock);
2305 }
2306
2307 if (! acquire_lock() ) {
2308 return IOPMNoErr;
2309 }
2310 // now make this real
2311 OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
2312
2313 // is it all acked?
2314 if (priv->head_note_pendingAcks == 0 ) {
2315 // yes, all acked
2316 IOUnlock(priv->our_lock);
2317 // return ack to parent
2318 return IOPMAckImplied;
2319 }
2320
2321 // not all acked
2322 IOUnlock(priv->our_lock);
2323
2324 exit: // unable to acquire_lock exit case
2325
2326 return IOPMWillAckLater;
2327 }
2328
2329
2330 //*********************************************************************************
2331 // notifyChild
2332 //
2333 // Notify a power domain child of an upcoming power change.
2334 //
2335 // If the object acknowledges the current change, we return TRUE.
2336 //*********************************************************************************
2337
2338 bool IOService::notifyChild ( IOPowerConnection * theNub, bool is_prechange )
2339 {
2340 IOReturn k = IOPMAckImplied;
2341 unsigned long childPower;
2342 IOService *theChild;
2343
2344 theChild = (IOService *)(theNub->copyChildEntry(gIOPowerPlane));
2345 if(!theChild)
2346 {
2347 // The child has been detached since we grabbed the child iterator.
2348 // Decrement pending_acks, already incremented in notifyAll,
2349 // to account for this unexpected departure.
2350
2351 if( acquire_lock() )
2352 {
2353 OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
2354 IOUnlock(priv->our_lock);
2355 }
2356 return true;
2357 }
2358
2359 // Unless the child handles the notification immediately and returns
2360 // kIOPMAckImplied, we'll be awaiting their acknowledgement later.
2361 theNub->setAwaitingAck(true);
2362
2363 if ( is_prechange )
2364 {
2365 k = theChild->powerDomainWillChangeTo(priv->head_note_outputFlags,theNub);
2366 } else {
2367 k = theChild->powerDomainDidChangeTo(priv->head_note_outputFlags,theNub);
2368 }
2369
2370 // did the return code ack?
2371 if ( k == IOPMAckImplied )
2372 {
2373 // yes
2374 if( acquire_lock() )
2375 {
2376 OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
2377 IOUnlock(priv->our_lock);
2378 }
2379
2380 theNub->setAwaitingAck(false);
2381 childPower = theChild->currentPowerConsumption();
2382 if ( childPower == kIOPMUnknown )
2383 {
2384 pm_vars->thePowerStates[priv->head_note_state].staticPower = kIOPMUnknown;
2385 } else {
2386 if ( pm_vars->thePowerStates[priv->head_note_state].staticPower != kIOPMUnknown )
2387 {
2388 pm_vars->thePowerStates[priv->head_note_state].staticPower += childPower;
2389 }
2390 }
2391 theChild->release();
2392 return true;
2393 }
2394 theChild->release();
2395 return false;
2396 }
2397
2398
2399 //*********************************************************************************
2400 // inform
2401 //
2402 // Notify an interested driver of an upcoming power change.
2403 //
2404 // If the object acknowledges the current change, we return TRUE.
2405 //*********************************************************************************
2406
2407 bool IOService::inform ( IOPMinformee * nextObject, bool is_prechange )
2408 {
2409 IOReturn k = IOPMAckImplied;
2410
2411 // initialize this
2412 nextObject->timer = -1;
2413
2414 if ( is_prechange )
2415 {
2416 pm_vars->thePlatform->PMLog (pm_vars->ourName,PMlogInformDriverPreChange,
2417 (unsigned long)priv->head_note_capabilityFlags,(unsigned long)priv->head_note_state);
2418 k = nextObject->whatObject->powerStateWillChangeTo( priv->head_note_capabilityFlags,priv->head_note_state,this);
2419 } else {
2420 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogInformDriverPostChange,
2421 (unsigned long)priv->head_note_capabilityFlags,(unsigned long)priv->head_note_state);
2422 k = nextObject->whatObject->powerStateDidChangeTo(priv->head_note_capabilityFlags,priv->head_note_state,this);
2423 }
2424
2425 // did it ack behind our back?
2426 if ( nextObject->timer == 0 )
2427 {
2428 // yes
2429 return true;
2430 }
2431
2432 if ( (k ==IOPMAckImplied) // no, did the return code ack?
2433 || (k < 0) ) // somebody goofed
2434 {
2435 // yes
2436 nextObject->timer = 0;
2437
2438 if( acquire_lock() )
2439 {
2440 OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
2441 IOUnlock(priv->our_lock);
2442 }
2443 return true;
2444 }
2445
2446 // no, it's a timer
2447 nextObject->timer = (k / (ACK_TIMER_PERIOD / ns_per_us)) + 1;
2448
2449 return false;
2450 }
2451
2452
2453 //*********************************************************************************
2454 // OurChangeTellClientsPowerDown
2455 //
2456 // All registered applications and kernel clients have positively acknowledged our
2457 // intention of lowering power. Here we notify them all that we will definitely
2458 // lower the power. If we don't have to wait for any of them to acknowledge, we
2459 // carry on by notifying interested drivers. Otherwise, we do wait.
2460 //*********************************************************************************
2461
2462 void IOService::OurChangeTellClientsPowerDown ( void )
2463 {
2464 // next state
2465 priv->machine_state = kIOPM_OurChangeTellPriorityClientsPowerDown;
2466
2467 // are we waiting for responses?
2468 if ( tellChangeDown1(priv->head_note_state) )
2469 {
2470 // no, notify priority clients
2471 OurChangeTellPriorityClientsPowerDown();
2472 }
2473 // If we are waiting for responses, execution will resume via
2474 // allowCancelCommon() or ack timeout
2475 }
2476
2477
2478 //*********************************************************************************
2479 // OurChangeTellPriorityClientsPowerDown
2480 //
2481 // All registered applications and kernel clients have positively acknowledged our
2482 // intention of lowering power. Here we notify "priority" clients that we are
2483 // lowering power. If we don't have to wait for any of them to acknowledge, we
2484 // carry on by notifying interested drivers. Otherwise, we do wait.
2485 //*********************************************************************************
2486
2487 void IOService::OurChangeTellPriorityClientsPowerDown ( void )
2488 {
2489 // next state
2490 priv->machine_state = kIOPM_OurChangeNotifyInterestedDriversWillChange;
2491 // are we waiting for responses?
2492 if ( tellChangeDown2(priv->head_note_state) )
2493 {
2494 // no, notify interested drivers
2495 return OurChangeNotifyInterestedDriversWillChange();
2496 }
2497 // If we are waiting for responses, execution will resume via
2498 // allowCancelCommon() or ack timeout
2499 }
2500
2501
2502 //*********************************************************************************
2503 // OurChangeNotifyInterestedDriversWillChange
2504 //
2505 // All registered applications and kernel clients have acknowledged our notification
2506 // that we are lowering power. Here we notify interested drivers. If we don't have
2507 // to wait for any of them to acknowledge, we instruct our power driver to make the change.
2508 // Otherwise, we do wait.
2509 //*********************************************************************************
2510
2511 void IOService::OurChangeNotifyInterestedDriversWillChange ( void )
2512 {
2513 // no, in case they don't all ack
2514 priv->machine_state = kIOPM_OurChangeSetPowerState;
2515 if ( notifyAll(true) == IOPMAckImplied )
2516 {
2517 // not waiting for responses
2518 OurChangeSetPowerState();
2519 }
2520 // If we are waiting for responses, execution will resume via
2521 // all_acked() or ack timeout
2522 }
2523
2524
2525 //*********************************************************************************
2526 // OurChangeSetPowerState
2527 //
2528 // All interested drivers have acknowledged our pre-change notification of a power
2529 // change we initiated. Here we instruct our controlling driver to make
2530 // the change to the hardware. If it does so, we continue processing
2531 // (waiting for settle and notifying interested parties post-change.)
2532 // If it doesn't, we have to wait for it to acknowledge and then continue.
2533 //*********************************************************************************
2534
2535 void IOService::OurChangeSetPowerState ( void )
2536 {
2537 priv->machine_state = kIOPM_OurChangeWaitForPowerSettle;
2538
2539 IOLockLock(priv->our_lock);
2540
2541 if ( instruct_driver(priv->head_note_state) == IOPMAckImplied )
2542 {
2543 // it's done, carry on
2544 IOLockUnlock(priv->our_lock);
2545 OurChangeWaitForPowerSettle();
2546 } else {
2547 // it's not, wait for it
2548 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogStartAckTimer,0,0);
2549 start_ack_timer();
2550 IOLockUnlock(priv->our_lock);
2551 // execution will resume via ack_timer_ticked()
2552 }
2553 }
2554
2555
2556 //*********************************************************************************
2557 // OurChangeWaitForPowerSettle
2558 //
2559 // Our controlling driver has changed power state on the hardware
2560 // during a power change we initiated. Here we see if we need to wait
2561 // for power to settle before continuing. If not, we continue processing
2562 // (notifying interested parties post-change). If so, we wait and
2563 // continue later.
2564 //*********************************************************************************
2565
2566 void IOService::OurChangeWaitForPowerSettle ( void )
2567 {
2568 priv->settle_time = compute_settle_time();
2569 if ( priv->settle_time == 0 )
2570 {
2571 OurChangeNotifyInterestedDriversDidChange();
2572 } else {
2573 priv->machine_state = kIOPM_OurChangeNotifyInterestedDriversDidChange;
2574 startSettleTimer(priv->settle_time);
2575 }
2576 }
2577
2578
2579 //*********************************************************************************
2580 // OurChangeNotifyInterestedDriversDidChange
2581 //
2582 // Power has settled on a power change we initiated. Here we notify
2583 // all our interested parties post-change. If they all acknowledge, we're
2584 // done with this change note, and we can start on the next one.
2585 // Otherwise we have to wait for acknowledgements and finish up later.
2586 //*********************************************************************************
2587
2588 void IOService::OurChangeNotifyInterestedDriversDidChange ( void )
2589 {
2590 // in case they don't all ack
2591 priv->machine_state = kIOPM_OurChangeFinish;
2592 if ( notifyAll(false) == IOPMAckImplied )
2593 {
2594 // not waiting for responses
2595 OurChangeFinish();
2596 }
2597 // If we are waiting for responses, execution will resume via
2598 // all_acked() or ack timeout
2599 }
2600
2601
2602 //*********************************************************************************
2603 // OurChangeFinish
2604 //
2605 // Power has settled on a power change we initiated, and
2606 // all our interested parties have acknowledged. We're
2607 // done with this change note, and we can start on the next one.
2608 //*********************************************************************************
2609
2610 void IOService::OurChangeFinish ( void )
2611 {
2612 all_done();
2613 }
2614
2615
2616 //*********************************************************************************
2617 // ParentDownTellPriorityClientsPowerDown_Immediate
2618 //
2619 // All applications and kernel clients have been notified of a power lowering
2620 // initiated by the parent and we didn't have to wait for any responses. Here
2621 // we notify any priority clients. If they all ack, we continue with the power change.
2622 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2623 //*********************************************************************************
2624
2625 IOReturn IOService::ParentDownTellPriorityClientsPowerDown_Immediate ( void )
2626 {
2627 // in case they don't all ack
2628 priv->machine_state = kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed;
2629 // are we waiting for responses?
2630 if ( tellChangeDown2(priv->head_note_state) )
2631 {
2632 // no, notify interested drivers
2633 return ParentDownNotifyInterestedDriversWillChange_Immediate();
2634 }
2635 // If we are waiting for responses, execution will resume via
2636 // allowCancelCommon() or ack timeout
2637 return IOPMWillAckLater;
2638 }
2639
2640
2641 //*********************************************************************************
2642 // ParentDownTellPriorityClientsPowerDown_Immediate2
2643 //
2644 // All priority kernel clients have been notified of a power lowering
2645 // initiated by the parent and we didn't have to wait for any responses. Here
2646 // we notify any interested drivers and power domain children. If they all ack,
2647 // we continue with the power change.
2648 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2649 //*********************************************************************************
2650
2651 IOReturn IOService::ParentDownNotifyInterestedDriversWillChange_Immediate ( void )
2652 {
2653 // in case they don't all ack
2654 priv->machine_state = kIOPM_ParentDownSetPowerState_Delayed;
2655 if ( notifyAll(true) == IOPMAckImplied )
2656 {
2657 // they did
2658 return ParentDownSetPowerState_Immediate();
2659 }
2660 // If we are waiting for responses, execution will resume via
2661 // all_acked() or ack timeout
2662 return IOPMWillAckLater;
2663 }
2664
2665
2666 //*********************************************************************************
2667 // ParentDownTellPriorityClientsPowerDown_Immediate4
2668 //
2669 // All applications and kernel clients have been notified of a power lowering
2670 // initiated by the parent and we had to wait for responses. Here
2671 // we notify any priority clients. If they all ack, we continue with the power change.
2672 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2673 //*********************************************************************************
2674
2675 void IOService::ParentDownTellPriorityClientsPowerDown_Delayed ( void )
2676 {
2677 // in case they don't all ack
2678 priv->machine_state = kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed;
2679
2680 // are we waiting for responses?
2681 if ( tellChangeDown2(priv->head_note_state) )
2682 {
2683 // no, notify interested drivers
2684 ParentDownNotifyInterestedDriversWillChange_Delayed();
2685 }
2686 // If we are waiting for responses, execution will resume via
2687 // allowCancelCommon() or ack timeout
2688 }
2689
2690
2691 //*********************************************************************************
2692 // ParentDownTellPriorityClientsPowerDown_Immediate5
2693 //
2694 // All applications and kernel clients have been notified of a power lowering
2695 // initiated by the parent and we had to wait for their responses. Here we notify
2696 // any interested drivers and power domain children. If they all ack, we continue
2697 // with the power change.
2698 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
2699 //*********************************************************************************
2700
2701 void IOService::ParentDownNotifyInterestedDriversWillChange_Delayed ( void )
2702 {
2703 // in case they don't all ack
2704 priv->machine_state = kIOPM_ParentDownSetPowerState_Delayed;
2705 if ( notifyAll(true) == IOPMAckImplied )
2706 {
2707 // they did
2708 ParentDownSetPowerState_Delayed();
2709 }
2710 // If we are waiting for responses, execution will resume via
2711 // all_acked() or ack timeout
2712 }
2713
2714
2715 //*********************************************************************************
2716 // ParentDownSetPowerState_Immediate
2717 //
2718 // All parties have acknowledged our pre-change notification of a power
2719 // lowering initiated by the parent. Here we instruct our controlling driver
2720 // to put the hardware in the state it needs to be in when the domain is
2721 // lowered. If it does so, we continue processing
2722 // (waiting for settle and acknowledging the parent.)
2723 // If it doesn't, we have to wait for it to acknowledge and then continue.
2724 //*********************************************************************************
2725
2726 IOReturn IOService::ParentDownSetPowerState_Immediate ( void )
2727 {
2728 priv->machine_state = kIOPM_ParentDownWaitForPowerSettle_Delayed;
2729
2730 IOLockLock(priv->our_lock);
2731
2732 if ( instruct_driver(priv->head_note_state) == IOPMAckImplied )
2733 {
2734 // it's done, carry on
2735 IOLockUnlock(priv->our_lock);
2736 return ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate();
2737 }
2738 // it's not, wait for it
2739 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogStartAckTimer,0,0);
2740 start_ack_timer();
2741 IOLockUnlock(priv->our_lock);
2742 return IOPMWillAckLater;
2743 }
2744
2745
2746 //*********************************************************************************
2747 // ParentDownSetPowerState_Delayed
2748 //
2749 // We had to wait for it, but all parties have acknowledged our pre-change
2750 // notification of a power lowering initiated by the parent.
2751 // Here we instruct our controlling driver
2752 // to put the hardware in the state it needs to be in when the domain is
2753 // lowered. If it does so, we continue processing
2754 // (waiting for settle and acknowledging the parent.)
2755 // If it doesn't, we have to wait for it to acknowledge and then continue.
2756 //*********************************************************************************
2757
2758 void IOService::ParentDownSetPowerState_Delayed ( void )
2759 {
2760 priv-> machine_state = kIOPM_ParentDownWaitForPowerSettle_Delayed;
2761
2762 IOLockLock(priv->our_lock);
2763
2764 if ( instruct_driver(priv->head_note_state) == IOPMAckImplied )
2765 {
2766 // it's done, carry on
2767 IOLockUnlock(priv->our_lock);
2768 ParentDownWaitForPowerSettle_Delayed();
2769 } else {
2770 // it's not, wait for it
2771 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogStartAckTimer,0,0);
2772 start_ack_timer();
2773 IOLockUnlock(priv->our_lock);
2774 }
2775 }
2776
2777
2778 //*********************************************************************************
2779 // ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate
2780 //
2781 // Our controlling driver has changed power state on the hardware
2782 // during a power change initiated by our parent. Here we see if we need
2783 // to wait for power to settle before continuing. If not, we continue
2784 // processing (acknowledging our preparedness to the parent).
2785 // If so, we wait and continue later.
2786 //*********************************************************************************
2787
2788 IOReturn IOService::ParentDownWaitForPowerSettleAndNotifyDidChange_Immediate ( void )
2789 {
2790 IOService * nub;
2791
2792 priv->settle_time = compute_settle_time();
2793 if ( priv->settle_time == 0 )
2794 {
2795 // store current state in case they don't all ack
2796 priv->machine_state = kIOPM_ParentDownAcknowledgeChange_Delayed;
2797 if ( notifyAll(false) == IOPMAckImplied )
2798 {
2799 // not waiting for responses
2800 nub = priv->head_note_parent;
2801 nub->retain();
2802 all_done();
2803 nub->release();
2804 return IOPMAckImplied;
2805 }
2806 // If we are waiting for responses, execution will resume via
2807 // all_acked() or ack timeout
2808 return IOPMWillAckLater;
2809 } else {
2810 // let settle time elapse, then notify interest drivers of our power state change in ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
2811 priv->machine_state = kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed;
2812 startSettleTimer(priv->settle_time);
2813 return IOPMWillAckLater;
2814 }
2815 }
2816
2817
2818 //*********************************************************************************
2819 // ParentDownWaitForPowerSettle_Delayed
2820 //
2821 // Our controlling driver has changed power state on the hardware
2822 // during a power change initiated by our parent. We have had to wait
2823 // for acknowledgement from interested parties, or we have had to wait
2824 // for the controlling driver to change the state. Here we see if we need
2825 // to wait for power to settle before continuing. If not, we continue
2826 // processing (acknowledging our preparedness to the parent).
2827 // If so, we wait and continue later.
2828 //*********************************************************************************
2829
2830 void IOService::ParentDownWaitForPowerSettle_Delayed ( void )
2831 {
2832 priv->settle_time = compute_settle_time();
2833 if ( priv->settle_time == 0 )
2834 {
2835 ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed();
2836 } else {
2837 priv->machine_state = kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed;
2838 startSettleTimer(priv->settle_time);
2839 }
2840 }
2841
2842
2843 //*********************************************************************************
2844 // ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed
2845 //
2846 // Power has settled on a power change initiated by our parent. Here we
2847 // notify interested parties.
2848 //*********************************************************************************
2849
2850 void IOService::ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed ( void )
2851 {
2852 IORegistryEntry *nub;
2853 IOService *parent;
2854
2855 // in case they don't all ack
2856 priv->machine_state = kIOPM_ParentDownAcknowledgeChange_Delayed;
2857 if ( notifyAll(false) == IOPMAckImplied ) {
2858 nub = priv->head_note_parent;
2859 nub->retain();
2860 all_done();
2861 parent = (IOService *)nub->copyParentEntry(gIOPowerPlane);
2862 if ( parent ) {
2863 parent->acknowledgePowerChange((IOService *)nub);
2864 parent->release();
2865 }
2866 nub->release();
2867 }
2868 // If we are waiting for responses, execution will resume via
2869 // all_acked() or ack timeout in ParentDownAcknowledgeChange_Delayed.
2870 // Notice the duplication of code just above and in ParentDownAcknowledgeChange_Delayed.
2871 }
2872
2873
2874 //*********************************************************************************
2875 // ParentDownAcknowledgeChange_Delayed
2876 //
2877 // We had to wait for it, but all parties have acknowledged our post-change
2878 // notification of a power lowering initiated by the parent.
2879 // Here we acknowledge the parent.
2880 // We are done with this change note, and we can start on the next one.
2881 //*********************************************************************************
2882
2883 void IOService::ParentDownAcknowledgeChange_Delayed ( void )
2884 {
2885 IORegistryEntry *nub;
2886 IOService *parent;
2887
2888 nub = priv->head_note_parent;
2889 nub->retain();
2890 all_done();
2891 parent = (IOService *)nub->copyParentEntry(gIOPowerPlane);
2892 if ( parent )
2893 {
2894 parent->acknowledgePowerChange((IOService *)nub);
2895 parent->release();
2896 }
2897 nub->release();
2898 }
2899
2900
2901 //*********************************************************************************
2902 // ParentUpSetPowerState_Delayed
2903 //
2904 // Our parent has informed us via powerStateDidChange that it has
2905 // raised the power in our power domain, and we have had to wait
2906 // for some interested party to acknowledge our notification.
2907 // Here we instruct our controlling
2908 // driver to program the hardware to take advantage of the higher domain
2909 // power. If it does so, we continue processing
2910 // (waiting for settle and notifying interested parties post-change.)
2911 // If it doesn't, we have to wait for it to acknowledge and then continue.
2912 //*********************************************************************************
2913
2914 void IOService::ParentUpSetPowerState_Delayed ( void )
2915 {
2916 priv->machine_state = kIOPM_ParentUpWaitForSettleTime_Delayed;
2917
2918 IOLockLock(priv->our_lock);
2919
2920 if ( instruct_driver(priv->head_note_state) == IOPMAckImplied )
2921 {
2922 // it did it, carry on
2923 IOLockUnlock(priv->our_lock);
2924 ParentUpWaitForSettleTime_Delayed();
2925 } else {
2926 // it didn't, wait for it
2927 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogStartAckTimer,0,0);
2928 start_ack_timer();
2929 IOLockUnlock(priv->our_lock);
2930 }
2931 }
2932
2933
2934 //*********************************************************************************
2935 // ParentUpSetPowerState_Immediate
2936 //
2937 // Our parent has informed us via powerStateDidChange that it has
2938 // raised the power in our power domain. Here we instruct our controlling
2939 // driver to program the hardware to take advantage of the higher domain
2940 // power. If it does so, we continue processing
2941 // (waiting for settle and notifying interested parties post-change.)
2942 // If it doesn't, we have to wait for it to acknowledge and then continue.
2943 //*********************************************************************************
2944
2945 IOReturn IOService::ParentUpSetPowerState_Immediate ( void )
2946 {
2947 priv->machine_state = kIOPM_ParentUpWaitForSettleTime_Delayed;
2948
2949 IOLockLock(priv->our_lock);
2950
2951 if ( instruct_driver(priv->head_note_state) == IOPMAckImplied )
2952 {
2953 // it did it, carry on
2954 IOLockUnlock(priv->our_lock);
2955 return ParentUpWaitForSettleTime_Immediate();
2956 }
2957 else {
2958 // it didn't, wait for it
2959 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogStartAckTimer,0,0);
2960 start_ack_timer();
2961 IOLockUnlock(priv->our_lock);
2962 return IOPMWillAckLater;
2963 }
2964 }
2965
2966
2967 //*********************************************************************************
2968 // ParentUpWaitForSettleTime_Immediate
2969 //
2970 // Our controlling driver has changed power state on the hardware
2971 // during a power raise initiated by the parent. Here we see if we need to wait
2972 // for power to settle before continuing. If not, we continue processing
2973 // (notifying interested parties post-change). If so, we wait and
2974 // continue later.
2975 //*********************************************************************************
2976
2977 IOReturn IOService::ParentUpWaitForSettleTime_Immediate ( void )
2978 {
2979 priv->settle_time = compute_settle_time();
2980 if ( priv->settle_time == 0 )
2981 {
2982 return ParentUpNotifyInterestedDriversDidChange_Immediate();
2983 } else {
2984 priv->machine_state = kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed;
2985 startSettleTimer(priv->settle_time);
2986 return IOPMWillAckLater;
2987 }
2988 }
2989
2990
2991 //*********************************************************************************
2992 // ParentUpWaitForSettleTime_Delayed
2993 //
2994 // Our controlling driver has changed power state on the hardware
2995 // during a power raise initiated by the parent, but we had to wait for it.
2996 // Here we see if we need to wait for power to settle before continuing.
2997 // If not, we continue processing (notifying interested parties post-change).
2998 // If so, we wait and continue later.
2999 //*********************************************************************************
3000
3001 void IOService::ParentUpWaitForSettleTime_Delayed ( void )
3002 {
3003 priv->settle_time = compute_settle_time();
3004 if ( priv->settle_time == 0 )
3005 {
3006 ParentUpNotifyInterestedDriversDidChange_Delayed();
3007 } else {
3008 priv->machine_state = kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed;
3009 startSettleTimer(priv->settle_time);
3010 }
3011 }
3012
3013
3014 //*********************************************************************************
3015 // ParentUpNotifyInterestedDriversDidChange_Immediate
3016 //
3017 // No power settling was required on a power raise initiated by the parent.
3018 // Here we notify all our interested parties post-change. If they all acknowledge,
3019 // we're done with this change note, and we can start on the next one.
3020 // Otherwise we have to wait for acknowledgements and finish up later.
3021 //*********************************************************************************
3022
3023 IOReturn IOService::ParentUpNotifyInterestedDriversDidChange_Immediate ( void )
3024 {
3025 IOService * nub;
3026
3027 // in case they don't all ack
3028 priv->machine_state = kIOPM_ParentUpAcknowledgePowerChange_Delayed;
3029 if ( notifyAll(false) == IOPMAckImplied )
3030 {
3031 nub = priv->head_note_parent;
3032 nub->retain();
3033 all_done();
3034 nub->release();
3035 return IOPMAckImplied;
3036 }
3037 // If we are waiting for responses, execution will resume via
3038 // all_acked() or ack timeout in ParentUpAcknowledgePowerChange_Delayed.
3039 return IOPMWillAckLater;
3040 }
3041
3042
3043 //*********************************************************************************
3044 // ParentUpNotifyInterestedDriversDidChange_Delayed
3045 //
3046 // Power has settled on a power raise initiated by the parent.
3047 // Here we notify all our interested parties post-change. If they all acknowledge,
3048 // we're done with this change note, and we can start on the next one.
3049 // Otherwise we have to wait for acknowledgements and finish up later.
3050 //*********************************************************************************
3051
3052 void IOService::ParentUpNotifyInterestedDriversDidChange_Delayed ( void )
3053 {
3054 // in case they don't all ack
3055 priv->machine_state = kIOPM_ParentUpAcknowledgePowerChange_Delayed;
3056 if ( notifyAll(false) == IOPMAckImplied )
3057 {
3058 ParentUpAcknowledgePowerChange_Delayed();
3059 }
3060 // If we are waiting for responses, execution will resume via
3061 // all_acked() or ack timeout in ParentUpAcknowledgePowerChange_Delayed.
3062 }
3063
3064
3065 //*********************************************************************************
3066 // ParentUpAcknowledgePowerChange_Delayed
3067 //
3068 // All parties have acknowledged our post-change notification of a power
3069 // raising initiated by the parent. Here we acknowledge the parent.
3070 // We are done with this change note, and we can start on the next one.
3071 //*********************************************************************************
3072
3073 void IOService::ParentUpAcknowledgePowerChange_Delayed ( void )
3074 {
3075 IORegistryEntry *nub;
3076 IOService *parent;
3077
3078 nub = priv->head_note_parent;
3079 nub->retain();
3080 all_done();
3081 parent = (IOService *)nub->copyParentEntry(gIOPowerPlane);
3082 if ( parent )
3083 {
3084 parent->acknowledgePowerChange((IOService *)nub);
3085 parent->release();
3086 }
3087 nub->release();
3088 }
3089
3090
3091 //*********************************************************************************
3092 // all_done
3093 //
3094 // A power change is complete, and the used post-change note is at
3095 // the head of the queue. Remove it and set myCurrentState to the result
3096 // of the change. Start up the next change in queue.
3097 //*********************************************************************************
3098
3099 void IOService::all_done ( void )
3100 {
3101 unsigned long previous_state;
3102 IORegistryEntry *nub;
3103 IOService *parent;
3104
3105 priv->machine_state = kIOPM_Finished;
3106
3107 // our power change
3108 if ( priv->head_note_flags & IOPMWeInitiated )
3109 {
3110 // could our driver switch to the new state?
3111 if ( !( priv->head_note_flags & IOPMNotDone) )
3112 {
3113 // yes, did power raise?
3114 if ( pm_vars->myCurrentState < priv->head_note_state )
3115 {
3116 // yes, inform clients and apps
3117 tellChangeUp (priv->head_note_state);
3118 } else {
3119 // no, if this lowers our
3120 if ( ! priv->we_are_root )
3121 {
3122 // power requirements, tell the parent
3123 ask_parent(priv->head_note_state);
3124 }
3125 }
3126 previous_state = pm_vars->myCurrentState;
3127 // either way
3128 pm_vars->myCurrentState = priv->head_note_state;
3129 priv->imminentState = pm_vars->myCurrentState;
3130 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogChangeDone,(unsigned long)pm_vars->myCurrentState,0);
3131 // inform subclass policy-maker
3132 powerChangeDone(previous_state);
3133 }
3134 }
3135
3136 // parent's power change
3137 if ( priv->head_note_flags & IOPMParentInitiated)
3138 {
3139 if ( ((priv->head_note_flags & IOPMDomainWillChange) && (pm_vars->myCurrentState >= priv->head_note_state)) ||
3140 ((priv->head_note_flags & IOPMDomainDidChange) && (pm_vars->myCurrentState < priv->head_note_state)) )
3141 {
3142 // did power raise?
3143 if ( pm_vars->myCurrentState < priv->head_note_state )
3144 {
3145 // yes, inform clients and apps
3146 tellChangeUp (priv->head_note_state);
3147 }
3148 // either way
3149 previous_state = pm_vars->myCurrentState;
3150 pm_vars->myCurrentState = priv->head_note_state;
3151 priv->imminentState = pm_vars->myCurrentState;
3152 pm_vars->maxCapability = pm_vars->theControllingDriver->maxCapabilityForDomainState(priv->head_note_domainState);
3153
3154 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogChangeDone,(unsigned long)pm_vars->myCurrentState,0);
3155 // inform subclass policy-maker
3156 powerChangeDone(previous_state);
3157 }
3158 }
3159
3160 IOLockLock(priv->queue_lock);
3161 // we're done with this
3162 priv->changeList->releaseHeadChangeNote();
3163
3164 // start next one in queue
3165 priv->head_note = priv->changeList->currentChange();
3166 if ( priv->head_note != -1 )
3167 {
3168
3169 IOLockUnlock(priv->queue_lock);
3170 if (priv->changeList->changeNote[priv->head_note].flags & IOPMWeInitiated )
3171 {
3172 start_our_change(priv->head_note);
3173 } else {
3174 nub = priv->changeList->changeNote[priv->head_note].parent;
3175 if ( start_parent_change(priv->head_note) == IOPMAckImplied )
3176 {
3177 parent = (IOService *)nub->copyParentEntry(gIOPowerPlane);
3178 if ( parent )
3179 {
3180 parent->acknowledgePowerChange((IOService *)nub);
3181 parent->release();
3182 }
3183 }
3184 }
3185 } else {
3186 IOLockUnlock(priv->queue_lock);
3187 }
3188 }
3189
3190
3191
3192 //*********************************************************************************
3193 // all_acked
3194 //
3195 // A driver or child has acknowledged our notification of an upcoming power
3196 // change, and this acknowledgement is the last one pending
3197 // before we change power or after changing power.
3198 //
3199 //*********************************************************************************
3200
3201 void IOService::all_acked ( void )
3202 {
3203 getPMRootDomain()->getPMArbiter()->allAckedOccurred(this);
3204 return;
3205 }
3206
3207
3208 void IOService::all_acked_threaded ( void )
3209 {
3210 switch (priv->machine_state) {
3211 case kIOPM_OurChangeSetPowerState:
3212 OurChangeSetPowerState();
3213 break;
3214 case kIOPM_OurChangeFinish:
3215 OurChangeFinish();
3216 break;
3217 case kIOPM_ParentDownSetPowerState_Delayed:
3218 ParentDownSetPowerState_Delayed();
3219 break;
3220 case kIOPM_ParentDownAcknowledgeChange_Delayed:
3221 ParentDownAcknowledgeChange_Delayed();
3222 break;
3223 case kIOPM_ParentUpSetPowerState_Delayed:
3224 ParentUpSetPowerState_Delayed();
3225 break;
3226 case kIOPM_ParentUpAcknowledgePowerChange_Delayed:
3227 ParentUpAcknowledgePowerChange_Delayed();
3228 break;
3229 }
3230 }
3231
3232 //*********************************************************************************
3233 // settleTimerExpired
3234 //
3235 // Power has settled after our last change. Notify interested parties that
3236 // there is a new power state.
3237 //*********************************************************************************
3238
3239 void IOService::settleTimerExpired ( void )
3240 {
3241 if ( ! initialized )
3242 {
3243 // we're unloading
3244 return;
3245 }
3246
3247 switch (priv->machine_state) {
3248 case kIOPM_OurChangeNotifyInterestedDriversDidChange:
3249 OurChangeNotifyInterestedDriversDidChange();
3250 break;
3251 case kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed:
3252 ParentDownNotifyDidChangeAndAcknowledgeChange_Delayed();
3253 break;
3254 case kIOPM_ParentUpNotifyInterestedDriversDidChange_Delayed:
3255 ParentUpNotifyInterestedDriversDidChange_Delayed();
3256 break;
3257 }
3258 }
3259
3260
3261 //*********************************************************************************
3262 // compute_settle_time
3263 //
3264 // Compute the power-settling delay in microseconds for the
3265 // change from myCurrentState to head_note_state.
3266 //*********************************************************************************
3267
3268 unsigned long IOService::compute_settle_time ( void )
3269 {
3270 unsigned long totalTime;
3271 unsigned long i;
3272
3273 // compute total time to attain the new state
3274 totalTime = 0;
3275 i = pm_vars->myCurrentState;
3276
3277 // we're lowering power
3278 if ( priv->head_note_state < pm_vars->myCurrentState )
3279 {
3280 while ( i > priv->head_note_state )
3281 {
3282 totalTime += pm_vars->thePowerStates[i].settleDownTime;
3283 i--;
3284 }
3285 }
3286
3287 // we're raising power
3288 if ( priv->head_note_state > pm_vars->myCurrentState )
3289 {
3290 while ( i < priv->head_note_state )
3291 {
3292 totalTime += pm_vars->thePowerStates[i+1].settleUpTime;
3293 i++;
3294 }
3295 }
3296
3297 return totalTime;
3298 }
3299
3300
3301 //*********************************************************************************
3302 // startSettleTimer
3303 //
3304 // Enter with a power-settling delay in microseconds and start a nano-second
3305 // timer for that delay.
3306 //*********************************************************************************
3307
3308 IOReturn IOService::startSettleTimer ( unsigned long delay )
3309 {
3310 AbsoluteTime deadline;
3311
3312 clock_interval_to_deadline(delay, kMicrosecondScale, &deadline);
3313
3314 thread_call_enter_delayed(priv->settleTimer, deadline);
3315
3316 return IOPMNoErr;
3317 }
3318
3319 //*********************************************************************************
3320 // ack_timer_ticked
3321 //
3322 // The acknowledgement timeout periodic timer has ticked.
3323 // If we are awaiting acks for a power change notification,
3324 // we decrement the timer word of each interested driver which hasn't acked.
3325 // If a timer word becomes zero, we pretend the driver aknowledged.
3326 // If we are waiting for the controlling driver to change the power
3327 // state of the hardware, we decrement its timer word, and if it becomes
3328 // zero, we pretend the driver acknowledged.
3329 //*********************************************************************************
3330
3331 void IOService::ack_timer_ticked ( void )
3332 {
3333 IOPMinformee * nextObject;
3334
3335 if ( ! initialized )
3336 {
3337 // we're unloading
3338 return;
3339 }
3340
3341 if (! acquire_lock() )
3342 {
3343 return;
3344 }
3345
3346 switch (priv->machine_state) {
3347 case kIOPM_OurChangeWaitForPowerSettle:
3348 case kIOPM_ParentDownWaitForPowerSettle_Delayed:
3349 case kIOPM_ParentUpWaitForSettleTime_Delayed:
3350 // are we waiting for our driver to make its change?
3351 if ( priv->driver_timer != 0 ) {
3352 // yes, tick once
3353 priv->driver_timer -= 1;
3354 // it's tardy, we'll go on without it
3355 if ( priv->driver_timer == 0 )
3356 {
3357 IOUnlock(priv->our_lock);
3358 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogCtrlDriverTardy,0,0);
3359 driver_acked();
3360 } else {
3361 // still waiting, set timer again
3362 start_ack_timer();
3363 IOUnlock(priv->our_lock);
3364 }
3365 }
3366 else {
3367 IOUnlock(priv->our_lock);
3368 }
3369 break;
3370
3371 case kIOPM_OurChangeSetPowerState:
3372 case kIOPM_OurChangeFinish:
3373 case kIOPM_ParentDownSetPowerState_Delayed:
3374 case kIOPM_ParentDownAcknowledgeChange_Delayed:
3375 case kIOPM_ParentUpSetPowerState_Delayed:
3376 case kIOPM_ParentUpAcknowledgePowerChange_Delayed:
3377 // are we waiting for interested parties to acknowledge?
3378 if (priv->head_note_pendingAcks != 0 )
3379 {
3380 // yes, go through the list of interested drivers
3381 nextObject = priv->interestedDrivers->firstInList();
3382 // and check each one
3383 while ( nextObject != NULL )
3384 {
3385 if ( nextObject->timer > 0 )
3386 {
3387 nextObject->timer -= 1;
3388 // this one should have acked by now
3389 if ( nextObject->timer == 0 )
3390 {
3391 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogIntDriverTardy,0,0);
3392 //kprintf("interested driver tardy: %s\n",nextObject->whatObject->getName());
3393 OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
3394 }
3395 }
3396 nextObject = priv->interestedDrivers->nextInList(nextObject);
3397 }
3398
3399 // is that the last?
3400 if ( priv->head_note_pendingAcks == 0 )
3401 {
3402 IOUnlock(priv->our_lock);
3403 // yes, we can continue
3404 all_acked();
3405 } else {
3406 // no, set timer again
3407 start_ack_timer();
3408 IOUnlock(priv->our_lock);
3409 }
3410 } else {
3411 IOUnlock(priv->our_lock);
3412 }
3413 break;
3414
3415 // apps didn't respond to parent-down notification
3416 case kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate:
3417 IOUnlock(priv->our_lock);
3418 IOLockLock(priv->flags_lock);
3419 if (pm_vars->responseFlags)
3420 {
3421 // get rid of this stuff
3422 pm_vars->responseFlags->release();
3423 pm_vars->responseFlags = NULL;
3424 }
3425 IOLockUnlock(priv->flags_lock);
3426 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogClientTardy,0,5);
3427 // carry on with the change
3428 ParentDownTellPriorityClientsPowerDown_Delayed();
3429 break;
3430
3431 case kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed:
3432 IOUnlock(priv->our_lock);
3433 IOLockLock(priv->flags_lock);
3434 if (pm_vars->responseFlags)
3435 {
3436 // get rid of this stuff
3437 pm_vars->responseFlags->release();
3438 pm_vars->responseFlags = NULL;
3439 }
3440 IOLockUnlock(priv->flags_lock);
3441 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogClientTardy,0,1);
3442 // carry on with the change
3443 ParentDownNotifyInterestedDriversWillChange_Delayed();
3444 break;
3445
3446 case kIOPM_OurChangeTellClientsPowerDown:
3447 // apps didn't respond to our power-down request
3448 IOUnlock(priv->our_lock);
3449 IOLockLock(priv->flags_lock);
3450 if (pm_vars->responseFlags)
3451 {
3452 // get rid of this stuff
3453 pm_vars->responseFlags->release();
3454 pm_vars->responseFlags = NULL;
3455 }
3456 IOLockUnlock(priv->flags_lock);
3457 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogClientTardy,0,2);
3458 // rescind the request
3459 tellNoChangeDown(priv->head_note_state);
3460 // mark the change note un-actioned
3461 priv->head_note_flags |= IOPMNotDone;
3462 // and we're done
3463 all_done();
3464 break;
3465
3466 case kIOPM_OurChangeTellPriorityClientsPowerDown:
3467 // clients didn't respond to our power-down note
3468 IOUnlock(priv->our_lock);
3469 IOLockLock(priv->flags_lock);
3470 if (pm_vars->responseFlags)
3471 {
3472 // get rid of this stuff
3473 pm_vars->responseFlags->release();
3474 pm_vars->responseFlags = NULL;
3475 }
3476 IOLockUnlock(priv->flags_lock);
3477 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogClientTardy,0,4);
3478 // carry on with the change
3479 OurChangeTellPriorityClientsPowerDown();
3480 break;
3481
3482 case kIOPM_OurChangeNotifyInterestedDriversWillChange:
3483 // apps didn't respond to our power-down notification
3484 IOUnlock(priv->our_lock);
3485 IOLockLock(priv->flags_lock);
3486 if (pm_vars->responseFlags)
3487 {
3488 // get rid of this stuff
3489 pm_vars->responseFlags->release();
3490 pm_vars->responseFlags = NULL;
3491 }
3492 IOLockUnlock(priv->flags_lock);
3493 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogClientTardy,0,3);
3494 // carry on with the change
3495 OurChangeNotifyInterestedDriversWillChange();
3496 break;
3497
3498 default:
3499 // not waiting for acks
3500 IOUnlock(priv->our_lock);
3501 break;
3502 }
3503 }
3504
3505
3506 //*********************************************************************************
3507 // start_ack_timer
3508 //
3509 //*********************************************************************************
3510
3511 void IOService::start_ack_timer ( void )
3512 {
3513 AbsoluteTime deadline;
3514
3515 clock_interval_to_deadline(ACK_TIMER_PERIOD, kNanosecondScale, &deadline);
3516
3517 thread_call_enter_delayed(priv->ackTimer, deadline);
3518 }
3519
3520
3521 //*********************************************************************************
3522 // stop_ack_timer
3523 //
3524 //*********************************************************************************
3525
3526 void IOService::stop_ack_timer ( void )
3527 {
3528 thread_call_cancel(priv->ackTimer);
3529 }
3530
3531
3532 //*********************************************************************************
3533 // c-language timer expiration functions
3534 //
3535 //*********************************************************************************
3536
3537 static void ack_timer_expired ( thread_call_param_t us)
3538 {
3539 ((IOService *)us)->ack_timer_ticked();
3540 }
3541
3542
3543 static void settle_timer_expired ( thread_call_param_t us)
3544 {
3545 ((IOService *)us)->settleTimerExpired();
3546 }
3547
3548
3549 //*********************************************************************************
3550 // add_child_to_active_change
3551 //
3552 // A child has just registered with us. If there is
3553 // currently a change in progress, get the new party involved: if we
3554 // have notified all parties and are waiting for acks, notify the new
3555 // party.
3556 //*********************************************************************************
3557
3558 IOReturn IOService::add_child_to_active_change ( IOPowerConnection * newObject )
3559 {
3560 if (! acquire_lock() )
3561 {
3562 return IOPMNoErr;
3563 }
3564
3565 switch (priv->machine_state)
3566 {
3567 case kIOPM_OurChangeSetPowerState:
3568 case kIOPM_ParentDownSetPowerState_Delayed:
3569 case kIOPM_ParentUpSetPowerState_Delayed:
3570 // one for this child and one to prevent
3571 OSAddAtomic(2, (SInt32*)&priv->head_note_pendingAcks);
3572 // incoming acks from changing our state
3573 IOUnlock(priv->our_lock);
3574 notifyChild(newObject, true);
3575 if (! acquire_lock() )
3576 {
3577 // put it back
3578 OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
3579 return IOPMNoErr;
3580 }
3581 // are we still waiting for acks?
3582 OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
3583 if ( priv->head_note_pendingAcks == 0 )
3584 {
3585 // no, stop the timer
3586 stop_ack_timer();
3587 IOUnlock(priv->our_lock);
3588
3589 // and now we can continue
3590 all_acked();
3591 return IOPMNoErr;
3592 }
3593 break;
3594 case kIOPM_OurChangeFinish:
3595 case kIOPM_ParentDownAcknowledgeChange_Delayed:
3596 case kIOPM_ParentUpAcknowledgePowerChange_Delayed:
3597 // one for this child and one to prevent
3598 OSAddAtomic(2, (SInt32*)&priv->head_note_pendingAcks);
3599 // incoming acks from changing our state
3600 IOUnlock(priv->our_lock);
3601 notifyChild(newObject, false);
3602 if (! acquire_lock() )
3603 {
3604 // put it back
3605 OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
3606 return IOPMNoErr;
3607 }
3608 // are we still waiting for acks?
3609 OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
3610 if ( priv->head_note_pendingAcks == 0 )
3611 {
3612 // no, stop the timer
3613 stop_ack_timer();
3614 IOUnlock(priv->our_lock);
3615
3616 // and now we can continue
3617 all_acked();
3618 return IOPMNoErr;
3619 }
3620 break;
3621 }
3622 IOUnlock(priv->our_lock);
3623 return IOPMNoErr;
3624 }
3625
3626
3627 //*********************************************************************************
3628 // add_driver_to_active_change
3629 //
3630 // An interested driver has just registered with us. If there is
3631 // currently a change in progress, get the new party involved: if we
3632 // have notified all parties and are waiting for acks, notify the new
3633 // party.
3634 //*********************************************************************************
3635
3636 IOReturn IOService::add_driver_to_active_change ( IOPMinformee * newObject )
3637 {
3638 if (! acquire_lock() )
3639 {
3640 return IOPMNoErr;
3641 }
3642
3643 switch (priv->machine_state) {
3644 case kIOPM_OurChangeSetPowerState:
3645 case kIOPM_ParentDownSetPowerState_Delayed:
3646 case kIOPM_ParentUpSetPowerState_Delayed:
3647 // one for this driver and one to prevent
3648 OSAddAtomic(2, (SInt32*)&priv->head_note_pendingAcks);
3649 // incoming acks from changing our state
3650 IOUnlock(priv->our_lock);
3651 // inform the driver
3652 inform(newObject, true);
3653 if (! acquire_lock() )
3654 {
3655 // put it back
3656 OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
3657 return IOPMNoErr;
3658 }
3659 // are we still waiting for acks?
3660 OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
3661 if ( priv->head_note_pendingAcks == 0 )
3662 {
3663 // no, stop the timer
3664 stop_ack_timer();
3665 IOUnlock(priv->our_lock);
3666
3667 // and now we can continue
3668 all_acked();
3669 return IOPMNoErr;
3670 }
3671 break;
3672 case kIOPM_OurChangeFinish:
3673 case kIOPM_ParentDownAcknowledgeChange_Delayed:
3674 case kIOPM_ParentUpAcknowledgePowerChange_Delayed:
3675 // one for this driver and one to prevent
3676 OSAddAtomic(2, (SInt32*)&priv->head_note_pendingAcks);
3677 // incoming acks from changing our state
3678 IOUnlock(priv->our_lock);
3679 // inform the driver
3680 inform(newObject, false);
3681 if (! acquire_lock() ) {
3682 // put it back
3683 OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
3684 return IOPMNoErr;
3685 }
3686 // are we still waiting for acks?
3687 OSAddAtomic(-1, (SInt32*)&priv->head_note_pendingAcks);
3688 if ( priv->head_note_pendingAcks == 0 ) {
3689 // no, stop the timer
3690 stop_ack_timer();
3691 IOUnlock(priv->our_lock);
3692
3693 // and now we can continue
3694 all_acked();
3695 return IOPMNoErr;
3696 }
3697 break;
3698 }
3699 IOUnlock(priv->our_lock);
3700 return IOPMNoErr;
3701 }
3702
3703
3704 //*********************************************************************************
3705 // start_parent_change
3706 //
3707 // Here we begin the processing of a change note initiated by our parent
3708 // which is at the head of the queue.
3709 //
3710 // It is possible for the change to be processed to completion and removed from the queue.
3711 // There are several possible interruptions to the processing, though, and they are:
3712 // we may have to wait for interested parties to acknowledge our pre-change notification,
3713 // we may have to wait for our controlling driver to change the hardware power state,
3714 // there may be a settling time after changing the hardware power state,
3715 // we may have to wait for interested parties to acknowledge our post-change notification,
3716 // we may have to wait for the acknowledgement timer expiration to substitute for the
3717 // acknowledgement from a failing driver.
3718 //*********************************************************************************
3719
3720 IOReturn IOService::start_parent_change ( unsigned long queue_head )
3721 {
3722 priv->head_note = queue_head;
3723 priv->head_note_flags = priv-> changeList->changeNote[priv->head_note].flags;
3724 priv->head_note_state = priv->changeList->changeNote[priv->head_note].newStateNumber;
3725 priv->imminentState = priv->head_note_state;
3726 priv->head_note_outputFlags = priv->changeList->changeNote[priv->head_note].outputPowerCharacter;
3727 priv->head_note_domainState = priv->changeList->changeNote[priv->head_note].domainState;
3728 priv->head_note_parent = priv->changeList->changeNote[priv->head_note].parent;
3729 priv->head_note_capabilityFlags = priv->changeList->changeNote[priv->head_note].capabilityFlags;
3730
3731 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogStartParentChange,
3732 (unsigned long)priv->head_note_state,(unsigned long)pm_vars->myCurrentState);
3733
3734 // if we need something and haven't told the parent, do so
3735 ask_parent( priv->ourDesiredPowerState);
3736
3737 // power domain is lowering
3738 if ( priv->head_note_state < pm_vars->myCurrentState )
3739 {
3740 setParentInfo(priv->changeList->changeNote[priv->head_note].singleParentState,priv->head_note_parent);
3741 priv->initial_change = false;
3742 // tell apps and kernel clients
3743 priv->machine_state = kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate;
3744
3745 // are we waiting for responses?
3746 if ( tellChangeDown1(priv->head_note_state) )
3747 {
3748 // no, notify priority clients
3749 return ParentDownTellPriorityClientsPowerDown_Immediate();
3750 }
3751 // yes
3752 return IOPMWillAckLater;
3753 }
3754
3755 // parent is raising power, we may or may not
3756 if ( priv->head_note_state > pm_vars->myCurrentState )
3757 {
3758 if ( priv->ourDesiredPowerState > pm_vars->myCurrentState )
3759 {
3760 if ( priv->ourDesiredPowerState < priv->head_note_state )
3761 {
3762 // we do, but not all the way
3763 priv->head_note_state = priv->ourDesiredPowerState;
3764 priv->imminentState = priv->head_note_state;
3765 priv->head_note_outputFlags = pm_vars->thePowerStates[priv->head_note_state].outputPowerCharacter;
3766 priv->head_note_capabilityFlags = pm_vars->thePowerStates[priv->head_note_state].capabilityFlags;
3767 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogAmendParentChange,(unsigned long)priv->head_note_state,0);
3768 }
3769 } else {
3770 // we don't
3771 priv->head_note_state = pm_vars->myCurrentState;
3772 priv->imminentState = priv->head_note_state;
3773 priv->head_note_outputFlags = pm_vars->thePowerStates[priv->head_note_state].outputPowerCharacter;
3774 priv->head_note_capabilityFlags = pm_vars->thePowerStates[priv->head_note_state].capabilityFlags;
3775 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogAmendParentChange,(unsigned long)priv->head_note_state,0);
3776 }
3777 }
3778
3779 if ( (priv->head_note_state > pm_vars->myCurrentState) &&
3780 (priv->head_note_flags & IOPMDomainDidChange) )
3781 {
3782 // changing up
3783 priv->initial_change = false;
3784 priv->machine_state = kIOPM_ParentUpSetPowerState_Delayed;
3785 if ( notifyAll(true) == IOPMAckImplied ) {
3786 return ParentUpSetPowerState_Immediate();
3787 }
3788 // they didn't all ack
3789 return IOPMWillAckLater;
3790 }
3791
3792 all_done();
3793 // a null change or power will go up
3794 return IOPMAckImplied;
3795 }
3796
3797
3798 //*********************************************************************************
3799 // start_our_change
3800 //
3801 // Here we begin the processing of a change note initiated by us
3802 // which is at the head of the queue.
3803 //
3804 // It is possible for the change to be processed to completion and removed from the queue.
3805 // There are several possible interruptions to the processing, though, and they are:
3806 // we may have to wait for interested parties to acknowledge our pre-change notification,
3807 // changes initiated by the parent will wait in the middle for powerStateDidChange,
3808 // we may have to wait for our controlling driver to change the hardware power state,
3809 // there may be a settling time after changing the hardware power state,
3810 // we may have to wait for interested parties to acknowledge our post-change notification,
3811 // we may have to wait for the acknowledgement timer expiration to substitute for the
3812 // acknowledgement from a failing driver.
3813 //*********************************************************************************
3814
3815 void IOService::start_our_change ( unsigned long queue_head )
3816 {
3817 priv->head_note = queue_head;
3818 priv->head_note_flags = priv->changeList->changeNote[priv->head_note].flags;
3819 priv->head_note_state = priv->changeList->changeNote[priv->head_note].newStateNumber;
3820 priv->imminentState = priv->head_note_state;
3821 priv->head_note_outputFlags = priv->changeList->changeNote[priv->head_note].outputPowerCharacter;
3822 priv->head_note_capabilityFlags = priv->changeList->changeNote[priv->head_note].capabilityFlags;
3823
3824 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogStartDeviceChange,
3825 (unsigned long)priv->head_note_state,(unsigned long)pm_vars->myCurrentState);
3826
3827 // can our driver switch to the new state?
3828 if ( priv->head_note_capabilityFlags & IOPMNotAttainable )
3829 {
3830 // no, ask the parent to do it then
3831 if ( ! priv->we_are_root )
3832 {
3833 ask_parent(priv->head_note_state);
3834 }
3835 // mark the change note un-actioned
3836 priv-> head_note_flags |= IOPMNotDone;
3837 // and we're done
3838 all_done();
3839 return;
3840 }
3841
3842 // is there enough power in the domain?
3843 if ( (pm_vars->maxCapability < priv->head_note_state) && (! priv->we_are_root) )
3844 {
3845 // no, ask the parent to raise it
3846 if ( ! priv->we_are_root )
3847 {
3848 ask_parent(priv->head_note_state);
3849 }
3850 // no, mark the change note un-actioned
3851 priv->head_note_flags |= IOPMNotDone;
3852 // and we're done
3853 // till the parent raises power
3854 all_done();
3855 return;
3856 }
3857
3858 if ( ! priv->initial_change )
3859 {
3860 if ( priv->head_note_state == pm_vars->myCurrentState )
3861 {
3862 // we initiated a null change; forget it
3863 all_done();
3864 return;
3865 }
3866 }
3867 priv->initial_change = false;
3868
3869 // dropping power?
3870 if ( priv->head_note_state < pm_vars->myCurrentState )
3871 {
3872 // yes, in case we have to wait for acks
3873 priv->machine_state = kIOPM_OurChangeTellClientsPowerDown;
3874 pm_vars->doNotPowerDown = false;
3875
3876 // ask apps and kernel clients if we can drop power
3877 pm_vars->outofbandparameter = kNotifyApps;
3878 if ( askChangeDown(priv->head_note_state) )
3879 {
3880 // don't have to wait, did any clients veto?
3881 if ( pm_vars->doNotPowerDown )
3882 {
3883 // yes, rescind the warning
3884 tellNoChangeDown(priv->head_note_state);
3885 // mark the change note un-actioned
3886 priv-> head_note_flags |= IOPMNotDone;
3887 // and we're done
3888 all_done();
3889 } else {
3890 // no, tell'em we're dropping power
3891 OurChangeTellClientsPowerDown();
3892 }
3893 }
3894 } else {
3895 // we are raising power
3896 if ( ! priv->we_are_root )
3897 {
3898 // if this changes our power requirement, tell the parent
3899 ask_parent(priv->head_note_state);
3900 }
3901 // in case they don't all ack
3902 priv->machine_state = kIOPM_OurChangeSetPowerState;
3903
3904 // notify interested drivers and children
3905 if ( notifyAll(true) == IOPMAckImplied )
3906 {
3907 OurChangeSetPowerState();
3908 }
3909 }
3910 }
3911
3912
3913 //*********************************************************************************
3914 // ask_parent
3915 //
3916 // Call the power domain parent to ask for a higher power state in the domain
3917 // or to suggest a lower power state.
3918 //*********************************************************************************
3919
3920 IOReturn IOService::ask_parent ( unsigned long requestedState )
3921 {
3922 OSIterator *iter;
3923 OSObject *next;
3924 IOPowerConnection *connection;
3925 IOService *parent;
3926 unsigned long ourRequest = pm_vars->thePowerStates[requestedState].inputPowerRequirement;
3927
3928 if ( pm_vars->thePowerStates[requestedState].capabilityFlags & (kIOPMChildClamp | kIOPMPreventIdleSleep) )
3929 {
3930 ourRequest |= kIOPMPreventIdleSleep;
3931 }
3932 if ( pm_vars->thePowerStates[requestedState].capabilityFlags & (kIOPMChildClamp2 | kIOPMPreventSystemSleep) )
3933 {
3934 ourRequest |= kIOPMPreventSystemSleep;
3935 }
3936
3937 // is this a new desire?
3938 if ( priv->previousRequest == ourRequest )
3939 {
3940 // no, the parent knows already, just return
3941 return IOPMNoErr;
3942 }
3943
3944 if ( priv->we_are_root )
3945 {
3946 return IOPMNoErr;
3947 }
3948 priv->previousRequest = ourRequest;
3949
3950 iter = getParentIterator(gIOPowerPlane);
3951
3952 if ( iter )
3953 {
3954 while ( (next = iter->getNextObject()) )
3955 {
3956 if ( (connection = OSDynamicCast(IOPowerConnection,next)) )
3957 {
3958 parent = (IOService *)connection->copyParentEntry(gIOPowerPlane);
3959 if ( parent ) {
3960 if ( parent->requestPowerDomainState(ourRequest,connection,IOPMLowestState)!= IOPMNoErr )
3961 {
3962 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogRequestDenied,
3963 (unsigned long)priv->previousRequest,0);
3964 }
3965 parent->release();
3966 }
3967 }
3968 }
3969 iter->release();
3970 }
3971
3972 return IOPMNoErr;
3973 }
3974
3975
3976 //*********************************************************************************
3977 // instruct_driver
3978 //
3979 // Call the controlling driver and have it change the power state of the
3980 // hardware. If it returns IOPMAckImplied, the change is complete, and
3981 // we return IOPMAckImplied. Otherwise, it will ack when the change
3982 // is done; we return IOPMWillAckLater.
3983 //*********************************************************************************
3984 IOReturn IOService::instruct_driver ( unsigned long newState )
3985 {
3986 IOReturn delay;
3987
3988 // can our driver switch to the desired state?
3989 if ( pm_vars->thePowerStates[newState].capabilityFlags & IOPMNotAttainable )
3990 {
3991 // no, so don't try
3992 return IOPMAckImplied;
3993 }
3994
3995 priv->driver_timer = -1;
3996
3997 // yes, instruct it
3998 IOLockUnlock(priv->our_lock);
3999 OUR_PMLog( kPMLogProgramHardware, (UInt32) this, newState);
4000 delay = pm_vars->theControllingDriver->setPowerState( newState,this );
4001 OUR_PMLog((UInt32) -kPMLogProgramHardware, (UInt32) this, (UInt32) delay);
4002 IOLockLock(priv->our_lock);
4003
4004 // it finished
4005 if ( delay == IOPMAckImplied )
4006 {
4007 priv->driver_timer = 0;
4008 return IOPMAckImplied;
4009 }
4010
4011 // it acked behind our back
4012 if ( priv->driver_timer == 0 )
4013 {
4014 return IOPMAckImplied;
4015 }
4016
4017 // somebody goofed
4018 if ( delay < 0 )
4019 {
4020 return IOPMAckImplied;
4021 }
4022
4023 // it didn't finish
4024 priv->driver_timer = (delay / ( ACK_TIMER_PERIOD / ns_per_us )) + 1;
4025 return IOPMWillAckLater;
4026 }
4027
4028
4029 //*********************************************************************************
4030 // acquire_lock
4031 //
4032 // We are acquiring the lock we use to protect our queue head from
4033 // simutaneous access by a thread which calls acknowledgePowerStateChange
4034 // or acknowledgeSetPowerState and the ack timer expiration thread.
4035 // Return TRUE if we acquire the lock, and the queue head didn't change
4036 // while we were acquiring the lock (and maybe blocked).
4037 // If there is no queue head, or it changes while we are blocked,
4038 // return FALSE with the lock unlocked.
4039 //*********************************************************************************
4040
4041 bool IOService::acquire_lock ( void )
4042 {
4043 long current_change_note;
4044
4045 current_change_note = priv->head_note;
4046 if ( current_change_note == -1 ) {
4047 return FALSE;
4048 }
4049
4050 IOTakeLock(priv->our_lock);
4051 if ( current_change_note == priv->head_note )
4052 {
4053 return TRUE;
4054 } else {
4055 // we blocked and something changed radically
4056 // so there's nothing to do any more
4057 IOUnlock(priv->our_lock);
4058 return FALSE;
4059 }
4060 }
4061
4062
4063 //*********************************************************************************
4064 // askChangeDown
4065 //
4066 // Ask registered applications and kernel clients if we can change to a lower
4067 // power state.
4068 //
4069 // Subclass can override this to send a different message type. Parameter is
4070 // the destination state number.
4071 //
4072 // Return true if we don't have to wait for acknowledgements
4073 //*********************************************************************************
4074
4075 bool IOService::askChangeDown ( unsigned long stateNum )
4076 {
4077 return tellClientsWithResponse(kIOMessageCanDevicePowerOff);
4078 }
4079
4080
4081 //*********************************************************************************
4082 // tellChangeDown1
4083 //
4084 // Notify registered applications and kernel clients that we are definitely
4085 // dropping power.
4086 //
4087 // Return true if we don't have to wait for acknowledgements
4088 //*********************************************************************************
4089
4090 bool IOService::tellChangeDown1 ( unsigned long stateNum )
4091 {
4092 pm_vars->outofbandparameter = kNotifyApps;
4093 return tellChangeDown(stateNum);
4094 }
4095
4096
4097 //*********************************************************************************
4098 // tellChangeDown2
4099 //
4100 // Notify priority clients that we are definitely dropping power.
4101 //
4102 // Return true if we don't have to wait for acknowledgements
4103 //*********************************************************************************
4104
4105 bool IOService::tellChangeDown2 ( unsigned long stateNum )
4106 {
4107 pm_vars->outofbandparameter = kNotifyPriority;
4108 return tellChangeDown(stateNum);
4109 }
4110
4111
4112 //*********************************************************************************
4113 // tellChangeDown
4114 //
4115 // Notify registered applications and kernel clients that we are definitely
4116 // dropping power.
4117 //
4118 // Subclass can override this to send a different message type. Parameter is
4119 // the destination state number.
4120 //
4121 // Return true if we don't have to wait for acknowledgements
4122 //*********************************************************************************
4123
4124 bool IOService::tellChangeDown ( unsigned long stateNum )
4125 {
4126 return tellClientsWithResponse(kIOMessageDeviceWillPowerOff);
4127 }
4128
4129
4130 //*********************************************************************************
4131 // tellClientsWithResponse
4132 //
4133 // Notify registered applications and kernel clients that we are definitely
4134 // dropping power.
4135 //
4136 // Return true if we don't have to wait for acknowledgements
4137 //*********************************************************************************
4138
4139 bool IOService::tellClientsWithResponse ( int messageType )
4140 {
4141 struct context theContext;
4142 AbsoluteTime deadline;
4143 OSBoolean *aBool;
4144
4145 pm_vars->responseFlags = OSArray::withCapacity( 1 );
4146 pm_vars->serialNumber += 1;
4147
4148 theContext.responseFlags = pm_vars->responseFlags;
4149 theContext.serialNumber = pm_vars->serialNumber;
4150 theContext.flags_lock = priv->flags_lock;
4151 theContext.counter = 1;
4152 theContext.msgType = messageType;
4153 theContext.us = this;
4154 theContext.maxTimeRequested = 0;
4155 theContext.stateNumber = priv->head_note_state;
4156 theContext.stateFlags = priv->head_note_capabilityFlags;
4157
4158 IOLockLock(priv->flags_lock);
4159
4160 // position zero is false to
4161 // prevent allowCancelCommon from succeeding
4162 aBool = OSBoolean::withBoolean(false);
4163 theContext.responseFlags->setObject(0,aBool);
4164 aBool->release();
4165 IOLockUnlock(priv->flags_lock);
4166
4167 switch ( pm_vars->outofbandparameter ) {
4168 case kNotifyApps:
4169 applyToInterested(gIOAppPowerStateInterest,tellAppWithResponse,(void *)&theContext);
4170 applyToInterested(gIOGeneralInterest,tellClientWithResponse,(void *)&theContext);
4171 break;
4172 case kNotifyPriority:
4173 applyToInterested(gIOPriorityPowerStateInterest,tellClientWithResponse,(void *)&theContext);
4174 break;
4175 }
4176
4177 if (! acquire_lock() )
4178 {
4179 return true;
4180 }
4181 IOLockLock(priv->flags_lock);
4182 // now fix position zero
4183 aBool = OSBoolean::withBoolean(true);
4184 theContext.responseFlags->replaceObject(0,aBool);
4185 aBool->release();
4186 IOLockUnlock(priv->flags_lock);
4187
4188 // do we have to wait for somebody?
4189 if ( ! checkForDone() )
4190 {
4191 // yes, start the ackTimer
4192 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogStartAckTimer,theContext.maxTimeRequested,0);
4193 clock_interval_to_deadline(theContext.maxTimeRequested / 1000, kMillisecondScale, &deadline);
4194
4195 thread_call_enter_delayed(priv->ackTimer, deadline);
4196
4197 IOUnlock(priv->our_lock);
4198 return false;
4199 }
4200
4201 IOUnlock(priv->our_lock);
4202 IOLockLock(priv->flags_lock);
4203
4204 // everybody responded
4205 pm_vars->responseFlags->release();
4206 pm_vars->responseFlags = NULL;
4207 IOLockUnlock(priv->flags_lock);
4208
4209 return true;
4210 }
4211
4212
4213 //*********************************************************************************
4214 // tellAppWithResponse
4215 //
4216 // We send a message to an application, and we expect a response, so we compute a
4217 // cookie we can identify the response with.
4218 //*********************************************************************************
4219 void tellAppWithResponse ( OSObject * object, void * context)
4220 {
4221 struct context *theContext = (struct context *)context;
4222 OSBoolean *aBool;
4223 IOPMprot *pm_vars = theContext->us->pm_vars;
4224
4225 if( OSDynamicCast( IOService, object) )
4226 {
4227 // Automatically 'ack' in kernel clients
4228 IOLockLock(theContext->flags_lock);
4229 aBool = OSBoolean::withBoolean(true);
4230 theContext->responseFlags->setObject(theContext->counter,aBool);
4231 aBool->release();
4232 IOLockUnlock(theContext->flags_lock);
4233
4234 const char *who = ((IOService *) object)->getName();
4235 pm_vars->thePlatform->PMLog(who,
4236 kPMLogClientAcknowledge, theContext->msgType, * (UInt32 *) object);
4237 } else {
4238 UInt32 refcon = ((theContext->serialNumber & 0xFFFF)<<16)
4239 + (theContext->counter & 0xFFFF);
4240 IOLockLock(theContext->flags_lock);
4241 aBool = OSBoolean::withBoolean(false);
4242 theContext->responseFlags->setObject(theContext->counter,aBool);
4243 aBool->release();
4244 IOLockUnlock(theContext->flags_lock);
4245
4246 OUR_PMLog(kPMLogAppNotify, theContext->msgType, refcon);
4247 theContext->us->messageClient(theContext->msgType,object,(void *)refcon);
4248 if ( theContext->maxTimeRequested < k30seconds )
4249 {
4250 theContext->maxTimeRequested = k30seconds;
4251 }
4252 }
4253 theContext->counter += 1;
4254 }
4255
4256 //*********************************************************************************
4257 // tellClientWithResponse
4258 //
4259 // We send a message to an in-kernel client, and we expect a response, so we compute a
4260 // cookie we can identify the response with.
4261 // If it doesn't understand the notification (it is not power-management savvy)
4262 // we won't wait for it to prepare for sleep. If it tells us via a return code
4263 // in the passed struct that it is currently ready, we won't wait for it to prepare.
4264 // If it tells us via the return code in the struct that it does need time, we will chill.
4265 //*********************************************************************************
4266 void tellClientWithResponse ( OSObject * object, void * context)
4267 {
4268 struct context *theContext = (struct context *)context;
4269 IOPowerStateChangeNotification notify;
4270 UInt32 refcon;
4271 IOReturn retCode;
4272 OSBoolean *aBool;
4273 OSObject *theFlag;
4274
4275 refcon = ((theContext->serialNumber & 0xFFFF)<<16) + (theContext->counter & 0xFFFF);
4276 IOLockLock(theContext->flags_lock);
4277 aBool = OSBoolean::withBoolean(false);
4278 theContext->responseFlags->setObject(theContext->counter,aBool);
4279 aBool->release();
4280 IOLockUnlock(theContext->flags_lock);
4281
4282 IOPMprot *pm_vars = theContext->us->pm_vars;
4283 if (gIOKitDebug & kIOLogPower) {
4284 OUR_PMLog(kPMLogClientNotify, refcon, (UInt32) theContext->msgType);
4285 if (OSDynamicCast(IOService, object)) {
4286 const char *who = ((IOService *) object)->getName();
4287 pm_vars->thePlatform->PMLog(who,
4288 kPMLogClientNotify, * (UInt32 *) object, (UInt32) object);
4289 } else if (OSDynamicCast(_IOServiceInterestNotifier, object)) {
4290 _IOServiceInterestNotifier *n = (_IOServiceInterestNotifier *) object;
4291 OUR_PMLog(kPMLogClientNotify, (UInt32) n->handler, 0);
4292 }
4293 }
4294
4295 notify.powerRef = (void *)refcon;
4296 notify.returnValue = 0;
4297 notify.stateNumber = theContext->stateNumber;
4298 notify.stateFlags = theContext->stateFlags;
4299 retCode = theContext->us->messageClient(theContext->msgType,object,(void *)&notify);
4300 if ( retCode == kIOReturnSuccess )
4301 {
4302 if ( notify.returnValue == 0 )
4303 {
4304 // client doesn't want time to respond
4305 IOLockLock(theContext->flags_lock);
4306 aBool = OSBoolean::withBoolean(true);
4307 // so set its flag true
4308 theContext->responseFlags->replaceObject(theContext->counter,aBool);
4309 aBool->release();
4310 IOLockUnlock(theContext->flags_lock);
4311 OUR_PMLog(kPMLogClientAcknowledge, refcon, (UInt32) object);
4312 } else {
4313 IOLockLock(theContext->flags_lock);
4314
4315 // it does want time, and it hasn't responded yet
4316 theFlag = theContext->responseFlags->getObject(theContext->counter);
4317 if ( theFlag != 0 )
4318 {
4319 if ( ((OSBoolean *)theFlag)->isFalse() )
4320 {
4321 // so note its time requirement
4322 if ( theContext->maxTimeRequested < notify.returnValue )
4323 {
4324 theContext->maxTimeRequested = notify.returnValue;
4325 }
4326 }
4327 }
4328 IOLockUnlock(theContext->flags_lock);
4329 }
4330 } else {
4331 OUR_PMLog(kPMLogClientAcknowledge, refcon, 0);
4332 // not a client of ours
4333 IOLockLock(theContext->flags_lock);
4334 // so we won't be waiting for response
4335 aBool = OSBoolean::withBoolean(true);
4336 theContext->responseFlags->replaceObject(theContext->counter,aBool);
4337 aBool->release();
4338 IOLockUnlock(theContext->flags_lock);
4339 }
4340 theContext->counter += 1;
4341 }
4342
4343
4344 //*********************************************************************************
4345 // tellNoChangeDown
4346 //
4347 // Notify registered applications and kernel clients that we are not
4348 // dropping power.
4349 //
4350 // Subclass can override this to send a different message type. Parameter is
4351 // the aborted destination state number.
4352 //*********************************************************************************
4353
4354 void IOService::tellNoChangeDown ( unsigned long )
4355 {
4356 return tellClients(kIOMessageDeviceWillNotPowerOff);
4357 }
4358
4359
4360 //*********************************************************************************
4361 // tellChangeUp
4362 //
4363 // Notify registered applications and kernel clients that we are raising power.
4364 //
4365 // Subclass can override this to send a different message type. Parameter is
4366 // the aborted destination state number.
4367 //*********************************************************************************
4368
4369 void IOService::tellChangeUp ( unsigned long )
4370 {
4371 return tellClients(kIOMessageDeviceHasPoweredOn);
4372 }
4373
4374
4375 //*********************************************************************************
4376 // tellClients
4377 //
4378 // Notify registered applications and kernel clients of something.
4379 //*********************************************************************************
4380
4381 void IOService::tellClients ( int messageType )
4382 {
4383 struct context theContext;
4384
4385 theContext.msgType = messageType;
4386 theContext.us = this;
4387 theContext.stateNumber = priv->head_note_state;
4388 theContext.stateFlags = priv->head_note_capabilityFlags;
4389
4390 applyToInterested(gIOAppPowerStateInterest,tellClient,(void *)&theContext);
4391 applyToInterested(gIOGeneralInterest,tellClient,(void *)&theContext);
4392 }
4393
4394
4395 //*********************************************************************************
4396 // tellClient
4397 //
4398 // Notify a registered application or kernel client of something.
4399 //*********************************************************************************
4400 void tellClient ( OSObject * object, void * context)
4401 {
4402 struct context *theContext = (struct context *)context;
4403 IOPowerStateChangeNotification notify;
4404
4405 notify.powerRef = (void *) 0;
4406 notify.returnValue = 0;
4407 notify.stateNumber = theContext->stateNumber;
4408 notify.stateFlags = theContext->stateFlags;
4409
4410 theContext->us->messageClient(theContext->msgType,object, &notify);
4411 }
4412
4413
4414 // **********************************************************************************
4415 // checkForDone
4416 //
4417 // **********************************************************************************
4418 bool IOService::checkForDone ( void )
4419 {
4420 int i = 0;
4421 OSObject *theFlag;
4422
4423 IOLockLock(priv->flags_lock);
4424 if ( pm_vars->responseFlags == NULL )
4425 {
4426 IOLockUnlock(priv->flags_lock);
4427 return true;
4428 }
4429
4430 for ( i = 0; ; i++ )
4431 {
4432 theFlag = pm_vars->responseFlags->getObject(i);
4433 if ( theFlag == NULL )
4434 {
4435 break;
4436 }
4437 if ( ((OSBoolean *)theFlag)->isFalse() )
4438 {
4439 IOLockUnlock(priv->flags_lock);
4440 return false;
4441 }
4442 }
4443 IOLockUnlock(priv->flags_lock);
4444 return true;
4445 }
4446
4447
4448 // **********************************************************************************
4449 // responseValid
4450 //
4451 // **********************************************************************************
4452 bool IOService::responseValid ( unsigned long x )
4453 {
4454 UInt16 serialComponent;
4455 UInt16 ordinalComponent;
4456 OSObject * theFlag;
4457 unsigned long refcon = (unsigned long)x;
4458 OSBoolean * aBool;
4459
4460 serialComponent = (refcon>>16) & 0xFFFF;
4461 ordinalComponent = refcon & 0xFFFF;
4462
4463 if ( serialComponent != pm_vars->serialNumber )
4464 {
4465 return false;
4466 }
4467
4468 IOLockLock(priv->flags_lock);
4469 if ( pm_vars->responseFlags == NULL )
4470 {
4471 IOLockUnlock(priv->flags_lock);
4472 return false;
4473 }
4474
4475 theFlag = pm_vars->responseFlags->getObject(ordinalComponent);
4476
4477 if ( theFlag == 0 )
4478 {
4479 IOLockUnlock(priv->flags_lock);
4480 return false;
4481 }
4482
4483 if ( ((OSBoolean *)theFlag)->isFalse() )
4484 {
4485 aBool = OSBoolean::withBoolean(true);
4486 pm_vars->responseFlags->replaceObject(ordinalComponent,aBool);
4487 aBool->release();
4488 }
4489
4490 IOLockUnlock(priv->flags_lock);
4491 return true;
4492 }
4493
4494
4495 // **********************************************************************************
4496 // allowPowerChange
4497 //
4498 // Our power state is about to lower, and we have notified applications
4499 // and kernel clients, and one of them has acknowledged. If this is the last to do
4500 // so, and all acknowledgements are positive, we continue with the power change.
4501 //
4502 // We serialize this processing with timer expiration with a command gate on the
4503 // power management workloop, which the timer expiration is command gated to as well.
4504 // **********************************************************************************
4505 IOReturn IOService::allowPowerChange ( unsigned long refcon )
4506 {
4507 if ( ! initialized )
4508 {
4509 // we're unloading
4510 return kIOReturnSuccess;
4511 }
4512
4513 return pm_vars->PMcommandGate->runAction(serializedAllowPowerChange,(void *)refcon);
4514 }
4515
4516
4517 IOReturn serializedAllowPowerChange ( OSObject *owner, void * refcon, void *, void *, void *)
4518 {
4519 return ((IOService *)owner)->serializedAllowPowerChange2((unsigned long)refcon);
4520 }
4521
4522 IOReturn IOService::serializedAllowPowerChange2 ( unsigned long refcon )
4523 {
4524 // response valid?
4525 if ( ! responseValid(refcon) )
4526 {
4527 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogAcknowledgeErr5,refcon,0);
4528 // no, just return
4529 return kIOReturnSuccess;
4530 }
4531 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogClientAcknowledge,refcon,0);
4532
4533 return allowCancelCommon();
4534 }
4535
4536
4537 // **********************************************************************************
4538 // cancelPowerChange
4539 //
4540 // Our power state is about to lower, and we have notified applications
4541 // and kernel clients, and one of them has vetoed the change. If this is the last
4542 // client to respond, we abandon the power change.
4543 //
4544 // We serialize this processing with timer expiration with a command gate on the
4545 // power management workloop, which the timer expiration is command gated to as well.
4546 // **********************************************************************************
4547 IOReturn IOService::cancelPowerChange ( unsigned long refcon )
4548 {
4549 if ( ! initialized )
4550 {
4551 // we're unloading
4552 return kIOReturnSuccess;
4553 }
4554
4555 return pm_vars->PMcommandGate->runAction(serializedCancelPowerChange,(void *)refcon);
4556 }
4557
4558
4559 IOReturn serializedCancelPowerChange ( OSObject *owner, void * refcon, void *, void *, void *)
4560 {
4561 return ((IOService *)owner)->serializedCancelPowerChange2((unsigned long)refcon);
4562 }
4563
4564 IOReturn IOService::serializedCancelPowerChange2 ( unsigned long refcon )
4565 {
4566 // response valid?
4567 if ( ! responseValid(refcon) )
4568 {
4569 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogAcknowledgeErr5,refcon,0);
4570 // no, just return
4571 return kIOReturnSuccess;
4572 }
4573 pm_vars->thePlatform->PMLog(pm_vars->ourName,PMlogClientCancel,refcon,0);
4574
4575 pm_vars->doNotPowerDown = true;
4576
4577 return allowCancelCommon();
4578 }
4579
4580
4581 // **********************************************************************************
4582 // allowCancelCommon
4583 //
4584 // **********************************************************************************
4585 IOReturn IOService::allowCancelCommon ( void )
4586 {
4587 if (! acquire_lock() )
4588 {
4589 return kIOReturnSuccess;
4590 }
4591
4592 // is this the last response?
4593 if ( checkForDone() )
4594 {
4595 // yes, stop the timer
4596 stop_ack_timer();
4597 IOUnlock(priv->our_lock);
4598 IOLockLock(priv->flags_lock);
4599 if ( pm_vars->responseFlags )
4600 {
4601 pm_vars->responseFlags->release();
4602 pm_vars->responseFlags = NULL;
4603 }
4604 IOLockUnlock(priv->flags_lock);
4605 switch (priv->machine_state) {
4606 case kIOPM_OurChangeTellClientsPowerDown:
4607 // our change, was it vetoed?
4608 if ( ! pm_vars->doNotPowerDown )
4609 {
4610 // no, we can continue
4611 OurChangeTellClientsPowerDown();
4612 } else {
4613 // yes, rescind the warning
4614 tellNoChangeDown(priv->head_note_state);
4615 // mark the change note un-actioned
4616 priv->head_note_flags |= IOPMNotDone;
4617
4618 // and we're done
4619 all_done();
4620 }
4621 break;
4622 case kIOPM_OurChangeTellPriorityClientsPowerDown:
4623 OurChangeTellPriorityClientsPowerDown();
4624 break;
4625 case kIOPM_OurChangeNotifyInterestedDriversWillChange:
4626 // our change, continue
4627 OurChangeNotifyInterestedDriversWillChange();
4628 break;
4629 case kIOPM_ParentDownTellPriorityClientsPowerDown_Immediate:
4630 // parent change, continue
4631 ParentDownTellPriorityClientsPowerDown_Delayed();
4632 break;
4633 case kIOPM_ParentDownNotifyInterestedDriversWillChange_Delayed:
4634 // parent change, continue
4635 ParentDownNotifyInterestedDriversWillChange_Delayed();
4636 break;
4637 }
4638 } else {
4639 // not done yet
4640 IOUnlock(priv->our_lock);
4641 }
4642
4643 return kIOReturnSuccess;
4644 }
4645
4646
4647 #if 0
4648 //*********************************************************************************
4649 // c_PM_clamp_Timer_Expired (C Func)
4650 //
4651 // Called when our clamp timer expires...we will call the object method.
4652 //*********************************************************************************
4653
4654 static void c_PM_Clamp_Timer_Expired (OSObject * client, IOTimerEventSource *)
4655 {
4656 if (client)
4657 ((IOService *)client)->PM_Clamp_Timer_Expired ();
4658 }
4659 #endif
4660
4661
4662 //*********************************************************************************
4663 // PM_Clamp_Timer_Expired
4664 //
4665 // called when clamp timer expires...set power state to 0.
4666 //*********************************************************************************
4667
4668 void IOService::PM_Clamp_Timer_Expired (void)
4669 {
4670 #if 0
4671 if ( ! initialized )
4672 {
4673 // we're unloading
4674 return;
4675 }
4676
4677 changePowerStateToPriv (0);
4678 #endif
4679 }
4680
4681 //******************************************************************************
4682 // clampPowerOn
4683 //
4684 // Set to highest available power state for a minimum of duration milliseconds
4685 //******************************************************************************
4686
4687 #define kFiveMinutesInNanoSeconds (300 * NSEC_PER_SEC)
4688
4689 void IOService::clampPowerOn (unsigned long duration)
4690 {
4691 #if 0
4692 changePowerStateToPriv (pm_vars->theNumberOfPowerStates-1);
4693
4694 if ( priv->clampTimerEventSrc == NULL ) {
4695 priv->clampTimerEventSrc = IOTimerEventSource::timerEventSource(this,
4696 c_PM_Clamp_Timer_Expired);
4697
4698 IOWorkLoop * workLoop = getPMworkloop ();
4699
4700 if ( !priv->clampTimerEventSrc || !workLoop ||
4701 ( workLoop->addEventSource( priv->clampTimerEventSrc) != kIOReturnSuccess) ) {
4702
4703 }
4704 }
4705
4706 priv->clampTimerEventSrc->setTimeout(300*USEC_PER_SEC, USEC_PER_SEC);
4707 #endif
4708 }
4709
4710 //*********************************************************************************
4711 // setPowerState
4712 //
4713 // Does nothing here. This should be implemented in a subclass driver.
4714 //*********************************************************************************
4715
4716 IOReturn IOService::setPowerState ( unsigned long powerStateOrdinal, IOService* whatDevice )
4717 {
4718 return IOPMNoErr;
4719 }
4720
4721
4722 //*********************************************************************************
4723 // maxCapabilityForDomainState
4724 //
4725 // Finds the highest power state in the array whose input power
4726 // requirement is equal to the input parameter. Where a more intelligent
4727 // decision is possible, override this in the subclassed driver.
4728 //*********************************************************************************
4729
4730 unsigned long IOService::maxCapabilityForDomainState ( IOPMPowerFlags domainState )
4731 {
4732 int i;
4733
4734 if (pm_vars->theNumberOfPowerStates == 0 )
4735 {
4736 return 0;
4737 }
4738 for ( i = (pm_vars->theNumberOfPowerStates)-1; i >= 0; i-- )
4739 {
4740 if ( (domainState & pm_vars->thePowerStates[i].inputPowerRequirement) == pm_vars->thePowerStates[i].inputPowerRequirement )
4741 {
4742 return i;
4743 }
4744 }
4745 return 0;
4746 }
4747
4748
4749 //*********************************************************************************
4750 // initialPowerStateForDomainState
4751 //
4752 // Finds the highest power state in the array whose input power
4753 // requirement is equal to the input parameter. Where a more intelligent
4754 // decision is possible, override this in the subclassed driver.
4755 //*********************************************************************************
4756
4757 unsigned long IOService::initialPowerStateForDomainState ( IOPMPowerFlags domainState )
4758 {
4759 int i;
4760
4761 if (pm_vars->theNumberOfPowerStates == 0 )
4762 {
4763 return 0;
4764 }
4765 for ( i = (pm_vars->theNumberOfPowerStates)-1; i >= 0; i-- )
4766 {
4767 if ( (domainState & pm_vars->thePowerStates[i].inputPowerRequirement) == pm_vars->thePowerStates[i].inputPowerRequirement )
4768 {
4769 return i;
4770 }
4771 }
4772 return 0;
4773 }
4774
4775
4776 //*********************************************************************************
4777 // powerStateForDomainState
4778 //
4779 // Finds the highest power state in the array whose input power
4780 // requirement is equal to the input parameter. Where a more intelligent
4781 // decision is possible, override this in the subclassed driver.
4782 //*********************************************************************************
4783
4784 unsigned long IOService::powerStateForDomainState ( IOPMPowerFlags domainState )
4785 {
4786 int i;
4787
4788 if (pm_vars->theNumberOfPowerStates == 0 )
4789 {
4790 return 0;
4791 }
4792 for ( i = (pm_vars->theNumberOfPowerStates)-1; i >= 0; i-- )
4793 {
4794 if ( (domainState & pm_vars->thePowerStates[i].inputPowerRequirement) == pm_vars->thePowerStates[i].inputPowerRequirement )
4795 {
4796 return i;
4797 }
4798 }
4799 return 0;
4800 }
4801
4802
4803 //*********************************************************************************
4804 // didYouWakeSystem
4805 //
4806 // Does nothing here. This should be implemented in a subclass driver.
4807 //*********************************************************************************
4808
4809 bool IOService::didYouWakeSystem ( void )
4810 {
4811 return false;
4812 }
4813
4814
4815 //*********************************************************************************
4816 // powerStateWillChangeTo
4817 //
4818 // Does nothing here. This should be implemented in a subclass driver.
4819 //*********************************************************************************
4820
4821 IOReturn IOService::powerStateWillChangeTo ( IOPMPowerFlags, unsigned long, IOService*)
4822 {
4823 return 0;
4824 }
4825
4826
4827 //*********************************************************************************
4828 // powerStateDidChangeTo
4829 //
4830 // Does nothing here. This should be implemented in a subclass driver.
4831 //*********************************************************************************
4832
4833 IOReturn IOService::powerStateDidChangeTo ( IOPMPowerFlags, unsigned long, IOService*)
4834 {
4835 return 0;
4836 }
4837
4838
4839 //*********************************************************************************
4840 // powerChangeDone
4841 //
4842 // Does nothing here. This should be implemented in a subclass policy-maker.
4843 //*********************************************************************************
4844
4845 void IOService::powerChangeDone ( unsigned long )
4846 {
4847 }
4848
4849
4850 //*********************************************************************************
4851 // newTemperature
4852 //
4853 // Does nothing here. This should be implemented in a subclass driver.
4854 //*********************************************************************************
4855
4856 IOReturn IOService::newTemperature ( long currentTemp, IOService * whichZone )
4857
4858 {
4859 return IOPMNoErr;
4860 }
4861
4862
4863 #undef super
4864 #define super OSObject
4865
4866 OSDefineMetaClassAndStructors(IOPMprot, OSObject)
4867 //*********************************************************************************
4868 // serialize
4869 //
4870 // Serialize protected instance variables for debug output.
4871 //*********************************************************************************
4872 bool IOPMprot::serialize(OSSerialize *s) const
4873 {
4874 OSString * theOSString;
4875 char * buffer;
4876 char * ptr;
4877 int buf_size;
4878 int i;
4879 bool rtn_code;
4880
4881 // estimate how many bytes we need to present all power states
4882 buf_size = 150 // beginning and end of string
4883 + (275 * (int)theNumberOfPowerStates) // size per state
4884 + 100; // extra room just for kicks
4885
4886 buffer = ptr = IONew(char, buf_size);
4887 if(!buffer)
4888 return false;
4889
4890 ptr += sprintf(ptr,"{ theNumberOfPowerStates = %d, ",(unsigned int)theNumberOfPowerStates);
4891
4892 if ( theNumberOfPowerStates != 0 ) {
4893 ptr += sprintf(ptr,"version %d, ",(unsigned int)thePowerStates[0].version);
4894 }
4895
4896 if ( theNumberOfPowerStates != 0 ) {
4897 for ( i = 0; i < (int)theNumberOfPowerStates; i++ ) {
4898 ptr += sprintf(ptr, "power state %d = { ",i);
4899 ptr += sprintf(ptr,"capabilityFlags %08x, ",(unsigned int)thePowerStates[i].capabilityFlags);
4900 ptr += sprintf(ptr,"outputPowerCharacter %08x, ",(unsigned int)thePowerStates[i].outputPowerCharacter);
4901 ptr += sprintf(ptr,"inputPowerRequirement %08x, ",(unsigned int)thePowerStates[i].inputPowerRequirement);
4902 ptr += sprintf(ptr,"staticPower %d, ",(unsigned int)thePowerStates[i].staticPower);
4903 ptr += sprintf(ptr,"unbudgetedPower %d, ",(unsigned int)thePowerStates[i].unbudgetedPower);
4904 ptr += sprintf(ptr,"powerToAttain %d, ",(unsigned int)thePowerStates[i].powerToAttain);
4905 ptr += sprintf(ptr,"timeToAttain %d, ",(unsigned int)thePowerStates[i].timeToAttain);
4906 ptr += sprintf(ptr,"settleUpTime %d, ",(unsigned int)thePowerStates[i].settleUpTime);
4907 ptr += sprintf(ptr,"timeToLower %d, ",(unsigned int)thePowerStates[i].timeToLower);
4908 ptr += sprintf(ptr,"settleDownTime %d, ",(unsigned int)thePowerStates[i].settleDownTime);
4909 ptr += sprintf(ptr,"powerDomainBudget %d }, ",(unsigned int)thePowerStates[i].powerDomainBudget);
4910 }
4911 }
4912
4913 ptr += sprintf(ptr,"aggressiveness = %d, ",(unsigned int)aggressiveness);
4914 ptr += sprintf(ptr,"myCurrentState = %d, ",(unsigned int)myCurrentState);
4915 ptr += sprintf(ptr,"parentsCurrentPowerFlags = %08x, ",(unsigned int)parentsCurrentPowerFlags);
4916 ptr += sprintf(ptr,"maxCapability = %d }",(unsigned int)maxCapability);
4917
4918 theOSString = OSString::withCString(buffer);
4919 rtn_code = theOSString->serialize(s);
4920 theOSString->release();
4921 IODelete(buffer, char, buf_size);
4922
4923 return rtn_code;
4924 }
4925
4926
4927 #undef super
4928 #define super OSObject
4929
4930 OSDefineMetaClassAndStructors(IOPMpriv, OSObject)
4931 //*********************************************************************************
4932 // serialize
4933 //
4934 // Serialize private instance variables for debug output.
4935 //*********************************************************************************
4936 bool IOPMpriv::serialize(OSSerialize *s) const
4937 {
4938 OSString * theOSString;
4939 bool rtn_code;
4940 char * buffer;
4941 char * ptr;
4942 IOPMinformee * nextObject;
4943
4944 buffer = ptr = IONew(char, 2000);
4945 if(!buffer)
4946 return false;
4947
4948 ptr += sprintf(ptr,"{ this object = %08x",(unsigned int)owner);
4949 if ( we_are_root ) {
4950 ptr += sprintf(ptr," (root)");
4951 }
4952 ptr += sprintf(ptr,", ");
4953
4954 nextObject = interestedDrivers->firstInList(); // display interested drivers
4955 while ( nextObject != NULL ) {
4956 ptr += sprintf(ptr,"interested driver = %08x, ",(unsigned int)nextObject->whatObject);
4957 nextObject = interestedDrivers->nextInList(nextObject);
4958 }
4959
4960 if ( machine_state != kIOPM_Finished ) {
4961 ptr += sprintf(ptr,"machine_state = %d, ",(unsigned int)machine_state);
4962 ptr += sprintf(ptr,"driver_timer = %d, ",(unsigned int)driver_timer);
4963 ptr += sprintf(ptr,"settle_time = %d, ",(unsigned int)settle_time);
4964 ptr += sprintf(ptr,"head_note_flags = %08x, ",(unsigned int)head_note_flags);
4965 ptr += sprintf(ptr,"head_note_state = %d, ",(unsigned int)head_note_state);
4966 ptr += sprintf(ptr,"head_note_outputFlags = %08x, ",(unsigned int)head_note_outputFlags);
4967 ptr += sprintf(ptr,"head_note_domainState = %08x, ",(unsigned int)head_note_domainState);
4968 ptr += sprintf(ptr,"head_note_capabilityFlags = %08x, ",(unsigned int)head_note_capabilityFlags);
4969 ptr += sprintf(ptr,"head_note_pendingAcks = %d, ",(unsigned int)head_note_pendingAcks);
4970 }
4971
4972 if ( device_overrides ) {
4973 ptr += sprintf(ptr,"device overrides, ");
4974 }
4975 ptr += sprintf(ptr,"driverDesire = %d, ",(unsigned int)driverDesire);
4976 ptr += sprintf(ptr,"deviceDesire = %d, ",(unsigned int)deviceDesire);
4977 ptr += sprintf(ptr,"ourDesiredPowerState = %d, ",(unsigned int)ourDesiredPowerState);
4978 ptr += sprintf(ptr,"previousRequest = %d }",(unsigned int)previousRequest);
4979
4980 theOSString = OSString::withCString(buffer);
4981 rtn_code = theOSString->serialize(s);
4982 theOSString->release();
4983 IODelete(buffer, char, 2000);
4984
4985 return rtn_code;
4986 }
4987