2 * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <IOKit/assert.h>
30 #include <IOKit/IOKitDebug.h>
31 #include <IOKit/IOLib.h>
32 #include <IOKit/IOMessage.h>
33 #include <IOKit/IOPlatformExpert.h>
34 #include <IOKit/IOService.h>
35 #include <IOKit/IOTimerEventSource.h>
36 #include <IOKit/IOWorkLoop.h>
37 #include <IOKit/IOCommand.h>
39 #include <IOKit/pwr_mgt/IOPMlog.h>
40 #include <IOKit/pwr_mgt/IOPMinformee.h>
41 #include <IOKit/pwr_mgt/IOPMinformeeList.h>
42 #include <IOKit/pwr_mgt/IOPowerConnection.h>
43 #include <IOKit/pwr_mgt/RootDomain.h>
47 // Required for notification instrumentation
48 #include "IOServicePrivate.h"
49 #include "IOServicePMPrivate.h"
50 #include "IOKitKernelInternal.h"
52 static void settle_timer_expired(thread_call_param_t
, thread_call_param_t
);
53 static void PM_idle_timer_expired(OSObject
*, IOTimerEventSource
*);
54 void tellAppWithResponse(OSObject
* object
, void * context
) { /*empty*/ }
55 void tellClientWithResponse(OSObject
* object
, void * context
) { /*empty*/ }
56 void tellClient(OSObject
* object
, void * context
);
57 IOReturn
serializedAllowPowerChange(OSObject
*, void *, void *, void *, void *);
59 static uint64_t computeTimeDeltaNS( const AbsoluteTime
* start
)
64 clock_get_uptime(&now
);
65 SUB_ABSOLUTETIME(&now
, start
);
66 absolutetime_to_nanoseconds(now
, &nsec
);
70 OSDefineMetaClassAndStructors(IOPMprot
, OSObject
)
72 // log setPowerStates longer than (ns):
73 #define LOG_SETPOWER_TIMES (50ULL * 1000ULL * 1000ULL)
74 // log app responses longer than (ns):
75 #define LOG_APP_RESPONSE_TIMES (100ULL * 1000ULL * 1000ULL)
77 //*********************************************************************************
79 //*********************************************************************************
81 static bool gIOPMInitialized
= false;
82 static IOItemCount gIOPMBusyCount
= 0;
83 static IOWorkLoop
* gIOPMWorkLoop
= 0;
84 static IOPMRequestQueue
* gIOPMRequestQueue
= 0;
85 static IOPMRequestQueue
* gIOPMReplyQueue
= 0;
86 static IOPMRequestQueue
* gIOPMFreeQueue
= 0;
88 //*********************************************************************************
90 //*********************************************************************************
92 #define PM_ERROR(x...) do { kprintf(x); IOLog(x); } while (false)
93 #define PM_DEBUG(x...) do { kprintf(x); } while (false)
95 #define PM_TRACE(x...) do { \
96 if (kIOLogDebugPower & gIOKitDebug) kprintf(x); } while (false)
98 #define PM_CONNECT(x...)
100 #define PM_ASSERT_IN_GATE(x) \
102 assert(gIOPMWorkLoop->inGate()); \
105 #define PM_LOCK() IOLockLock(fPMLock)
106 #define PM_UNLOCK() IOLockUnlock(fPMLock)
108 #define ns_per_us 1000
109 #define k30seconds (30*1000000)
110 #define kMinAckTimeoutTicks (10*1000000)
111 #define kIOPMTardyAckSPSKey "IOPMTardyAckSetPowerState"
112 #define kIOPMTardyAckPSCKey "IOPMTardyAckPowerStateChange"
113 #define kPwrMgtKey "IOPowerManagement"
115 #define OUR_PMLog(t, a, b) \
116 do { fPlatform->PMLog( fName, t, a, b); } while(0)
118 #define NS_TO_MS(nsec) ((int)((nsec) / 1000000ULL))
120 //*********************************************************************************
122 //*********************************************************************************
125 kIOPM_OurChangeTellClientsPowerDown
= 1,
126 kIOPM_OurChangeTellPriorityClientsPowerDown
= 2,
127 kIOPM_OurChangeNotifyInterestedDriversWillChange
= 3,
128 kIOPM_OurChangeSetPowerState
= 4,
129 kIOPM_OurChangeWaitForPowerSettle
= 5,
130 kIOPM_OurChangeNotifyInterestedDriversDidChange
= 6,
131 kIOPM_OurChangeFinish
= 7,
132 kIOPM_ParentDownTellPriorityClientsPowerDown
= 8,
133 kIOPM_ParentDownNotifyInterestedDriversWillChange
= 9,
135 kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange
= 11,
136 kIOPM_ParentDownSetPowerState
= 12,
137 kIOPM_ParentDownWaitForPowerSettle
= 13,
138 kIOPM_ParentDownAcknowledgeChange
= 14,
139 kIOPM_ParentUpSetPowerState
= 15,
141 kIOPM_ParentUpWaitForSettleTime
= 17,
142 kIOPM_ParentUpNotifyInterestedDriversDidChange
= 18,
143 kIOPM_ParentUpAcknowledgePowerChange
= 19,
145 kIOPM_DriverThreadCallDone
= 21,
146 kIOPM_NotifyChildrenDone
= 22
151 Power Management defines a few roles that drivers can play in their own,
152 and other drivers', power management. We briefly define those here.
154 Many drivers implement their policy maker and power controller within the same
155 IOService object, but that is not required.
158 * Virtual IOService PM methods a "policy maker" may implement
159 * maxCapabilityForDomainState()
160 * initialPowerStateForDomainState()
161 * powerStateForDomainState()
163 * Virtual IOService PM methods a "policy maker" may CALL
166 == Power Controller ==
167 * Virtual IOService PM methods a "power controller" may implement
170 * Virtual IOService PM methods a "power controller" may CALL
172 * registerPowerDriver()
174 =======================
175 There are two different kinds of power state changes.
176 * One is initiated by a subclassed device object which has either decided
177 to change power state, or its controlling driver has suggested it, or
178 some other driver wants to use the idle device and has asked it to become
180 * The second kind of power state change is initiated by the power domain
182 The two are handled through different code paths.
184 We maintain a queue of "change notifications," or change notes.
185 * Usually the queue is empty.
186 * When it isn't, usually there is one change note in it
187 * It's possible to have more than one power state change pending at one
188 time, so a queue is implemented.
190 * The subclass device decides it's idle and initiates a change to a lower
191 power state. This causes interested parties to be notified, but they
192 don't all acknowledge right away. This causes the change note to sit
193 in the queue until all the acks are received. During this time, the
194 device decides it isn't idle anymore and wants to raise power back up
195 again. This change can't be started, however, because the previous one
196 isn't complete yet, so the second one waits in the queue. During this
197 time, the parent decides to lower or raise the power state of the entire
198 power domain and notifies the device, and that notification goes into
199 the queue, too, and can't be actioned until the others are.
202 This is how a power change initiated by the subclass device is handled:
203 -> First, all interested parties are notified of the change via their
204 powerStateWillChangeTo method. If they all don't acknowledge via return
205 code, then we have to wait. If they do, or when they finally all
206 acknowledge via our acknowledgePowerChange method, then we can continue.
207 -> We call the controlling driver, instructing it to change to the new state
208 -> Then we wait for power to settle. If there is no settling-time, or after
210 -> we notify interested parties again, this time via their
211 powerStateDidChangeTo methods.
212 -> When they have all acked, we're done.
213 If we lowered power and don't need the power domain to be in its current power
214 state, we suggest to the parent that it lower the power domain state.
216 == PowerDomainDownInitiated ==
217 How a change to a lower power domain state initiated by the parent is handled:
218 -> First, we figure out what power state we will be in when the new domain
220 -> Then all interested parties are notified that we are moving to that new
222 -> When they have acknowledged, we call the controlling driver to assume
223 that state and we wait for power to settle.
224 -> Then we acknowledge our preparedness to our parent. When all its
225 interested parties have acknowledged,
226 -> it lowers power and then notifies its interested parties again.
227 -> When we get this call, we notify our interested parties that the power
228 state has changed, and when they have all acknowledged, we're done.
230 == PowerDomainUpInitiated ==
231 How a change to a higher power domain state initiated by the parent is handled:
232 -> We figure out what power state we will be in when the new domain state is
234 -> If it is different from our current state we acknowledge the parent.
235 -> When all the parent's interested parties have acknowledged, it raises
236 power in the domain and waits for power to settle.
237 -> Then it notifies everyone that the new state has been reached.
238 -> When we get this call, we call the controlling driver, instructing it to
239 assume the new state, and wait for power to settle.
240 -> Then we notify our interested parties. When they all acknowledge we are
243 In either of the two power domain state cases above, it is possible that we
244 will not be changing state even though the domain is.
246 * A change to a lower domain state may not affect us because we are already
247 in a low enough state,
248 * We will not take advantage of a change to a higher domain state, because
249 we have no need of the higher power. In such cases, there is nothing to
250 do but acknowledge the parent. So when the parent calls our
251 powerDomainWillChange method, and we decide that we will not be changing
252 state, we merely acknowledge the parent, via return code, and wait.
253 When the parent subsequently calls powerStateDidChange, we acknowledge again
254 via return code, and the change is complete.
256 == 4 Paths Through State Machine ==
257 Power state changes are processed in a state machine, and since there are four
258 varieties of power state changes, there are four major paths through the state
261 == 5. No Need To change ==
262 The fourth is nearly trivial. In this path, the parent is changing the domain
263 state, but we are not changing the device state. The change starts when the
264 parent calls powerDomainWillChange. All we do is acknowledge the parent. When
265 the parent calls powerStateDidChange, we acknowledge the parent again, and
268 == 1. OurChange Down == XXX gvdl
269 The first is fairly simple. It starts:
270 * when a power domain child calls requestPowerDomainState and we decide to
271 change power states to accomodate the child,
272 * or if our power-controlling driver calls changePowerStateTo,
273 * or if some other driver which is using our device calls makeUsable,
274 * or if a subclassed object calls changePowerStateToPriv.
275 These are all power changes initiated by us, not forced upon us by the parent.
277 -> We start by notifying interested parties.
278 -> If they all acknowledge via return code, we can go on to state
280 -> Otherwise, we start the ack timer and wait for the stragglers to
281 acknowlege by calling acknowledgePowerChange.
282 -> We move on to state "msSetPowerState" when all the
283 stragglers have acknowledged, or when the ack timer expires on
284 all those which didn't acknowledge.
285 In "msSetPowerState" we call the power-controlling driver to change the
286 power state of the hardware.
287 -> If it returns saying it has done so, we go on to state
288 "msWaitForPowerSettle".
289 -> Otherwise, we have to wait for it, so we set the ack timer and wait.
290 -> When it calls acknowledgeSetPowerState, or when the ack timer
292 In "msWaitForPowerSettle", we look in the power state array to see if
293 there is any settle time required when changing from our current state to the
295 -> If not, we go right away to "msNotifyInterestedDriversDidChange".
296 -> Otherwise, we set the settle timer and wait. When it expires, we move on.
297 In "msNotifyInterestedDriversDidChange" state, we notify all our
298 interested parties via their powerStateDidChange methods that we have finished
299 changing power state.
300 -> If they all acknowledge via return code, we move on to "msFinish".
301 -> Otherwise we set the ack timer and wait. When they have all
302 acknowledged, or when the ack timer has expired for those that didn't,
303 we move on to "msFinish".
304 In "msFinish" we remove the used change note from the head of the queue
305 and start the next one if one exists.
307 == 2. Parent Change Down ==
308 Start at Stage 2 of OurChange Down XXX gvdl
311 Start at Stage 4 of OurChange Down XXX gvdl
313 Note all parent requested changes need to acknowledge the power has changed to the parent when done.
316 //*********************************************************************************
317 // [public virtual] PMinit
319 // Initialize power management.
320 //*********************************************************************************
322 void IOService::PMinit ( void )
326 if ( !gIOPMInitialized
)
328 gIOPMWorkLoop
= IOWorkLoop::workLoop();
331 gIOPMRequestQueue
= IOPMRequestQueue::create(
332 this, OSMemberFunctionCast(IOPMRequestQueue::Action
,
333 this, &IOService::servicePMRequestQueue
));
335 gIOPMReplyQueue
= IOPMRequestQueue::create(
336 this, OSMemberFunctionCast(IOPMRequestQueue::Action
,
337 this, &IOService::servicePMReplyQueue
));
339 gIOPMFreeQueue
= IOPMRequestQueue::create(
340 this, OSMemberFunctionCast(IOPMRequestQueue::Action
,
341 this, &IOService::servicePMFreeQueue
));
343 if (gIOPMWorkLoop
->addEventSource(gIOPMRequestQueue
) !=
346 gIOPMRequestQueue
->release();
347 gIOPMRequestQueue
= 0;
350 if (gIOPMWorkLoop
->addEventSource(gIOPMReplyQueue
) !=
353 gIOPMReplyQueue
->release();
357 if (gIOPMWorkLoop
->addEventSource(gIOPMFreeQueue
) !=
360 gIOPMFreeQueue
->release();
365 if (gIOPMRequestQueue
&& gIOPMReplyQueue
&& gIOPMFreeQueue
)
366 gIOPMInitialized
= true;
368 if (!gIOPMInitialized
)
371 pwrMgt
= new IOServicePM
;
373 setProperty(kPwrMgtKey
, pwrMgt
);
377 fPMLock
= IOLockAlloc();
378 fInterestedDrivers
= new IOPMinformeeList
;
379 fInterestedDrivers
->initialize();
380 fDesiredPowerState
= 0;
383 fInitialChange
= true;
384 fNeedToBecomeUsable
= false;
385 fPreviousRequest
= 0;
386 fDeviceOverrides
= false;
387 fMachineState
= kIOPM_Finished
;
388 fIdleTimerEventSource
= NULL
;
389 fIdleTimerMinPowerState
= 0;
390 fActivityLock
= IOLockAlloc();
392 fStrictTreeOrder
= false;
393 fActivityTicklePowerState
= -1;
394 fControllingDriver
= NULL
;
396 fNumberOfPowerStates
= 0;
397 fCurrentPowerState
= 0;
398 fParentsCurrentPowerFlags
= 0;
401 fPlatform
= getPlatform();
402 fParentsKnowState
= false;
404 fResponseArray
= NULL
;
405 fDoNotPowerDown
= true;
406 fCurrentPowerConsumption
= kIOPMUnknown
;
408 for (unsigned int i
= 0; i
<= kMaxType
; i
++)
410 fAggressivenessValue
[i
] = 0;
411 fAggressivenessValid
[i
] = false;
414 fAckTimer
= thread_call_allocate(
415 &IOService::ack_timer_expired
, (thread_call_param_t
)this);
416 fSettleTimer
= thread_call_allocate(
417 &settle_timer_expired
, (thread_call_param_t
)this);
418 fDriverCallEntry
= thread_call_allocate(
419 (thread_call_func_t
) &IOService::pmDriverCallout
, this);
420 assert(fDriverCallEntry
);
423 IOPMprot
* prot
= new IOPMprot
;
427 prot
->ourName
= fName
;
428 prot
->thePlatform
= fPlatform
;
433 pm_vars
= (IOPMprot
*) true;
440 //*********************************************************************************
443 // Free up the data created in PMinit, if it exists.
444 //*********************************************************************************
446 void IOService::PMfree ( void )
453 assert(fMachineState
== kIOPM_Finished
);
454 assert(fInsertInterestSet
== NULL
);
455 assert(fRemoveInterestSet
== NULL
);
456 assert(fNotifyChildArray
== NULL
);
458 if ( fIdleTimerEventSource
!= NULL
) {
459 getPMworkloop()->removeEventSource(fIdleTimerEventSource
);
460 fIdleTimerEventSource
->release();
461 fIdleTimerEventSource
= NULL
;
463 if ( fSettleTimer
) {
464 thread_call_cancel(fSettleTimer
);
465 thread_call_free(fSettleTimer
);
469 thread_call_cancel(fAckTimer
);
470 thread_call_free(fAckTimer
);
473 if ( fDriverCallEntry
) {
474 thread_call_free(fDriverCallEntry
);
475 fDriverCallEntry
= NULL
;
481 if ( fActivityLock
) {
482 IOLockFree(fActivityLock
);
483 fActivityLock
= NULL
;
485 if ( fInterestedDrivers
) {
486 fInterestedDrivers
->release();
487 fInterestedDrivers
= NULL
;
489 if ( fPMWorkQueue
) {
490 getPMworkloop()->removeEventSource(fPMWorkQueue
);
491 fPMWorkQueue
->release();
494 if (fDriverCallParamSlots
&& fDriverCallParamPtr
) {
495 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
496 fDriverCallParamPtr
= 0;
497 fDriverCallParamSlots
= 0;
499 if ( fResponseArray
) {
500 fResponseArray
->release();
501 fResponseArray
= NULL
;
503 if (fPowerStates
&& fNumberOfPowerStates
) {
504 IODelete(fPowerStates
, IOPMPowerState
, fNumberOfPowerStates
);
505 fNumberOfPowerStates
= 0;
522 //*********************************************************************************
523 // [public virtual] joinPMtree
525 // A policy-maker calls its nub here when initializing, to be attached into
526 // the power management hierarchy. The default function is to call the
527 // platform expert, which knows how to do it. This method is overridden
528 // by a nub subclass which may either know how to do it, or may need to
529 // take other action.
531 // This may be the only "power management" method used in a nub,
532 // meaning it may not be initialized for power management.
533 //*********************************************************************************
535 void IOService::joinPMtree ( IOService
* driver
)
537 IOPlatformExpert
* platform
;
539 platform
= getPlatform();
540 assert(platform
!= 0);
541 platform
->PMRegisterDevice(this, driver
);
544 //*********************************************************************************
545 // [public virtual] youAreRoot
547 // Power Managment is informing us that we are the root power domain.
548 // The only difference between us and any other power domain is that
549 // we have no parent and therefore never call it.
550 //*********************************************************************************
552 IOReturn
IOService::youAreRoot ( void )
555 fParentsKnowState
= true;
556 attachToParent( getRegistryRoot(), gIOPowerPlane
);
560 //*********************************************************************************
561 // [public virtual] PMstop
563 // Immediately stop driver callouts. Schedule an async stop request to detach
565 //*********************************************************************************
567 void IOService::PMstop ( void )
569 IOPMRequest
* request
;
574 // Schedule an async PMstop request, but immediately stop any further
575 // calls to the controlling or interested drivers. This device will
576 // continue to exist in the power plane and participate in power state
577 // changes until the PMstop async request is processed.
582 PM_DEBUG("%s::PMstop() driver call busy\n", getName());
585 request
= acquirePMRequest( this, kIOPMRequestTypePMStop
);
588 PM_TRACE("[%s] %p PMstop\n", getName(), this);
589 submitPMRequest( request
);
593 //*********************************************************************************
596 // Disconnect the node from its parents and children in the Power Plane.
597 //*********************************************************************************
599 void IOService::handlePMstop ( IOPMRequest
* request
)
603 IOPowerConnection
* connection
;
604 IOService
* theChild
;
605 IOService
* theParent
;
608 PM_TRACE("[%s] %p %s start\n", getName(), this, __FUNCTION__
);
610 // remove the property
611 removeProperty(kPwrMgtKey
);
614 iter
= getParentIterator(gIOPowerPlane
);
617 while ( (next
= iter
->getNextObject()) )
619 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
621 theParent
= (IOService
*)connection
->copyParentEntry(gIOPowerPlane
);
624 theParent
->removePowerChild(connection
);
625 theParent
->release();
632 // detach IOConnections
633 detachAbove( gIOPowerPlane
);
635 // no more power state changes
636 fParentsKnowState
= false;
639 iter
= getChildIterator(gIOPowerPlane
);
642 while ( (next
= iter
->getNextObject()) )
644 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
646 theChild
= ((IOService
*)(connection
->copyChildEntry(gIOPowerPlane
)));
649 // detach nub from child
650 connection
->detachFromChild(theChild
, gIOPowerPlane
);
653 // detach us from nub
654 detachFromChild(connection
, gIOPowerPlane
);
660 // Remove all interested drivers from the list, including the power
661 // controlling driver.
663 // Usually, the controlling driver and the policy-maker functionality
664 // are implemented by the same object, and without the deregistration,
665 // the object will be holding an extra retain on itself, and cannot
668 if ( fInterestedDrivers
)
670 IOPMinformeeList
* list
= fInterestedDrivers
;
674 while ((item
= list
->firstInList()))
676 list
->removeFromList(item
->whatObject
);
681 // Tell PM_idle_timer_expiration() to ignore idle timer.
682 fIdleTimerPeriod
= 0;
685 PM_TRACE("[%s] %p %s done\n", getName(), this, __FUNCTION__
);
688 //*********************************************************************************
689 // [public virtual] addPowerChild
691 // Power Management is informing us who our children are.
692 //*********************************************************************************
694 IOReturn
IOService::addPowerChild ( IOService
* child
)
696 IOPowerConnection
* connection
= 0;
697 IOPMRequest
* requests
[3] = {0, 0, 0};
702 return kIOReturnBadArgument
;
704 if (!initialized
|| !child
->initialized
)
705 return IOPMNotYetInitialized
;
707 OUR_PMLog( kPMLogAddChild
, 0, 0 );
710 // Is this child already one of our children?
712 iter
= child
->getParentIterator( gIOPowerPlane
);
715 IORegistryEntry
* entry
;
718 while ((next
= iter
->getNextObject()))
720 if ((entry
= OSDynamicCast(IORegistryEntry
, next
)) &&
721 isChild(entry
, gIOPowerPlane
))
731 PM_DEBUG("[%s] %s (%p) is already a child\n",
732 getName(), child
->getName(), child
);
736 // Add the child to the power plane immediately, but the
737 // joining connection is marked as not ready.
738 // We want the child to appear in the power plane before
739 // returning to the caller, but don't want the caller to
740 // block on the PM work loop.
742 connection
= new IOPowerConnection
;
746 // Create a chain of PM requests to perform the bottom-half
747 // work from the PM work loop.
749 requests
[0] = acquirePMRequest(
751 /* type */ kIOPMRequestTypeAddPowerChild1
);
753 requests
[1] = acquirePMRequest(
755 /* type */ kIOPMRequestTypeAddPowerChild2
);
757 requests
[2] = acquirePMRequest(
759 /* type */ kIOPMRequestTypeAddPowerChild3
);
761 if (!requests
[0] || !requests
[1] || !requests
[2])
764 requests
[0]->setParentRequest( requests
[1] );
765 requests
[1]->setParentRequest( requests
[2] );
768 connection
->start(this);
769 connection
->setAwaitingAck(false);
770 connection
->setReadyFlag(false);
772 attachToChild( connection
, gIOPowerPlane
);
773 connection
->attachToChild( child
, gIOPowerPlane
);
775 // connection needs to be released
776 requests
[0]->fArg0
= connection
;
777 requests
[1]->fArg0
= connection
;
778 requests
[2]->fArg0
= connection
;
780 submitPMRequest( requests
, 3 );
781 return kIOReturnSuccess
;
785 if (connection
) connection
->release();
786 if (requests
[0]) releasePMRequest(requests
[0]);
787 if (requests
[1]) releasePMRequest(requests
[1]);
788 if (requests
[2]) releasePMRequest(requests
[2]);
790 // silent failure, to prevent platform drivers from adding the child
791 // to the root domain.
795 //*********************************************************************************
796 // [private] addPowerChild1
798 // Called on the power parent.
799 //*********************************************************************************
801 void IOService::addPowerChild1 ( IOPMRequest
* request
)
803 unsigned long tempDesire
= 0;
805 // Make us temporary usable before adding the child.
808 OUR_PMLog( kPMLogMakeUsable
, kPMLogMakeUsable
, fDeviceDesire
);
810 if (fControllingDriver
&& inPlane(gIOPowerPlane
) && fParentsKnowState
)
812 tempDesire
= fNumberOfPowerStates
- 1;
815 if (tempDesire
&& (fWeAreRoot
|| (fMaxCapability
>= tempDesire
)))
817 computeDesiredState( tempDesire
);
822 //*********************************************************************************
823 // [private] addPowerChild2
825 // Called on the joining child. Blocked behind addPowerChild1.
826 //*********************************************************************************
828 void IOService::addPowerChild2 ( IOPMRequest
* request
)
830 IOPowerConnection
* connection
= (IOPowerConnection
*) request
->fArg0
;
832 IOPMPowerFlags powerFlags
;
834 unsigned long powerState
;
835 unsigned long tempDesire
;
838 parent
= (IOService
*) connection
->getParentEntry(gIOPowerPlane
);
840 if (!parent
|| !inPlane(gIOPowerPlane
))
842 PM_DEBUG("[%s] addPowerChild2 not in power plane\n", getName());
846 // Parent will be waiting for us to complete this stage, safe to
847 // directly access parent's vars.
849 knowsState
= (parent
->fPowerStates
) && (parent
->fParentsKnowState
);
850 powerState
= parent
->fCurrentPowerState
;
853 powerFlags
= parent
->fPowerStates
[powerState
].outputPowerCharacter
;
857 // Set our power parent.
859 OUR_PMLog(kPMLogSetParent
, knowsState
, powerFlags
);
861 setParentInfo( powerFlags
, connection
, knowsState
);
863 connection
->setReadyFlag(true);
865 if ( fControllingDriver
&& fParentsKnowState
)
867 fMaxCapability
= fControllingDriver
->maxCapabilityForDomainState(fParentsCurrentPowerFlags
);
868 // initially change into the state we are already in
869 tempDesire
= fControllingDriver
->initialPowerStateForDomainState(fParentsCurrentPowerFlags
);
870 computeDesiredState(tempDesire
);
871 fPreviousRequest
= 0xffffffff;
876 //*********************************************************************************
877 // [private] addPowerChild3
879 // Called on the parent. Blocked behind addPowerChild2.
880 //*********************************************************************************
882 void IOService::addPowerChild3 ( IOPMRequest
* request
)
884 IOPowerConnection
* connection
= (IOPowerConnection
*) request
->fArg0
;
889 child
= (IOService
*) connection
->getChildEntry(gIOPowerPlane
);
891 if (child
&& inPlane(gIOPowerPlane
))
893 if (child
->getProperty("IOPMStrictTreeOrder"))
895 PM_DEBUG("[%s] strict ordering enforced\n", getName());
896 fStrictTreeOrder
= true;
899 for (i
= 0; i
<= kMaxType
; i
++)
901 if ( fAggressivenessValid
[i
] )
903 child
->setAggressiveness(i
, fAggressivenessValue
[i
]);
909 PM_DEBUG("[%s] addPowerChild3 not in power plane\n", getName());
912 connection
->release();
915 //*********************************************************************************
916 // [public virtual deprecated] setPowerParent
918 // Power Management is informing us who our parent is.
919 // If we have a controlling driver, find out, given our newly-informed
920 // power domain state, what state it would be in, and then tell it
921 // to assume that state.
922 //*********************************************************************************
924 IOReturn
IOService::setPowerParent (
925 IOPowerConnection
* theParent
, bool stateKnown
, IOPMPowerFlags powerFlags
)
927 return kIOReturnUnsupported
;
930 //*********************************************************************************
931 // [public virtual] removePowerChild
933 // Called on a parent whose child is being removed by PMstop().
934 //*********************************************************************************
936 IOReturn
IOService::removePowerChild ( IOPowerConnection
* theNub
)
938 IORegistryEntry
* theChild
;
941 OUR_PMLog( kPMLogRemoveChild
, 0, 0 );
945 // detach nub from child
946 theChild
= theNub
->copyChildEntry(gIOPowerPlane
);
949 theNub
->detachFromChild(theChild
, gIOPowerPlane
);
952 // detach from the nub
953 detachFromChild(theNub
, gIOPowerPlane
);
955 // Are we awaiting an ack from this child?
956 if ( theNub
->getAwaitingAck() )
958 // yes, pretend we got one
959 theNub
->setAwaitingAck(false);
960 if (fHeadNotePendingAcks
!= 0 )
962 // that's one fewer ack to worry about
963 fHeadNotePendingAcks
--;
966 if ( fHeadNotePendingAcks
== 0 )
975 // Schedule a request to re-scan child desires and clamp bits.
976 if (!fWillAdjustPowerState
)
978 IOPMRequest
* request
;
980 request
= acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState
);
983 submitPMRequest( request
);
984 fWillAdjustPowerState
= true;
991 //*********************************************************************************
992 // [public virtual] registerPowerDriver
994 // A driver has called us volunteering to control power to our device.
995 //*********************************************************************************
997 IOReturn
IOService::registerPowerDriver (
998 IOService
* powerDriver
,
999 IOPMPowerState
* powerStates
,
1000 unsigned long numberOfStates
)
1002 IOPMRequest
* request
;
1003 IOPMPowerState
* powerStatesCopy
= 0;
1006 return IOPMNotYetInitialized
;
1008 // Validate arguments.
1009 if (!powerStates
|| (numberOfStates
< 2))
1011 OUR_PMLog(kPMLogControllingDriverErr5
, numberOfStates
, 0);
1012 return kIOReturnBadArgument
;
1017 OUR_PMLog(kPMLogControllingDriverErr4
, 0, 0);
1018 return kIOReturnBadArgument
;
1021 if (powerStates
[0].version
!= kIOPMPowerStateVersion1
)
1023 OUR_PMLog(kPMLogControllingDriverErr1
, powerStates
[0].version
, 0);
1024 return kIOReturnBadArgument
;
1028 // Make a copy of the supplied power state array.
1029 powerStatesCopy
= IONew(IOPMPowerState
, numberOfStates
);
1030 if (!powerStatesCopy
)
1033 bcopy( powerStates
, powerStatesCopy
,
1034 sizeof(IOPMPowerState
) * numberOfStates
);
1036 request
= acquirePMRequest( this, kIOPMRequestTypeRegisterPowerDriver
);
1040 powerDriver
->retain();
1041 request
->fArg0
= (void *) powerDriver
;
1042 request
->fArg1
= (void *) powerStatesCopy
;
1043 request
->fArg2
= (void *) numberOfStates
;
1045 submitPMRequest( request
);
1046 return kIOReturnSuccess
;
1050 if (powerStatesCopy
)
1051 IODelete(powerStatesCopy
, IOPMPowerState
, numberOfStates
);
1052 return kIOReturnNoMemory
;
1055 //*********************************************************************************
1056 // [private] handleRegisterPowerDriver
1057 //*********************************************************************************
1059 void IOService::handleRegisterPowerDriver ( IOPMRequest
* request
)
1061 IOService
* powerDriver
= (IOService
*) request
->fArg0
;
1062 IOPMPowerState
* powerStates
= (IOPMPowerState
*) request
->fArg1
;
1063 unsigned long numberOfStates
= (unsigned long) request
->fArg2
;
1067 PM_ASSERT_IN_GATE();
1068 assert(powerStates
);
1069 assert(powerDriver
);
1070 assert(numberOfStates
> 1);
1072 if ( !fNumberOfPowerStates
)
1074 OUR_PMLog(kPMLogControllingDriver
,
1075 (unsigned long) numberOfStates
,
1076 (unsigned long) powerStates
[0].version
);
1078 fPowerStates
= powerStates
;
1079 fNumberOfPowerStates
= numberOfStates
;
1080 fControllingDriver
= powerDriver
;
1081 fCurrentCapabilityFlags
= fPowerStates
[0].capabilityFlags
;
1083 // make a mask of all the character bits we know about
1084 fOutputPowerCharacterFlags
= 0;
1085 for ( i
= 0; i
< numberOfStates
; i
++ ) {
1086 fOutputPowerCharacterFlags
|= fPowerStates
[i
].outputPowerCharacter
;
1089 // Register powerDriver as interested, unless already done.
1090 // We don't want to register the default implementation since
1091 // it does nothing. One ramification of not always registering
1092 // is the one fewer retain count held.
1094 root
= getPlatform()->getProvider();
1097 ((OSMemberFunctionCast(void (*)(void),
1098 root
, &IOService::powerStateDidChangeTo
)) !=
1099 ((OSMemberFunctionCast(void (*)(void),
1100 this, &IOService::powerStateDidChangeTo
)))) ||
1101 ((OSMemberFunctionCast(void (*)(void),
1102 root
, &IOService::powerStateWillChangeTo
)) !=
1103 ((OSMemberFunctionCast(void (*)(void),
1104 this, &IOService::powerStateWillChangeTo
)))))
1106 if (fInterestedDrivers
->findItem(powerDriver
) == NULL
)
1109 fInterestedDrivers
->appendNewInformee(powerDriver
);
1114 if ( fNeedToBecomeUsable
) {
1115 fNeedToBecomeUsable
= false;
1116 fDeviceDesire
= fNumberOfPowerStates
- 1;
1119 if ( inPlane(gIOPowerPlane
) && fParentsKnowState
)
1121 unsigned long tempDesire
;
1122 fMaxCapability
= fControllingDriver
->maxCapabilityForDomainState(fParentsCurrentPowerFlags
);
1123 // initially change into the state we are already in
1124 tempDesire
= fControllingDriver
->initialPowerStateForDomainState(fParentsCurrentPowerFlags
);
1125 computeDesiredState(tempDesire
);
1131 OUR_PMLog(kPMLogControllingDriverErr2
, numberOfStates
, 0);
1132 IODelete(powerStates
, IOPMPowerState
, numberOfStates
);
1135 powerDriver
->release();
1138 //*********************************************************************************
1139 // [public virtual] registerInterestedDriver
1141 // Add the caller to our list of interested drivers and return our current
1142 // power state. If we don't have a power-controlling driver yet, we will
1143 // call this interested driver again later when we do get a driver and find
1144 // out what the current power state of the device is.
1145 //*********************************************************************************
1147 IOPMPowerFlags
IOService::registerInterestedDriver ( IOService
* driver
)
1149 IOPMRequest
* request
;
1152 if (!initialized
|| !fInterestedDrivers
)
1153 return IOPMNotPowerManaged
;
1156 signal
= (!fInsertInterestSet
&& !fRemoveInterestSet
);
1157 if (fInsertInterestSet
== NULL
)
1158 fInsertInterestSet
= OSSet::withCapacity(4);
1159 if (fInsertInterestSet
)
1160 fInsertInterestSet
->setObject(driver
);
1165 request
= acquirePMRequest( this, kIOPMRequestTypeInterestChanged
);
1167 submitPMRequest( request
);
1170 // This return value cannot be trusted, but return a value
1171 // for those clients that care.
1173 OUR_PMLog(kPMLogInterestedDriver
, kIOPMDeviceUsable
, 2);
1174 return kIOPMDeviceUsable
;
1177 //*********************************************************************************
1178 // [public virtual] deRegisterInterestedDriver
1179 //*********************************************************************************
1181 IOReturn
IOService::deRegisterInterestedDriver ( IOService
* driver
)
1183 IOPMinformeeList
* list
;
1184 IOPMinformee
* item
;
1185 IOPMRequest
* request
;
1188 if (!initialized
|| !fInterestedDrivers
)
1189 return IOPMNotPowerManaged
;
1192 signal
= (!fRemoveInterestSet
&& !fInsertInterestSet
);
1193 if (fRemoveInterestSet
== NULL
)
1194 fRemoveInterestSet
= OSSet::withCapacity(4);
1195 if (fRemoveInterestSet
)
1197 fRemoveInterestSet
->setObject(driver
);
1199 list
= fInterestedDrivers
;
1200 item
= list
->findItem(driver
);
1201 if (item
&& item
->active
)
1203 item
->active
= false;
1205 if (fDriverCallBusy
)
1206 PM_DEBUG("%s::deRegisterInterestedDriver() driver call busy\n", getName());
1212 request
= acquirePMRequest( this, kIOPMRequestTypeInterestChanged
);
1214 submitPMRequest( request
);
1220 //*********************************************************************************
1221 // [private] handleInterestChanged
1223 // Handle interest added or removed.
1224 //*********************************************************************************
1226 void IOService::handleInterestChanged( IOPMRequest
* request
)
1229 IOPMinformee
* informee
;
1230 IOPMinformeeList
* list
= fInterestedDrivers
;
1234 if (fInsertInterestSet
)
1236 while ((driver
= (IOService
*) fInsertInterestSet
->getAnyObject()))
1238 if ((list
->findItem(driver
) == NULL
) &&
1239 (!fRemoveInterestSet
||
1240 !fRemoveInterestSet
->containsObject(driver
)))
1242 informee
= list
->appendNewInformee(driver
);
1244 fInsertInterestSet
->removeObject(driver
);
1246 fInsertInterestSet
->release();
1247 fInsertInterestSet
= 0;
1250 if (fRemoveInterestSet
)
1252 while ((driver
= (IOService
*) fRemoveInterestSet
->getAnyObject()))
1254 informee
= list
->findItem(driver
);
1257 if (fHeadNotePendingAcks
&& informee
->timer
)
1259 informee
->timer
= 0;
1260 fHeadNotePendingAcks
--;
1262 list
->removeFromList(driver
);
1264 fRemoveInterestSet
->removeObject(driver
);
1266 fRemoveInterestSet
->release();
1267 fRemoveInterestSet
= 0;
1273 //*********************************************************************************
1274 // [public virtual] acknowledgePowerChange
1276 // After we notified one of the interested drivers or a power-domain child
1277 // of an impending change in power, it has called to say it is now
1278 // prepared for the change. If this object is the last to
1279 // acknowledge this change, we take whatever action we have been waiting
1281 // That may include acknowledging to our parent. In this case, we do it
1282 // last of all to insure that this doesn't cause the parent to call us some-
1283 // where else and alter data we are relying on here (like the very existance
1284 // of a "current change note".)
1285 //*********************************************************************************
1287 IOReturn
IOService::acknowledgePowerChange ( IOService
* whichObject
)
1289 IOPMRequest
* request
;
1292 return IOPMNotYetInitialized
;
1294 return kIOReturnBadArgument
;
1296 request
= acquirePMRequest( this, kIOPMRequestTypeAckPowerChange
);
1299 PM_ERROR("%s::%s no memory\n", getName(), __FUNCTION__
);
1300 return kIOReturnNoMemory
;
1303 whichObject
->retain();
1304 request
->fArg0
= whichObject
;
1306 submitPMRequest( request
);
1310 //*********************************************************************************
1311 // [private] handleAcknowledgePowerChange
1312 //*********************************************************************************
1314 bool IOService::handleAcknowledgePowerChange ( IOPMRequest
* request
)
1316 IOPMinformee
* informee
;
1317 unsigned long childPower
= kIOPMUnknown
;
1318 IOService
* theChild
;
1319 IOService
* whichObject
;
1320 bool all_acked
= false;
1322 PM_ASSERT_IN_GATE();
1323 whichObject
= (IOService
*) request
->fArg0
;
1324 assert(whichObject
);
1326 // one of our interested drivers?
1327 informee
= fInterestedDrivers
->findItem( whichObject
);
1328 if ( informee
== NULL
)
1330 if ( !isChild(whichObject
, gIOPowerPlane
) )
1332 OUR_PMLog(kPMLogAcknowledgeErr1
, 0, 0);
1335 OUR_PMLog(kPMLogChildAcknowledge
, fHeadNotePendingAcks
, 0);
1338 OUR_PMLog(kPMLogDriverAcknowledge
, fHeadNotePendingAcks
, 0);
1341 if ( fHeadNotePendingAcks
!= 0 )
1343 assert(fPowerStates
!= NULL
);
1345 // yes, make sure we're expecting acks
1346 if ( informee
!= NULL
)
1348 // it's an interested driver
1349 // make sure we're expecting this ack
1350 if ( informee
->timer
!= 0 )
1352 #if LOG_SETPOWER_TIMES
1353 if (informee
->timer
> 0)
1355 uint64_t nsec
= computeTimeDeltaNS(&informee
->startTime
);
1356 if (nsec
> LOG_SETPOWER_TIMES
)
1357 PM_DEBUG("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) async took %d ms\n",
1358 informee
->whatObject
->getName(),
1359 (fDriverCallReason
== kDriverCallInformPreChange
) ? "Will" : "Did",
1360 informee
->whatObject
,
1361 fName
, fCurrentPowerState
, fHeadNoteState
, NS_TO_MS(nsec
));
1365 informee
->timer
= 0;
1366 // that's one fewer to worry about
1367 fHeadNotePendingAcks
--;
1369 // this driver has already acked
1370 OUR_PMLog(kPMLogAcknowledgeErr2
, 0, 0);
1374 // make sure we're expecting this ack
1375 if ( ((IOPowerConnection
*)whichObject
)->getAwaitingAck() )
1377 // that's one fewer to worry about
1378 fHeadNotePendingAcks
--;
1379 ((IOPowerConnection
*)whichObject
)->setAwaitingAck(false);
1380 theChild
= (IOService
*)whichObject
->copyChildEntry(gIOPowerPlane
);
1383 childPower
= theChild
->currentPowerConsumption();
1384 theChild
->release();
1386 if ( childPower
== kIOPMUnknown
)
1388 fPowerStates
[fHeadNoteState
].staticPower
= kIOPMUnknown
;
1390 if ( fPowerStates
[fHeadNoteState
].staticPower
!= kIOPMUnknown
)
1392 fPowerStates
[fHeadNoteState
].staticPower
+= childPower
;
1398 if ( fHeadNotePendingAcks
== 0 ) {
1399 // yes, stop the timer
1401 // and now we can continue
1405 OUR_PMLog(kPMLogAcknowledgeErr3
, 0, 0); // not expecting anybody to ack
1410 whichObject
->release();
1415 //*********************************************************************************
1416 // [public virtual] acknowledgeSetPowerState
1418 // After we instructed our controlling driver to change power states,
1419 // it has called to say it has finished doing so.
1420 // We continue to process the power state change.
1421 //*********************************************************************************
1423 IOReturn
IOService::acknowledgeSetPowerState ( void )
1425 IOPMRequest
* request
;
1428 return IOPMNotYetInitialized
;
1430 request
= acquirePMRequest( this, kIOPMRequestTypeAckSetPowerState
);
1433 PM_ERROR("%s::%s no memory\n", getName(), __FUNCTION__
);
1434 return kIOReturnNoMemory
;
1437 submitPMRequest( request
);
1438 return kIOReturnSuccess
;
1441 //*********************************************************************************
1442 // [private] adjustPowerState
1444 // Child has signaled a change - child changed it's desire, new child added,
1445 // existing child removed. Adjust our power state accordingly.
1446 //*********************************************************************************
1448 void IOService::adjustPowerState( void )
1450 PM_ASSERT_IN_GATE();
1451 if (inPlane(gIOPowerPlane
))
1453 rebuildChildClampBits();
1454 computeDesiredState();
1455 if ( fControllingDriver
&& fParentsKnowState
)
1460 PM_DEBUG("[%s] %s: not in power tree\n", getName(), __FUNCTION__
);
1463 fWillAdjustPowerState
= false;
1466 //*********************************************************************************
1467 // [public deprecated] powerDomainWillChangeTo
1469 // Called by the power-hierarchy parent notifying of a new power state
1470 // in the power domain.
1471 // We enqueue a parent power-change to our queue of power changes.
1472 // This may or may not cause us to change power, depending on what
1473 // kind of change is occuring in the domain.
1474 //*********************************************************************************
1476 IOReturn
IOService::powerDomainWillChangeTo (
1477 IOPMPowerFlags newPowerFlags
,
1478 IOPowerConnection
* whichParent
)
1481 return kIOReturnUnsupported
;
1484 //*********************************************************************************
1485 // [private] handlePowerDomainWillChangeTo
1486 //*********************************************************************************
1488 void IOService::handlePowerDomainWillChangeTo ( IOPMRequest
* request
)
1490 IOPMPowerFlags newPowerFlags
= (IOPMPowerFlags
) request
->fArg0
;
1491 IOPowerConnection
* whichParent
= (IOPowerConnection
*) request
->fArg1
;
1492 bool powerWillDrop
= (bool) request
->fArg2
;
1495 IOPowerConnection
* connection
;
1496 unsigned long newPowerState
;
1497 IOPMPowerFlags combinedPowerFlags
;
1498 bool savedParentsKnowState
;
1499 IOReturn result
= IOPMAckImplied
;
1501 PM_ASSERT_IN_GATE();
1502 OUR_PMLog(kPMLogWillChange
, newPowerFlags
, 0);
1504 if (!inPlane(gIOPowerPlane
) || !whichParent
|| !whichParent
->getAwaitingAck())
1506 PM_DEBUG("[%s] %s: not in power tree\n", getName(), __FUNCTION__
);
1510 savedParentsKnowState
= fParentsKnowState
;
1512 // Combine parents' power flags to determine our maximum state
1513 // within the new power domain
1514 combinedPowerFlags
= 0;
1516 iter
= getParentIterator(gIOPowerPlane
);
1519 while ( (next
= iter
->getNextObject()) )
1521 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
1523 if ( connection
== whichParent
)
1524 combinedPowerFlags
|= newPowerFlags
;
1526 combinedPowerFlags
|= connection
->parentCurrentPowerFlags();
1532 if ( fControllingDriver
)
1534 newPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1535 combinedPowerFlags
);
1537 result
= enqueuePowerChange(
1538 /* flags */ IOPMParentInitiated
| IOPMDomainWillChange
,
1539 /* power state */ newPowerState
,
1540 /* domain state */ combinedPowerFlags
,
1541 /* connection */ whichParent
,
1542 /* parent state */ newPowerFlags
);
1545 // If parent is dropping power, immediately update the parent's
1546 // capability flags. Any future merging of parent(s) combined
1547 // power flags should account for this power drop.
1551 setParentInfo(newPowerFlags
, whichParent
, true);
1554 // Parent is expecting an ACK from us. If we did not embark on a state
1555 // transition, when enqueuePowerChang() returns IOPMAckImplied. We are
1556 // still required to issue an ACK to our parent.
1558 if (IOPMAckImplied
== result
)
1561 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
1565 parent
->acknowledgePowerChange( whichParent
);
1570 // If the parent registers it's power driver late, then this is the
1571 // first opportunity to tell our parent about our desire.
1573 if (!savedParentsKnowState
&& fParentsKnowState
)
1575 PM_TRACE("[%s] powerDomainWillChangeTo: parentsKnowState = true\n",
1577 ask_parent( fDesiredPowerState
);
1581 // Drop the retain from notifyChild().
1582 if (whichParent
) whichParent
->release();
1585 //*********************************************************************************
1586 // [public deprecated] powerDomainDidChangeTo
1588 // Called by the power-hierarchy parent after the power state of the power domain
1589 // has settled at a new level.
1590 // We enqueue a parent power-change to our queue of power changes.
1591 // This may or may not cause us to change power, depending on what
1592 // kind of change is occuring in the domain.
1593 //*********************************************************************************
1595 IOReturn
IOService::powerDomainDidChangeTo (
1596 IOPMPowerFlags newPowerFlags
,
1597 IOPowerConnection
* whichParent
)
1600 return kIOReturnUnsupported
;
1603 //*********************************************************************************
1604 // [private] handlePowerDomainDidChangeTo
1605 //*********************************************************************************
1607 void IOService::handlePowerDomainDidChangeTo ( IOPMRequest
* request
)
1609 IOPMPowerFlags newPowerFlags
= (IOPMPowerFlags
) request
->fArg0
;
1610 IOPowerConnection
* whichParent
= (IOPowerConnection
*) request
->fArg1
;
1611 unsigned long newPowerState
;
1612 bool savedParentsKnowState
;
1613 IOReturn result
= IOPMAckImplied
;
1615 PM_ASSERT_IN_GATE();
1616 OUR_PMLog(kPMLogDidChange
, newPowerFlags
, 0);
1618 if (!inPlane(gIOPowerPlane
) || !whichParent
|| !whichParent
->getAwaitingAck())
1620 PM_DEBUG("[%s] %s: not in power tree\n", getName(), __FUNCTION__
);
1624 savedParentsKnowState
= fParentsKnowState
;
1626 setParentInfo(newPowerFlags
, whichParent
, true);
1628 if ( fControllingDriver
)
1630 newPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1631 fParentsCurrentPowerFlags
);
1633 result
= enqueuePowerChange(
1634 /* flags */ IOPMParentInitiated
| IOPMDomainDidChange
,
1635 /* power state */ newPowerState
,
1636 /* domain state */ fParentsCurrentPowerFlags
,
1637 /* connection */ whichParent
,
1638 /* parent state */ 0);
1641 // Parent is expecting an ACK from us. If we did not embark on a state
1642 // transition, when enqueuePowerChang() returns IOPMAckImplied. We are
1643 // still required to issue an ACK to our parent.
1645 if (IOPMAckImplied
== result
)
1648 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
1652 parent
->acknowledgePowerChange( whichParent
);
1657 // If the parent registers it's power driver late, then this is the
1658 // first opportunity to tell our parent about our desire.
1660 if (!savedParentsKnowState
&& fParentsKnowState
)
1662 PM_TRACE("[%s] powerDomainDidChangeTo: parentsKnowState = true\n",
1664 ask_parent( fDesiredPowerState
);
1668 // Drop the retain from notifyChild().
1669 if (whichParent
) whichParent
->release();
1672 //*********************************************************************************
1673 // [private] setParentInfo
1675 // Set our connection data for one specific parent, and then combine all the parent
1677 //*********************************************************************************
1679 void IOService::setParentInfo (
1680 IOPMPowerFlags newPowerFlags
,
1681 IOPowerConnection
* whichParent
,
1686 IOPowerConnection
* conn
;
1688 PM_ASSERT_IN_GATE();
1690 // set our connection data
1691 whichParent
->setParentCurrentPowerFlags(newPowerFlags
);
1692 whichParent
->setParentKnowsState(knowsState
);
1694 // recompute our parent info
1695 fParentsCurrentPowerFlags
= 0;
1696 fParentsKnowState
= true;
1698 iter
= getParentIterator(gIOPowerPlane
);
1701 while ( (next
= iter
->getNextObject()) )
1703 if ( (conn
= OSDynamicCast(IOPowerConnection
, next
)) )
1705 fParentsKnowState
&= conn
->parentKnowsState();
1706 fParentsCurrentPowerFlags
|= conn
->parentCurrentPowerFlags();
1713 //*********************************************************************************
1714 // [private] rebuildChildClampBits
1716 // The ChildClamp bits (kIOPMChildClamp & kIOPMChildClamp2) in our capabilityFlags
1717 // indicate that one of our children (or grandchildren or great-grandchildren ...)
1718 // doesn't support idle or system sleep in its current state. Since we don't track
1719 // the origin of each bit, every time any child changes state we have to clear
1720 // these bits and rebuild them.
1721 //*********************************************************************************
1723 void IOService::rebuildChildClampBits ( void )
1728 IOPowerConnection
* connection
;
1729 unsigned long powerState
;
1731 // A child's desires has changed. We need to rebuild the child-clamp bits in
1732 // our power state array. Start by clearing the bits in each power state.
1734 for ( i
= 0; i
< fNumberOfPowerStates
; i
++ )
1736 fPowerStates
[i
].capabilityFlags
&= ~(kIOPMChildClamp
| kIOPMChildClamp2
);
1739 // Loop through the children. When we encounter the calling child, save the
1740 // computed state as this child's desire. And set the ChildClamp bits in any
1741 // of our states that some child has clamp on.
1743 iter
= getChildIterator(gIOPowerPlane
);
1746 while ( (next
= iter
->getNextObject()) )
1748 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
1750 if (connection
->getReadyFlag() == false)
1752 PM_CONNECT("[%s] %s: connection not ready\n",
1753 getName(), __FUNCTION__
);
1757 powerState
= connection
->getDesiredDomainState();
1758 if (powerState
< fNumberOfPowerStates
)
1760 if ( connection
->getPreventIdleSleepFlag() )
1761 fPowerStates
[powerState
].capabilityFlags
|= kIOPMChildClamp
;
1762 if ( connection
->getPreventSystemSleepFlag() )
1763 fPowerStates
[powerState
].capabilityFlags
|= kIOPMChildClamp2
;
1771 //*********************************************************************************
1772 // [public virtual] requestPowerDomainState
1774 // The child of a power domain calls it parent here to request power of a certain
1776 //*********************************************************************************
1778 IOReturn
IOService::requestPowerDomainState (
1779 IOPMPowerFlags desiredState
,
1780 IOPowerConnection
* whichChild
,
1781 unsigned long specification
)
1784 unsigned long computedState
;
1785 unsigned long theDesiredState
;
1789 return IOPMNotYetInitialized
;
1791 if (gIOPMWorkLoop
->onThread() == false)
1793 PM_DEBUG("[%s] called requestPowerDomainState\n", getName());
1794 return kIOReturnSuccess
;
1797 theDesiredState
= desiredState
& ~(kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
1799 OUR_PMLog(kPMLogRequestDomain
, desiredState
, specification
);
1801 if (!isChild(whichChild
, gIOPowerPlane
))
1802 return kIOReturnNotAttached
;
1804 if (fControllingDriver
== NULL
|| !fPowerStates
)
1805 return IOPMNotYetInitialized
;
1807 child
= (IOService
*) whichChild
->getChildEntry(gIOPowerPlane
);
1810 switch (specification
) {
1811 case IOPMLowestState
:
1813 while ( i
< fNumberOfPowerStates
)
1815 if ( ( fPowerStates
[i
].outputPowerCharacter
& theDesiredState
) ==
1816 (theDesiredState
& fOutputPowerCharacterFlags
) )
1822 if ( i
>= fNumberOfPowerStates
)
1824 return IOPMNoSuchState
;
1828 case IOPMNextLowerState
:
1829 i
= fCurrentPowerState
- 1;
1830 while ( (int) i
>= 0 )
1832 if ( ( fPowerStates
[i
].outputPowerCharacter
& theDesiredState
) ==
1833 (theDesiredState
& fOutputPowerCharacterFlags
) )
1841 return IOPMNoSuchState
;
1845 case IOPMHighestState
:
1846 i
= fNumberOfPowerStates
;
1847 while ( (int) i
>= 0 )
1850 if ( ( fPowerStates
[i
].outputPowerCharacter
& theDesiredState
) ==
1851 (theDesiredState
& fOutputPowerCharacterFlags
) )
1858 return IOPMNoSuchState
;
1862 case IOPMNextHigherState
:
1863 i
= fCurrentPowerState
+ 1;
1864 while ( i
< fNumberOfPowerStates
)
1866 if ( ( fPowerStates
[i
].outputPowerCharacter
& theDesiredState
) ==
1867 (theDesiredState
& fOutputPowerCharacterFlags
) )
1873 if ( i
== fNumberOfPowerStates
)
1875 return IOPMNoSuchState
;
1880 return IOPMBadSpecification
;
1885 // Clamp removed on the initial power request from a new child.
1887 if (fClampOn
&& !whichChild
->childHasRequestedPower())
1889 PM_TRACE("[%s] %p power clamp removed (child = %p)\n",
1890 getName(), this, whichChild
);
1895 // Record the child's desires on the connection.
1897 whichChild
->setDesiredDomainState( computedState
);
1898 whichChild
->setPreventIdleSleepFlag( desiredState
& kIOPMPreventIdleSleep
);
1899 whichChild
->setPreventSystemSleepFlag( desiredState
& kIOPMPreventSystemSleep
);
1900 whichChild
->setChildHasRequestedPower();
1902 if (whichChild
->getReadyFlag() == false)
1905 // Issue a ping for us to re-evaluate all children desires and
1906 // possibly change power state.
1908 if (!fWillAdjustPowerState
&& !fDeviceOverrides
)
1910 IOPMRequest
* childRequest
;
1912 childRequest
= acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState
);
1915 submitPMRequest( childRequest
);
1916 fWillAdjustPowerState
= true;
1923 //*********************************************************************************
1924 // [public virtual] temporaryPowerClampOn
1926 // A power domain wants to clamp its power on till it has children which
1927 // will thendetermine the power domain state.
1929 // We enter the highest state until addPowerChild is called.
1930 //*********************************************************************************
1932 IOReturn
IOService::temporaryPowerClampOn ( void )
1934 IOPMRequest
* request
;
1937 return IOPMNotYetInitialized
;
1939 request
= acquirePMRequest( this, kIOPMRequestTypeTemporaryPowerClamp
);
1941 return kIOReturnNoMemory
;
1943 submitPMRequest( request
);
1947 //*********************************************************************************
1948 // [public virtual] makeUsable
1950 // Some client of our device is asking that we become usable. Although
1951 // this has not come from a subclassed device object, treat it exactly
1952 // as if it had. In this way, subsequent requests for lower power from
1953 // a subclassed device object will pre-empt this request.
1955 // We treat this as a subclass object request to switch to the
1956 // highest power state.
1957 //*********************************************************************************
1959 IOReturn
IOService::makeUsable ( void )
1961 IOPMRequest
* request
;
1964 return IOPMNotYetInitialized
;
1966 OUR_PMLog(kPMLogMakeUsable
, 0, 0);
1968 request
= acquirePMRequest( this, kIOPMRequestTypeMakeUsable
);
1970 return kIOReturnNoMemory
;
1972 submitPMRequest( request
);
1976 //*********************************************************************************
1977 // [private] handleMakeUsable
1979 // Handle a request to become usable.
1980 //*********************************************************************************
1982 void IOService::handleMakeUsable ( IOPMRequest
* request
)
1984 PM_ASSERT_IN_GATE();
1985 if ( fControllingDriver
)
1987 fDeviceDesire
= fNumberOfPowerStates
- 1;
1988 computeDesiredState();
1989 if ( inPlane(gIOPowerPlane
) && fParentsKnowState
)
1996 fNeedToBecomeUsable
= true;
2000 //*********************************************************************************
2001 // [public virtual] currentCapability
2002 //*********************************************************************************
2004 IOPMPowerFlags
IOService::currentCapability ( void )
2007 return IOPMNotPowerManaged
;
2009 return fCurrentCapabilityFlags
;
2012 //*********************************************************************************
2013 // [public virtual] changePowerStateTo
2015 // For some reason, our power-controlling driver has decided it needs to change
2016 // power state. We enqueue the power change so that appropriate parties
2017 // will be notified, and then we will instruct the driver to make the change.
2018 //*********************************************************************************
2020 IOReturn
IOService::changePowerStateTo ( unsigned long ordinal
)
2022 IOPMRequest
* request
;
2025 return IOPMNotYetInitialized
;
2027 OUR_PMLog(kPMLogChangeStateTo
, ordinal
, 0);
2029 request
= acquirePMRequest( this, kIOPMRequestTypeChangePowerStateTo
);
2031 return kIOReturnNoMemory
;
2033 request
->fArg0
= (void *) ordinal
;
2034 request
->fArg1
= (void *) false;
2036 // Avoid needless downwards power transitions by clamping power in
2037 // computeDesiredState() until the delayed request is processed.
2039 if (gIOPMWorkLoop
->inGate())
2041 fTempClampPowerState
= max(fTempClampPowerState
, ordinal
);
2043 request
->fArg1
= (void *) true;
2046 submitPMRequest( request
);
2050 //*********************************************************************************
2051 // [private] handleChangePowerStateTo
2052 //*********************************************************************************
2054 void IOService::handleChangePowerStateTo ( IOPMRequest
* request
)
2056 unsigned long ordinal
= (unsigned long) request
->fArg0
;
2058 PM_ASSERT_IN_GATE();
2061 assert(fTempClampCount
!= 0);
2062 if (fTempClampCount
)
2064 if (!fTempClampCount
)
2065 fTempClampPowerState
= 0;
2068 if ( fControllingDriver
&& (ordinal
< fNumberOfPowerStates
))
2070 fDriverDesire
= ordinal
;
2071 computeDesiredState();
2072 if ( inPlane(gIOPowerPlane
) && fParentsKnowState
)
2079 //*********************************************************************************
2080 // [public virtual] changePowerStateToPriv
2082 // For some reason, a subclassed device object has decided it needs to change
2083 // power state. We enqueue the power change so that appropriate parties
2084 // will be notified, and then we will instruct the driver to make the change.
2085 //*********************************************************************************
2087 IOReturn
IOService::changePowerStateToPriv ( unsigned long ordinal
)
2089 IOPMRequest
* request
;
2092 return IOPMNotYetInitialized
;
2094 request
= acquirePMRequest( this, kIOPMRequestTypeChangePowerStateToPriv
);
2096 return kIOReturnNoMemory
;
2098 request
->fArg0
= (void *) ordinal
;
2099 request
->fArg1
= (void *) false;
2101 // Avoid needless downwards power transitions by clamping power in
2102 // computeDesiredState() until the delayed request is processed.
2104 if (gIOPMWorkLoop
->inGate())
2106 fTempClampPowerState
= max(fTempClampPowerState
, ordinal
);
2108 request
->fArg1
= (void *) true;
2111 submitPMRequest( request
);
2115 //*********************************************************************************
2116 // [private] handleChangePowerStateToPriv
2117 //*********************************************************************************
2119 void IOService::handleChangePowerStateToPriv ( IOPMRequest
* request
)
2121 unsigned long ordinal
= (unsigned long) request
->fArg0
;
2123 PM_ASSERT_IN_GATE();
2124 OUR_PMLog(kPMLogChangeStateToPriv
, ordinal
, 0);
2127 assert(fTempClampCount
!= 0);
2128 if (fTempClampCount
)
2130 if (!fTempClampCount
)
2131 fTempClampPowerState
= 0;
2134 if ( fControllingDriver
&& (ordinal
< fNumberOfPowerStates
))
2136 fDeviceDesire
= ordinal
;
2137 computeDesiredState();
2138 if ( inPlane(gIOPowerPlane
) && fParentsKnowState
)
2145 //*********************************************************************************
2146 // [private] computeDesiredState
2147 //*********************************************************************************
2149 void IOService::computeDesiredState ( unsigned long tempDesire
)
2153 IOPowerConnection
* connection
;
2154 unsigned long newDesiredState
= 0;
2155 unsigned long childDesire
= 0;
2156 unsigned long deviceDesire
;
2159 deviceDesire
= tempDesire
;
2161 deviceDesire
= fDeviceDesire
;
2163 // If clamp is on, always override deviceDesire to max.
2165 if (fClampOn
&& fNumberOfPowerStates
)
2166 deviceDesire
= fNumberOfPowerStates
- 1;
2168 // Compute the maximum of our children's desires,
2169 // our controlling driver's desire, and the subclass device's desire.
2171 if ( !fDeviceOverrides
)
2173 iter
= getChildIterator(gIOPowerPlane
);
2176 while ( (next
= iter
->getNextObject()) )
2178 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
2180 if (connection
->getReadyFlag() == false)
2182 PM_CONNECT("[%s] %s: connection not ready\n",
2183 getName(), __FUNCTION__
);
2187 if (connection
->getDesiredDomainState() > childDesire
)
2188 childDesire
= connection
->getDesiredDomainState();
2194 fChildrenDesire
= childDesire
;
2195 newDesiredState
= max(childDesire
, fDriverDesire
);
2198 newDesiredState
= max(deviceDesire
, newDesiredState
);
2199 if (fTempClampCount
&& (fTempClampPowerState
< fNumberOfPowerStates
))
2200 newDesiredState
= max(fTempClampPowerState
, newDesiredState
);
2202 fDesiredPowerState
= newDesiredState
;
2204 // Limit check against number of power states.
2206 if (fNumberOfPowerStates
== 0)
2207 fDesiredPowerState
= 0;
2208 else if (fDesiredPowerState
>= fNumberOfPowerStates
)
2209 fDesiredPowerState
= fNumberOfPowerStates
- 1;
2211 // Restart idle timer if stopped and deviceDesire has increased.
2213 if (fDeviceDesire
&& fActivityTimerStopped
)
2215 fActivityTimerStopped
= false;
2216 start_PM_idle_timer();
2219 // Invalidate cached tickle power state when desires change, and not
2220 // due to a tickle request. This invalidation must occur before the
2221 // power state change to minimize races. We want to err on the side
2222 // of servicing more activity tickles rather than dropping one when
2223 // the device is in a low power state.
2225 if (fPMRequest
&& (fPMRequest
->getType() != kIOPMRequestTypeActivityTickle
) &&
2226 (fActivityTicklePowerState
!= -1))
2228 IOLockLock(fActivityLock
);
2229 fActivityTicklePowerState
= -1;
2230 IOLockUnlock(fActivityLock
);
2233 PM_TRACE(" NewState %ld, Child %ld, Driver %ld, Device %ld, Clamp %d (%ld)\n",
2234 fDesiredPowerState
, childDesire
, fDriverDesire
, deviceDesire
,
2235 fClampOn
, fTempClampCount
? fTempClampPowerState
: 0);
2238 //*********************************************************************************
2239 // [private] changeState
2241 // A subclass object, our controlling driver, or a power domain child
2242 // has asked for a different power state. Here we compute what new
2243 // state we should enter and enqueue the change (or start it).
2244 //*********************************************************************************
2246 IOReturn
IOService::changeState ( void )
2250 PM_ASSERT_IN_GATE();
2251 assert(inPlane(gIOPowerPlane
));
2252 assert(fParentsKnowState
);
2253 assert(fControllingDriver
);
2255 result
= enqueuePowerChange(
2256 /* flags */ IOPMWeInitiated
,
2257 /* power state */ fDesiredPowerState
,
2258 /* domain state */ 0,
2260 /* parent state */ 0);
2265 //*********************************************************************************
2266 // [public virtual] currentPowerConsumption
2268 //*********************************************************************************
2270 unsigned long IOService::currentPowerConsumption ( void )
2273 return kIOPMUnknown
;
2275 return fCurrentPowerConsumption
;
2278 //*********************************************************************************
2279 // [public virtual] getPMworkloop
2280 //*********************************************************************************
2282 IOWorkLoop
* IOService::getPMworkloop ( void )
2284 return gIOPMWorkLoop
;
2287 //*********************************************************************************
2288 // [public virtual] activityTickle
2290 // The tickle with parameter kIOPMSuperclassPolicy1 causes the activity
2291 // flag to be set, and the device state checked. If the device has been
2292 // powered down, it is powered up again.
2293 // The tickle with parameter kIOPMSubclassPolicy is ignored here and
2294 // should be intercepted by a subclass.
2295 //*********************************************************************************
2297 bool IOService::activityTickle ( unsigned long type
, unsigned long stateNumber
)
2299 IOPMRequest
* request
;
2300 bool noPowerChange
= true;
2302 if ( initialized
&& stateNumber
&& (type
== kIOPMSuperclassPolicy1
) )
2304 IOLockLock(fActivityLock
);
2306 // Record device activity for the idle timer handler.
2308 fDeviceActive
= true;
2309 clock_get_uptime(&fDeviceActiveTimestamp
);
2311 // Record the last tickle power state.
2312 // This helps to filter out redundant tickles as
2313 // this function may be called from the data path.
2315 if (fActivityTicklePowerState
< (long)stateNumber
)
2317 fActivityTicklePowerState
= stateNumber
;
2318 noPowerChange
= false;
2320 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
2323 request
->fArg0
= (void *) stateNumber
; // power state
2324 request
->fArg1
= (void *) true; // power rise
2325 submitPMRequest(request
);
2329 IOLockUnlock(fActivityLock
);
2332 // Returns false if the activityTickle might cause a transition to a
2333 // higher powered state, true otherwise.
2335 return noPowerChange
;
2338 //*********************************************************************************
2339 // [public virtual] setIdleTimerPeriod
2341 // A subclass policy-maker is going to use our standard idleness
2342 // detection service. Make a command queue and an idle timer and
2343 // connect them to the power management workloop. Finally,
2345 //*********************************************************************************
2347 IOReturn
IOService::setIdleTimerPeriod ( unsigned long period
)
2349 IOWorkLoop
* wl
= getPMworkloop();
2351 if (!initialized
|| !wl
)
2352 return IOPMNotYetInitialized
;
2354 OUR_PMLog(PMsetIdleTimerPeriod
, period
, 0);
2356 fIdleTimerPeriod
= period
;
2360 // make the timer event
2361 if ( fIdleTimerEventSource
== NULL
)
2363 IOTimerEventSource
* timerSrc
;
2365 timerSrc
= IOTimerEventSource::timerEventSource(
2366 this, PM_idle_timer_expired
);
2368 if (timerSrc
&& (wl
->addEventSource(timerSrc
) != kIOReturnSuccess
))
2370 timerSrc
->release();
2374 fIdleTimerEventSource
= timerSrc
;
2377 start_PM_idle_timer();
2382 //******************************************************************************
2383 // [public virtual] nextIdleTimeout
2385 // Returns how many "seconds from now" the device should idle into its
2386 // next lowest power state.
2387 //******************************************************************************
2389 SInt32
IOService::nextIdleTimeout(
2390 AbsoluteTime currentTime
,
2391 AbsoluteTime lastActivity
,
2392 unsigned int powerState
)
2399 // Calculate time difference using funky macro from clock.h.
2400 delta
= currentTime
;
2401 SUB_ABSOLUTETIME(&delta
, &lastActivity
);
2403 // Figure it in seconds.
2404 absolutetime_to_nanoseconds(delta
, &delta_ns
);
2405 delta_secs
= (SInt32
)(delta_ns
/ NSEC_PER_SEC
);
2407 // Be paranoid about delta somehow exceeding timer period.
2408 if (delta_secs
< (int) fIdleTimerPeriod
)
2409 delay_secs
= (int) fIdleTimerPeriod
- delta_secs
;
2411 delay_secs
= (int) fIdleTimerPeriod
;
2413 return (SInt32
)delay_secs
;
2416 //******************************************************************************
2417 // [public virtual] start_PM_idle_timer
2419 // The parameter is a pointer to us. Use it to call our timeout method.
2420 //******************************************************************************
2422 void IOService::start_PM_idle_timer ( void )
2424 static const int maxTimeout
= 100000;
2425 static const int minTimeout
= 1;
2426 AbsoluteTime uptime
;
2429 if (!initialized
|| !fIdleTimerEventSource
)
2432 IOLockLock(fActivityLock
);
2434 clock_get_uptime(&uptime
);
2436 // Subclasses may modify idle sleep algorithm
2437 idle_in
= nextIdleTimeout(uptime
, fDeviceActiveTimestamp
, fCurrentPowerState
);
2439 // Check for out-of range responses
2440 if (idle_in
> maxTimeout
)
2442 // use standard implementation
2443 idle_in
= IOService::nextIdleTimeout(uptime
,
2444 fDeviceActiveTimestamp
,
2445 fCurrentPowerState
);
2446 } else if (idle_in
< minTimeout
) {
2447 idle_in
= fIdleTimerPeriod
;
2450 IOLockUnlock(fActivityLock
);
2452 fIdleTimerEventSource
->setTimeout(idle_in
, NSEC_PER_SEC
);
2455 //*********************************************************************************
2456 // [private] PM_idle_timer_expired
2458 // The parameter is a pointer to us. Use it to call our timeout method.
2459 //*********************************************************************************
2461 void PM_idle_timer_expired ( OSObject
* ourSelves
, IOTimerEventSource
* )
2463 ((IOService
*)ourSelves
)->PM_idle_timer_expiration();
2466 //*********************************************************************************
2467 // [public virtual] PM_idle_timer_expiration
2469 // The idle timer has expired. If there has been activity since the last
2470 // expiration, just restart the timer and return. If there has not been
2471 // activity, switch to the next lower power state and restart the timer.
2472 //*********************************************************************************
2474 void IOService::PM_idle_timer_expiration ( void )
2476 IOPMRequest
* request
;
2477 bool restartTimer
= true;
2479 if ( !initialized
|| !fIdleTimerPeriod
)
2482 IOLockLock(fActivityLock
);
2484 // Check for device activity (tickles) over last timer period.
2488 // Device was active - do not drop power, restart timer.
2489 fDeviceActive
= false;
2493 // No device activity - drop power state by one level.
2494 // Decrement the cached tickle power state when possible.
2495 // This value may be (-1) before activityTickle() is called,
2496 // but the power drop request must be issued regardless.
2498 if (fActivityTicklePowerState
> 0)
2500 fActivityTicklePowerState
--;
2503 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
2506 request
->fArg0
= (void *) 0; // power state (irrelevant)
2507 request
->fArg1
= (void *) false; // power drop
2508 submitPMRequest( request
);
2510 // Do not restart timer until after the tickle request has been
2513 restartTimer
= false;
2517 IOLockUnlock(fActivityLock
);
2520 start_PM_idle_timer();
2523 //*********************************************************************************
2524 // [public virtual] command_received
2526 //*********************************************************************************
2528 void IOService::command_received ( void *statePtr
, void *, void * , void * )
2532 //*********************************************************************************
2533 // [public virtual] setAggressiveness
2535 // Pass on the input parameters to all power domain children. All those which are
2536 // power domains will pass it on to their children, etc.
2537 //*********************************************************************************
2539 IOReturn
IOService::setAggressiveness ( unsigned long type
, unsigned long newLevel
)
2543 IOPowerConnection
* connection
;
2547 return IOPMNotYetInitialized
;
2549 if (getPMRootDomain() == this)
2550 OUR_PMLog(kPMLogSetAggressiveness
, type
, newLevel
);
2552 if ( type
<= kMaxType
)
2554 fAggressivenessValue
[type
] = newLevel
;
2555 fAggressivenessValid
[type
] = true;
2558 iter
= getChildIterator(gIOPowerPlane
);
2561 while ( (next
= iter
->getNextObject()) )
2563 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
2565 if (connection
->getReadyFlag() == false)
2567 PM_CONNECT("[%s] %s: connection not ready\n",
2568 getName(), __FUNCTION__
);
2572 child
= ((IOService
*)(connection
->copyChildEntry(gIOPowerPlane
)));
2575 child
->setAggressiveness(type
, newLevel
);
2586 //*********************************************************************************
2587 // [public virtual] getAggressiveness
2589 // Called by the user client.
2590 //*********************************************************************************
2592 IOReturn
IOService::getAggressiveness ( unsigned long type
, unsigned long * currentLevel
)
2594 if ( !initialized
|| (type
> kMaxType
) )
2595 return kIOReturnBadArgument
;
2597 if ( !fAggressivenessValid
[type
] )
2598 return kIOReturnInvalid
;
2600 *currentLevel
= fAggressivenessValue
[type
];
2602 return kIOReturnSuccess
;
2605 //*********************************************************************************
2606 // [public] getPowerState
2608 //*********************************************************************************
2610 UInt32
IOService::getPowerState ( void )
2615 return fCurrentPowerState
;
2618 //*********************************************************************************
2619 // [public virtual] systemWake
2621 // Pass this to all power domain children. All those which are
2622 // power domains will pass it on to their children, etc.
2623 //*********************************************************************************
2625 IOReturn
IOService::systemWake ( void )
2629 IOPowerConnection
* connection
;
2630 IOService
* theChild
;
2632 OUR_PMLog(kPMLogSystemWake
, 0, 0);
2634 iter
= getChildIterator(gIOPowerPlane
);
2637 while ( (next
= iter
->getNextObject()) )
2639 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
2641 if (connection
->getReadyFlag() == false)
2643 PM_CONNECT("[%s] %s: connection not ready\n",
2644 getName(), __FUNCTION__
);
2648 theChild
= (IOService
*)connection
->copyChildEntry(gIOPowerPlane
);
2651 theChild
->systemWake();
2652 theChild
->release();
2659 if ( fControllingDriver
!= NULL
)
2661 if ( fControllingDriver
->didYouWakeSystem() )
2670 //*********************************************************************************
2671 // [public virtual] temperatureCriticalForZone
2672 //*********************************************************************************
2674 IOReturn
IOService::temperatureCriticalForZone ( IOService
* whichZone
)
2676 IOService
* theParent
;
2679 OUR_PMLog(kPMLogCriticalTemp
, 0, 0);
2681 if ( inPlane(gIOPowerPlane
) && !fWeAreRoot
)
2683 theNub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
2686 theParent
= (IOService
*)theNub
->copyParentEntry(gIOPowerPlane
);
2690 theParent
->temperatureCriticalForZone(whichZone
);
2691 theParent
->release();
2698 //*********************************************************************************
2699 // [public] powerOverrideOnPriv
2700 //*********************************************************************************
2702 IOReturn
IOService::powerOverrideOnPriv ( void )
2704 IOPMRequest
* request
;
2707 return IOPMNotYetInitialized
;
2709 if (gIOPMWorkLoop
->inGate())
2711 fDeviceOverrides
= true;
2715 request
= acquirePMRequest( this, kIOPMRequestTypePowerOverrideOnPriv
);
2717 return kIOReturnNoMemory
;
2719 submitPMRequest( request
);
2723 //*********************************************************************************
2724 // [public] powerOverrideOffPriv
2725 //*********************************************************************************
2727 IOReturn
IOService::powerOverrideOffPriv ( void )
2729 IOPMRequest
* request
;
2732 return IOPMNotYetInitialized
;
2734 if (gIOPMWorkLoop
->inGate())
2736 fDeviceOverrides
= false;
2740 request
= acquirePMRequest( this, kIOPMRequestTypePowerOverrideOffPriv
);
2742 return kIOReturnNoMemory
;
2744 submitPMRequest( request
);
2748 //*********************************************************************************
2749 // [private] handlePowerOverrideChanged
2750 //*********************************************************************************
2752 void IOService::handlePowerOverrideChanged ( IOPMRequest
* request
)
2754 PM_ASSERT_IN_GATE();
2755 if (request
->getType() == kIOPMRequestTypePowerOverrideOnPriv
)
2757 OUR_PMLog(kPMLogOverrideOn
, 0, 0);
2758 fDeviceOverrides
= true;
2762 OUR_PMLog(kPMLogOverrideOff
, 0, 0);
2763 fDeviceOverrides
= false;
2766 if (fControllingDriver
&& inPlane(gIOPowerPlane
) && fParentsKnowState
)
2768 computeDesiredState();
2773 //*********************************************************************************
2774 // [private] enqueuePowerChange
2775 //*********************************************************************************
2777 IOReturn
IOService::enqueuePowerChange (
2778 unsigned long flags
,
2779 unsigned long whatStateOrdinal
,
2780 unsigned long domainState
,
2781 IOPowerConnection
* whichParent
,
2782 unsigned long singleParentState
)
2784 changeNoteItem changeNote
;
2785 IOPMPowerState
* powerStatePtr
;
2787 PM_ASSERT_IN_GATE();
2788 assert( fMachineState
== kIOPM_Finished
);
2789 assert( whatStateOrdinal
< fNumberOfPowerStates
);
2791 if (whatStateOrdinal
>= fNumberOfPowerStates
)
2792 return IOPMAckImplied
;
2794 powerStatePtr
= &fPowerStates
[whatStateOrdinal
];
2796 // Initialize the change note
2797 changeNote
.flags
= flags
;
2798 changeNote
.newStateNumber
= whatStateOrdinal
;
2799 changeNote
.outputPowerCharacter
= powerStatePtr
->outputPowerCharacter
;
2800 changeNote
.inputPowerRequirement
= powerStatePtr
->inputPowerRequirement
;
2801 changeNote
.capabilityFlags
= powerStatePtr
->capabilityFlags
;
2802 changeNote
.parent
= NULL
;
2804 if (flags
& IOPMParentInitiated
)
2806 changeNote
.domainState
= domainState
;
2807 changeNote
.parent
= whichParent
;
2808 changeNote
.singleParentState
= singleParentState
;
2811 if (flags
& IOPMWeInitiated
)
2813 start_our_change(&changeNote
);
2818 return start_parent_change(&changeNote
);
2822 //*********************************************************************************
2823 // [private] notifyInterestedDrivers
2824 //*********************************************************************************
2826 bool IOService::notifyInterestedDrivers ( void )
2828 IOPMinformee
* informee
;
2829 IOPMinformeeList
* list
= fInterestedDrivers
;
2830 DriverCallParam
* param
;
2833 PM_ASSERT_IN_GATE();
2834 assert( fDriverCallBusy
== false );
2835 assert( fDriverCallParamCount
== 0 );
2836 assert( fHeadNotePendingAcks
== 0 );
2838 count
= list
->numberOfItems();
2840 goto done
; // no interested drivers
2842 // Allocate an array of interested drivers and their return values
2843 // for the callout thread. Everything else is still "owned" by the
2844 // PM work loop, which can run to process acknowledgePowerChange()
2847 param
= (DriverCallParam
*) fDriverCallParamPtr
;
2848 if (count
> fDriverCallParamSlots
)
2850 if (fDriverCallParamSlots
)
2852 assert(fDriverCallParamPtr
);
2853 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
2854 fDriverCallParamPtr
= 0;
2855 fDriverCallParamSlots
= 0;
2858 param
= IONew(DriverCallParam
, count
);
2860 goto done
; // no memory
2862 fDriverCallParamPtr
= (void *) param
;
2863 fDriverCallParamSlots
= count
;
2866 informee
= list
->firstInList();
2868 for (IOItemCount i
= 0; i
< count
; i
++)
2870 informee
->timer
= -1;
2871 param
[i
].Target
= informee
;
2873 informee
= list
->nextInList( informee
);
2876 fDriverCallParamCount
= count
;
2877 fHeadNotePendingAcks
= count
;
2879 // Machine state will be blocked pending callout thread completion.
2882 fDriverCallBusy
= true;
2884 thread_call_enter( fDriverCallEntry
);
2888 // no interested drivers or did not schedule callout thread due to error.
2892 //*********************************************************************************
2893 // [private] notifyInterestedDriversDone
2894 //*********************************************************************************
2896 void IOService::notifyInterestedDriversDone ( void )
2898 IOPMinformee
* informee
;
2900 DriverCallParam
* param
;
2903 PM_ASSERT_IN_GATE();
2904 param
= (DriverCallParam
*) fDriverCallParamPtr
;
2905 count
= fDriverCallParamCount
;
2907 assert( fDriverCallBusy
== false );
2908 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
2912 for (IOItemCount i
= 0; i
< count
; i
++, param
++)
2914 informee
= (IOPMinformee
*) param
->Target
;
2915 result
= param
->Result
;
2917 if ((result
== IOPMAckImplied
) || (result
< 0))
2919 // child return IOPMAckImplied
2920 informee
->timer
= 0;
2921 fHeadNotePendingAcks
--;
2923 else if (informee
->timer
)
2925 assert(informee
->timer
== -1);
2927 // Driver has not acked, and has returned a positive result.
2928 // Enforce a minimum permissible timeout value.
2929 // Make the min value large enough so timeout is less likely
2930 // to occur if a driver misinterpreted that the return value
2931 // should be in microsecond units. And make it large enough
2932 // to be noticeable if a driver neglects to ack.
2934 if (result
< kMinAckTimeoutTicks
)
2935 result
= kMinAckTimeoutTicks
;
2937 informee
->timer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
2939 // else, child has already acked or driver has removed interest,
2940 // and head_note_pendingAcks decremented.
2941 // informee may have been removed from the interested drivers list,
2942 // thus the informee must be retained across the callout.
2944 informee
->release();
2947 fDriverCallParamCount
= 0;
2949 if ( fHeadNotePendingAcks
)
2951 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
2956 // Hop back to original machine state path (from notifyAll)
2957 fMachineState
= fNextMachineState
;
2962 //*********************************************************************************
2963 // [private] notifyChildren
2964 //*********************************************************************************
2966 void IOService::notifyChildren ( void )
2970 IOPowerConnection
* connection
;
2971 OSArray
* children
= 0;
2973 if (fStrictTreeOrder
)
2974 children
= OSArray::withCapacity(8);
2976 // Sum child power consumption in notifyChild()
2977 fPowerStates
[fHeadNoteState
].staticPower
= 0;
2979 iter
= getChildIterator(gIOPowerPlane
);
2982 while ((next
= iter
->getNextObject()))
2984 if ((connection
= OSDynamicCast(IOPowerConnection
, next
)))
2986 if (connection
->getReadyFlag() == false)
2988 PM_CONNECT("[%s] %s: connection not ready\n",
2989 getName(), __FUNCTION__
);
2994 children
->setObject( connection
);
2996 notifyChild( connection
,
2997 fDriverCallReason
== kDriverCallInformPreChange
);
3005 if (children
->getCount() == 0)
3007 children
->release();
3012 assert(fNotifyChildArray
== 0);
3013 fNotifyChildArray
= children
;
3014 fNextMachineState
= fMachineState
;
3015 fMachineState
= kIOPM_NotifyChildrenDone
;
3020 //*********************************************************************************
3021 // [private] notifyChildrenDone
3022 //*********************************************************************************
3024 void IOService::notifyChildrenDone ( void )
3026 PM_ASSERT_IN_GATE();
3027 assert(fNotifyChildArray
);
3028 assert(fMachineState
== kIOPM_NotifyChildrenDone
);
3030 // Interested drivers have all acked (if any), ack timer stopped.
3031 // Notify one child, wait for it's ack, then repeat for next child.
3032 // This is a workaround for some drivers with multiple instances at
3033 // the same branch in the power tree, but the driver is slow to power
3034 // up unless the tree ordering is observed. Problem observed only on
3035 // system wake, not on system sleep.
3037 // We have the ability to power off in reverse child index order.
3038 // That works nicely on some machines, but not on all HW configs.
3040 if (fNotifyChildArray
->getCount())
3042 IOPowerConnection
* connection
;
3043 connection
= (IOPowerConnection
*) fNotifyChildArray
->getObject(0);
3044 fNotifyChildArray
->removeObject(0);
3045 notifyChild( connection
, fDriverCallReason
== kDriverCallInformPreChange
);
3049 fNotifyChildArray
->release();
3050 fNotifyChildArray
= 0;
3051 fMachineState
= fNextMachineState
;
3055 //*********************************************************************************
3056 // [private] notifyAll
3057 //*********************************************************************************
3059 IOReturn
IOService::notifyAll ( bool is_prechange
)
3061 // Save the next machine_state to be restored by notifyInterestedDriversDone()
3063 PM_ASSERT_IN_GATE();
3064 fNextMachineState
= fMachineState
;
3065 fMachineState
= kIOPM_DriverThreadCallDone
;
3066 fDriverCallReason
= is_prechange
?
3067 kDriverCallInformPreChange
: kDriverCallInformPostChange
;
3069 if (!notifyInterestedDrivers())
3070 notifyInterestedDriversDone();
3072 return IOPMWillAckLater
;
3075 //*********************************************************************************
3076 // [private, static] pmDriverCallout
3078 // Thread call context
3079 //*********************************************************************************
3081 IOReturn
IOService::actionDriverCalloutDone (
3083 void * arg0
, void * arg1
,
3084 void * arg2
, void * arg3
)
3086 IOServicePM
* pwrMgt
= (IOServicePM
*) arg0
;
3089 fDriverCallBusy
= false;
3092 if (gIOPMReplyQueue
)
3093 gIOPMReplyQueue
->signalWorkAvailable();
3095 return kIOReturnSuccess
;
3098 void IOService::pmDriverCallout ( IOService
* from
)
3101 switch (from
->fDriverCallReason
)
3103 case kDriverCallSetPowerState
:
3104 from
->driverSetPowerState();
3107 case kDriverCallInformPreChange
:
3108 case kDriverCallInformPostChange
:
3109 from
->driverInformPowerChange();
3113 IOPanic("IOService::pmDriverCallout bad machine state");
3116 gIOPMWorkLoop
->runAction(actionDriverCalloutDone
,
3118 /* arg0 */ (void *) from
->pwrMgt
);
3121 //*********************************************************************************
3122 // [private] driverSetPowerState
3124 // Thread call context
3125 //*********************************************************************************
3127 void IOService::driverSetPowerState ( void )
3130 unsigned long powerState
;
3131 DriverCallParam
* param
;
3135 assert( fDriverCallBusy
);
3136 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3138 assert( fDriverCallParamCount
== 1 );
3140 driver
= fControllingDriver
;
3141 powerState
= fHeadNoteState
;
3145 OUR_PMLog( kPMLogProgramHardware
, (UInt32
) this, powerState
);
3146 clock_get_uptime(&fDriverCallStartTime
);
3147 result
= driver
->setPowerState( powerState
, this );
3148 clock_get_uptime(&end
);
3149 OUR_PMLog((UInt32
) -kPMLogProgramHardware
, (UInt32
) this, (UInt32
) result
);
3151 #if LOG_SETPOWER_TIMES
3152 if ((result
== IOPMAckImplied
) || (result
< 0))
3156 SUB_ABSOLUTETIME(&end
, &fDriverCallStartTime
);
3157 absolutetime_to_nanoseconds(end
, &nsec
);
3158 if (nsec
> LOG_SETPOWER_TIMES
)
3159 PM_DEBUG("%s::setPowerState(%p, %lu -> %lu) took %d ms\n",
3160 fName
, this, fCurrentPowerState
, powerState
, NS_TO_MS(nsec
));
3165 result
= kIOPMAckImplied
;
3167 param
->Result
= result
;
3170 //*********************************************************************************
3171 // [private] driverInformPowerChange
3173 // Thread call context
3174 //*********************************************************************************
3176 void IOService::driverInformPowerChange ( void )
3179 IOPMinformee
* informee
;
3182 IOPMPowerFlags powerFlags
;
3183 unsigned long powerState
;
3184 DriverCallParam
* param
;
3187 assert( fDriverCallBusy
);
3188 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3189 count
= fDriverCallParamCount
;
3190 assert( count
&& param
);
3192 powerFlags
= fHeadNoteCapabilityFlags
;
3193 powerState
= fHeadNoteState
;
3195 for (IOItemCount i
= 0; i
< count
; i
++)
3197 informee
= (IOPMinformee
*) param
->Target
;
3198 driver
= informee
->whatObject
;
3200 if (!fWillPMStop
&& informee
->active
)
3202 if (fDriverCallReason
== kDriverCallInformPreChange
)
3204 OUR_PMLog(kPMLogInformDriverPreChange
, (UInt32
) this, powerState
);
3205 clock_get_uptime(&informee
->startTime
);
3206 result
= driver
->powerStateWillChangeTo(powerFlags
, powerState
, this);
3207 clock_get_uptime(&end
);
3208 OUR_PMLog((UInt32
)-kPMLogInformDriverPreChange
, (UInt32
) this, result
);
3212 OUR_PMLog(kPMLogInformDriverPostChange
, (UInt32
) this, powerState
);
3213 clock_get_uptime(&informee
->startTime
);
3214 result
= driver
->powerStateDidChangeTo(powerFlags
, powerState
, this);
3215 clock_get_uptime(&end
);
3216 OUR_PMLog((UInt32
)-kPMLogInformDriverPostChange
, (UInt32
) this, result
);
3219 #if LOG_SETPOWER_TIMES
3220 if ((result
== IOPMAckImplied
) || (result
< 0))
3224 SUB_ABSOLUTETIME(&end
, &informee
->startTime
);
3225 absolutetime_to_nanoseconds(end
, &nsec
);
3226 if (nsec
> LOG_SETPOWER_TIMES
)
3227 PM_DEBUG("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) took %d ms\n",
3229 (fDriverCallReason
== kDriverCallInformPreChange
) ? "Will" : "Did",
3230 driver
, fName
, fCurrentPowerState
, powerState
, NS_TO_MS(nsec
));
3235 result
= kIOPMAckImplied
;
3237 param
->Result
= result
;
3242 //*********************************************************************************
3243 // [private] notifyChild
3245 // Notify a power domain child of an upcoming power change.
3246 // If the object acknowledges the current change, we return TRUE.
3247 //*********************************************************************************
3249 bool IOService::notifyChild ( IOPowerConnection
* theNub
, bool is_prechange
)
3251 IOReturn k
= IOPMAckImplied
;
3252 unsigned long childPower
;
3253 IOService
* theChild
;
3254 IOPMRequest
* childRequest
;
3257 PM_ASSERT_IN_GATE();
3258 theChild
= (IOService
*)(theNub
->copyChildEntry(gIOPowerPlane
));
3265 // Unless the child handles the notification immediately and returns
3266 // kIOPMAckImplied, we'll be awaiting their acknowledgement later.
3267 fHeadNotePendingAcks
++;
3268 theNub
->setAwaitingAck(true);
3270 requestType
= is_prechange
?
3271 kIOPMRequestTypePowerDomainWillChange
:
3272 kIOPMRequestTypePowerDomainDidChange
;
3274 childRequest
= acquirePMRequest( theChild
, requestType
);
3278 childRequest
->fArg0
= (void *) fHeadNoteOutputFlags
;
3279 childRequest
->fArg1
= (void *) theNub
;
3280 childRequest
->fArg2
= (void *) (fHeadNoteState
< fCurrentPowerState
);
3281 theChild
->submitPMRequest( childRequest
);
3282 k
= IOPMWillAckLater
;
3287 fHeadNotePendingAcks
--;
3288 theNub
->setAwaitingAck(false);
3289 childPower
= theChild
->currentPowerConsumption();
3290 if ( childPower
== kIOPMUnknown
)
3292 fPowerStates
[fHeadNoteState
].staticPower
= kIOPMUnknown
;
3294 if ( fPowerStates
[fHeadNoteState
].staticPower
!= kIOPMUnknown
)
3296 fPowerStates
[fHeadNoteState
].staticPower
+= childPower
;
3301 theChild
->release();
3302 return (k
== IOPMAckImplied
);
3305 //*********************************************************************************
3306 // [private] OurChangeTellClientsPowerDown
3308 // All registered applications and kernel clients have positively acknowledged our
3309 // intention of lowering power. Here we notify them all that we will definitely
3310 // lower the power. If we don't have to wait for any of them to acknowledge, we
3311 // carry on by notifying interested drivers. Otherwise, we do wait.
3312 //*********************************************************************************
3314 void IOService::OurChangeTellClientsPowerDown ( void )
3316 fMachineState
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
3317 tellChangeDown1(fHeadNoteState
);
3320 //*********************************************************************************
3321 // [private] OurChangeTellPriorityClientsPowerDown
3323 // All registered applications and kernel clients have positively acknowledged our
3324 // intention of lowering power. Here we notify "priority" clients that we are
3325 // lowering power. If we don't have to wait for any of them to acknowledge, we
3326 // carry on by notifying interested drivers. Otherwise, we do wait.
3327 //*********************************************************************************
3329 void IOService::OurChangeTellPriorityClientsPowerDown ( void )
3331 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversWillChange
;
3332 tellChangeDown2(fHeadNoteState
);
3335 //*********************************************************************************
3336 // [private] OurChangeNotifyInterestedDriversWillChange
3338 // All registered applications and kernel clients have acknowledged our notification
3339 // that we are lowering power. Here we notify interested drivers. If we don't have
3340 // to wait for any of them to acknowledge, we instruct our power driver to make the
3341 // change. Otherwise, we do wait.
3342 //*********************************************************************************
3344 void IOService::OurChangeNotifyInterestedDriversWillChange ( void )
3346 fMachineState
= kIOPM_OurChangeSetPowerState
;
3350 //*********************************************************************************
3351 // [private] OurChangeSetPowerState
3353 // All interested drivers have acknowledged our pre-change notification of a power
3354 // change we initiated. Here we instruct our controlling driver to make
3355 // the change to the hardware. If it does so, we continue processing
3356 // (waiting for settle and notifying interested parties post-change.)
3357 // If it doesn't, we have to wait for it to acknowledge and then continue.
3358 //*********************************************************************************
3360 void IOService::OurChangeSetPowerState ( void )
3362 fNextMachineState
= kIOPM_OurChangeWaitForPowerSettle
;
3363 fMachineState
= kIOPM_DriverThreadCallDone
;
3364 fDriverCallReason
= kDriverCallSetPowerState
;
3366 if (notifyControllingDriver() == false)
3367 notifyControllingDriverDone();
3370 //*********************************************************************************
3371 // [private] OurChangeWaitForPowerSettle
3373 // Our controlling driver has changed power state on the hardware
3374 // during a power change we initiated. Here we see if we need to wait
3375 // for power to settle before continuing. If not, we continue processing
3376 // (notifying interested parties post-change). If so, we wait and
3378 //*********************************************************************************
3380 void IOService::OurChangeWaitForPowerSettle ( void )
3382 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversDidChange
;
3383 fSettleTimeUS
= compute_settle_time();
3384 if ( fSettleTimeUS
)
3386 startSettleTimer(fSettleTimeUS
);
3390 //*********************************************************************************
3391 // [private] OurChangeNotifyInterestedDriversDidChange
3393 // Power has settled on a power change we initiated. Here we notify
3394 // all our interested parties post-change. If they all acknowledge, we're
3395 // done with this change note, and we can start on the next one.
3396 // Otherwise we have to wait for acknowledgements and finish up later.
3397 //*********************************************************************************
3399 void IOService::OurChangeNotifyInterestedDriversDidChange ( void )
3401 fMachineState
= kIOPM_OurChangeFinish
;
3405 //*********************************************************************************
3406 // [private] OurChangeFinish
3408 // Power has settled on a power change we initiated, and
3409 // all our interested parties have acknowledged. We're
3410 // done with this change note, and we can start on the next one.
3411 //*********************************************************************************
3413 void IOService::OurChangeFinish ( void )
3418 //*********************************************************************************
3419 // [private] ParentDownTellPriorityClientsPowerDown
3421 // All applications and kernel clients have been notified of a power lowering
3422 // initiated by the parent and we had to wait for responses. Here
3423 // we notify any priority clients. If they all ack, we continue with the power change.
3424 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
3425 //*********************************************************************************
3427 void IOService::ParentDownTellPriorityClientsPowerDown ( void )
3429 fMachineState
= kIOPM_ParentDownNotifyInterestedDriversWillChange
;
3430 tellChangeDown2(fHeadNoteState
);
3433 //*********************************************************************************
3434 // [private] ParentDownNotifyInterestedDriversWillChange
3436 // All applications and kernel clients have been notified of a power lowering
3437 // initiated by the parent and we had to wait for their responses. Here we notify
3438 // any interested drivers and power domain children. If they all ack, we continue
3439 // with the power change.
3440 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
3441 //*********************************************************************************
3443 void IOService::ParentDownNotifyInterestedDriversWillChange ( void )
3445 fMachineState
= kIOPM_ParentDownSetPowerState
;
3449 //*********************************************************************************
3450 // [private] ParentDownSetPowerState
3452 // We had to wait for it, but all parties have acknowledged our pre-change
3453 // notification of a power lowering initiated by the parent.
3454 // Here we instruct our controlling driver
3455 // to put the hardware in the state it needs to be in when the domain is
3456 // lowered. If it does so, we continue processing
3457 // (waiting for settle and acknowledging the parent.)
3458 // If it doesn't, we have to wait for it to acknowledge and then continue.
3459 //*********************************************************************************
3461 void IOService::ParentDownSetPowerState ( void )
3463 fNextMachineState
= kIOPM_ParentDownWaitForPowerSettle
;
3464 fMachineState
= kIOPM_DriverThreadCallDone
;
3465 fDriverCallReason
= kDriverCallSetPowerState
;
3467 if (notifyControllingDriver() == false)
3468 notifyControllingDriverDone();
3471 //*********************************************************************************
3472 // [private] ParentDownWaitForPowerSettle
3474 // Our controlling driver has changed power state on the hardware
3475 // during a power change initiated by our parent. We have had to wait
3476 // for acknowledgement from interested parties, or we have had to wait
3477 // for the controlling driver to change the state. Here we see if we need
3478 // to wait for power to settle before continuing. If not, we continue
3479 // processing (acknowledging our preparedness to the parent).
3480 // If so, we wait and continue later.
3481 //*********************************************************************************
3483 void IOService::ParentDownWaitForPowerSettle ( void )
3485 fMachineState
= kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange
;
3486 fSettleTimeUS
= compute_settle_time();
3487 if ( fSettleTimeUS
)
3489 startSettleTimer(fSettleTimeUS
);
3493 //*********************************************************************************
3494 // [private] ParentDownNotifyDidChangeAndAcknowledgeChange
3496 // Power has settled on a power change initiated by our parent. Here we
3497 // notify interested parties.
3498 //*********************************************************************************
3500 void IOService::ParentDownNotifyDidChangeAndAcknowledgeChange ( void )
3502 fMachineState
= kIOPM_ParentDownAcknowledgeChange
;
3506 //*********************************************************************************
3507 // [private] ParentDownAcknowledgeChange
3509 // We had to wait for it, but all parties have acknowledged our post-change
3510 // notification of a power lowering initiated by the parent.
3511 // Here we acknowledge the parent.
3512 // We are done with this change note, and we can start on the next one.
3513 //*********************************************************************************
3515 void IOService::ParentDownAcknowledgeChange ( void )
3517 IORegistryEntry
* nub
;
3520 nub
= fHeadNoteParent
;
3523 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
3526 parent
->acknowledgePowerChange((IOService
*)nub
);
3532 //*********************************************************************************
3533 // [private] ParentUpSetPowerState
3535 // Our parent has informed us via powerStateDidChange that it has
3536 // raised the power in our power domain, and we have had to wait
3537 // for some interested party to acknowledge our notification.
3538 // Here we instruct our controlling
3539 // driver to program the hardware to take advantage of the higher domain
3540 // power. If it does so, we continue processing
3541 // (waiting for settle and notifying interested parties post-change.)
3542 // If it doesn't, we have to wait for it to acknowledge and then continue.
3543 //*********************************************************************************
3545 void IOService::ParentUpSetPowerState ( void )
3547 fNextMachineState
= kIOPM_ParentUpWaitForSettleTime
;
3548 fMachineState
= kIOPM_DriverThreadCallDone
;
3549 fDriverCallReason
= kDriverCallSetPowerState
;
3551 if (notifyControllingDriver() == false)
3552 notifyControllingDriverDone();
3555 //*********************************************************************************
3556 // [private] ParentUpWaitForSettleTime
3558 // Our controlling driver has changed power state on the hardware
3559 // during a power raise initiated by the parent, but we had to wait for it.
3560 // Here we see if we need to wait for power to settle before continuing.
3561 // If not, we continue processing (notifying interested parties post-change).
3562 // If so, we wait and continue later.
3563 //*********************************************************************************
3565 void IOService::ParentUpWaitForSettleTime ( void )
3567 fMachineState
= kIOPM_ParentUpNotifyInterestedDriversDidChange
;
3568 fSettleTimeUS
= compute_settle_time();
3569 if ( fSettleTimeUS
)
3571 startSettleTimer(fSettleTimeUS
);
3575 //*********************************************************************************
3576 // [private] ParentUpNotifyInterestedDriversDidChange
3578 // Power has settled on a power raise initiated by the parent.
3579 // Here we notify all our interested parties post-change. If they all acknowledge,
3580 // we're done with this change note, and we can start on the next one.
3581 // Otherwise we have to wait for acknowledgements and finish up later.
3582 //*********************************************************************************
3584 void IOService::ParentUpNotifyInterestedDriversDidChange ( void )
3586 fMachineState
= kIOPM_ParentUpAcknowledgePowerChange
;
3590 //*********************************************************************************
3591 // [private] ParentUpAcknowledgePowerChange
3593 // All parties have acknowledged our post-change notification of a power
3594 // raising initiated by the parent. Here we acknowledge the parent.
3595 // We are done with this change note, and we can start on the next one.
3596 //*********************************************************************************
3598 void IOService::ParentUpAcknowledgePowerChange ( void )
3600 IORegistryEntry
* nub
;
3603 nub
= fHeadNoteParent
;
3606 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
3609 parent
->acknowledgePowerChange((IOService
*)nub
);
3615 //*********************************************************************************
3616 // [private] all_done
3618 // A power change is complete, and the used post-change note is at
3619 // the head of the queue. Remove it and set myCurrentState to the result
3620 // of the change. Start up the next change in queue.
3621 //*********************************************************************************
3623 void IOService::all_done ( void )
3625 unsigned long previous_state
;
3627 fMachineState
= kIOPM_Finished
;
3630 if ( fHeadNoteFlags
& IOPMWeInitiated
)
3632 // could our driver switch to the new state?
3633 if ( !( fHeadNoteFlags
& IOPMNotDone
) )
3635 // we changed, tell our parent
3638 ask_parent(fHeadNoteState
);
3641 // yes, did power raise?
3642 if ( fCurrentPowerState
< fHeadNoteState
)
3644 // yes, inform clients and apps
3645 tellChangeUp (fHeadNoteState
);
3647 previous_state
= fCurrentPowerState
;
3649 fCurrentPowerState
= fHeadNoteState
;
3651 fPMVars
->myCurrentState
= fCurrentPowerState
;
3653 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, 0);
3655 // inform subclass policy-maker
3656 if (!fWillPMStop
&& fParentsKnowState
)
3657 powerChangeDone(previous_state
);
3659 PM_DEBUG("%s::powerChangeDone() skipped\n", getName());
3663 // parent's power change
3664 if ( fHeadNoteFlags
& IOPMParentInitiated
)
3666 if (((fHeadNoteFlags
& IOPMDomainWillChange
) && (fCurrentPowerState
>= fHeadNoteState
)) ||
3667 ((fHeadNoteFlags
& IOPMDomainDidChange
) && (fCurrentPowerState
< fHeadNoteState
)))
3670 if ( fCurrentPowerState
< fHeadNoteState
)
3672 // yes, inform clients and apps
3673 tellChangeUp (fHeadNoteState
);
3676 previous_state
= fCurrentPowerState
;
3677 fCurrentPowerState
= fHeadNoteState
;
3679 fPMVars
->myCurrentState
= fCurrentPowerState
;
3681 fMaxCapability
= fControllingDriver
->maxCapabilityForDomainState(fHeadNoteDomainState
);
3683 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, 0);
3685 // inform subclass policy-maker
3686 if (!fWillPMStop
&& fParentsKnowState
)
3687 powerChangeDone(previous_state
);
3689 PM_DEBUG("%s::powerChangeDone() skipped\n", getName());
3693 if (fCurrentPowerState
< fNumberOfPowerStates
)
3695 const IOPMPowerState
* powerStatePtr
= &fPowerStates
[fCurrentPowerState
];
3697 fCurrentCapabilityFlags
= powerStatePtr
->capabilityFlags
;
3698 if (fCurrentCapabilityFlags
& kIOPMStaticPowerValid
)
3699 fCurrentPowerConsumption
= powerStatePtr
->staticPower
;
3702 // When power rises enough to satisfy the tickle's desire for more power,
3703 // the condition preventing idle-timer from dropping power is removed.
3705 if (fCurrentPowerState
>= fIdleTimerMinPowerState
)
3707 fIdleTimerMinPowerState
= 0;
3711 //*********************************************************************************
3712 // [public] settleTimerExpired
3714 // Power has settled after our last change. Notify interested parties that
3715 // there is a new power state.
3716 //*********************************************************************************
3718 void IOService::settleTimerExpired ( void )
3723 //*********************************************************************************
3724 // [private] compute_settle_time
3726 // Compute the power-settling delay in microseconds for the
3727 // change from myCurrentState to head_note_state.
3728 //*********************************************************************************
3730 unsigned long IOService::compute_settle_time ( void )
3732 unsigned long totalTime
;
3735 PM_ASSERT_IN_GATE();
3737 // compute total time to attain the new state
3739 i
= fCurrentPowerState
;
3741 // we're lowering power
3742 if ( fHeadNoteState
< fCurrentPowerState
)
3744 while ( i
> fHeadNoteState
)
3746 totalTime
+= fPowerStates
[i
].settleDownTime
;
3751 // we're raising power
3752 if ( fHeadNoteState
> fCurrentPowerState
)
3754 while ( i
< fHeadNoteState
)
3756 totalTime
+= fPowerStates
[i
+1].settleUpTime
;
3764 //*********************************************************************************
3765 // [private] startSettleTimer
3767 // Enter a power-settling delay in microseconds and start a timer for that delay.
3768 //*********************************************************************************
3770 IOReturn
IOService::startSettleTimer ( unsigned long delay
)
3772 AbsoluteTime deadline
;
3776 clock_interval_to_deadline(delay
, kMicrosecondScale
, &deadline
);
3777 pending
= thread_call_enter_delayed(fSettleTimer
, deadline
);
3778 if (pending
) release();
3783 //*********************************************************************************
3784 // [public] ackTimerTick
3786 // The acknowledgement timeout periodic timer has ticked.
3787 // If we are awaiting acks for a power change notification,
3788 // we decrement the timer word of each interested driver which hasn't acked.
3789 // If a timer word becomes zero, we pretend the driver aknowledged.
3790 // If we are waiting for the controlling driver to change the power
3791 // state of the hardware, we decrement its timer word, and if it becomes
3792 // zero, we pretend the driver acknowledged.
3794 // Returns true if the timer tick made it possible to advance to the next
3795 // machine state, false otherwise.
3796 //*********************************************************************************
3798 void IOService::ack_timer_ticked ( void )
3803 bool IOService::ackTimerTick( void )
3805 IOPMinformee
* nextObject
;
3808 PM_ASSERT_IN_GATE();
3809 switch (fMachineState
) {
3810 case kIOPM_OurChangeWaitForPowerSettle
:
3811 case kIOPM_ParentDownWaitForPowerSettle
:
3812 case kIOPM_ParentUpWaitForSettleTime
:
3813 // are we waiting for controlling driver to acknowledge?
3814 if ( fDriverTimer
> 0 )
3816 // yes, decrement timer tick
3818 if ( fDriverTimer
== 0 )
3820 // controlling driver is tardy
3821 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
3822 OUR_PMLog(kPMLogCtrlDriverTardy
, 0, 0);
3823 setProperty(kIOPMTardyAckSPSKey
, kOSBooleanTrue
);
3824 PM_ERROR("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms\n",
3825 fName
, this, fCurrentPowerState
, fHeadNoteState
, NS_TO_MS(nsec
));
3827 if (gIOKitDebug
& kIOLogDebugPower
)
3829 panic("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms",
3830 fName
, this, fCurrentPowerState
, fHeadNoteState
, NS_TO_MS(nsec
));
3834 // Unblock state machine and pretend driver has acked.
3838 // still waiting, set timer again
3844 case kIOPM_OurChangeSetPowerState
:
3845 case kIOPM_OurChangeFinish
:
3846 case kIOPM_ParentDownSetPowerState
:
3847 case kIOPM_ParentDownAcknowledgeChange
:
3848 case kIOPM_ParentUpSetPowerState
:
3849 case kIOPM_ParentUpAcknowledgePowerChange
:
3850 case kIOPM_NotifyChildrenDone
:
3851 // are we waiting for interested parties to acknowledge?
3852 if ( fHeadNotePendingAcks
!= 0 )
3854 // yes, go through the list of interested drivers
3855 nextObject
= fInterestedDrivers
->firstInList();
3856 // and check each one
3857 while ( nextObject
!= NULL
)
3859 if ( nextObject
->timer
> 0 )
3861 nextObject
->timer
--;
3862 // this one should have acked by now
3863 if ( nextObject
->timer
== 0 )
3865 uint64_t nsec
= computeTimeDeltaNS(&nextObject
->startTime
);
3866 OUR_PMLog(kPMLogIntDriverTardy
, 0, 0);
3867 nextObject
->whatObject
->setProperty(kIOPMTardyAckPSCKey
, kOSBooleanTrue
);
3868 PM_ERROR("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) timed out after %d ms\n",
3869 nextObject
->whatObject
->getName(),
3870 (fDriverCallReason
== kDriverCallInformPreChange
) ? "Will" : "Did",
3871 nextObject
->whatObject
, fName
, fCurrentPowerState
, fHeadNoteState
,
3874 // Pretend driver has acked.
3875 fHeadNotePendingAcks
--;
3878 nextObject
= fInterestedDrivers
->nextInList(nextObject
);
3881 // is that the last?
3882 if ( fHeadNotePendingAcks
== 0 )
3884 // yes, we can continue
3887 // no, set timer again
3893 case kIOPM_ParentDownTellPriorityClientsPowerDown
:
3894 case kIOPM_ParentDownNotifyInterestedDriversWillChange
:
3895 case kIOPM_OurChangeTellClientsPowerDown
:
3896 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
3897 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
3898 // apps didn't respond in time
3899 cleanClientResponses(true);
3900 OUR_PMLog(kPMLogClientTardy
, 0, 1);
3901 if (fMachineState
== kIOPM_OurChangeTellClientsPowerDown
)
3903 // tardy equates to veto
3904 fDoNotPowerDown
= true;
3910 PM_TRACE("[%s] unexpected ack timer tick (state = %ld)\n",
3911 getName(), fMachineState
);
3917 //*********************************************************************************
3918 // [private] start_ack_timer
3919 //*********************************************************************************
3921 void IOService::start_ack_timer ( void )
3923 start_ack_timer( ACK_TIMER_PERIOD
, kNanosecondScale
);
3926 void IOService::start_ack_timer ( UInt32 interval
, UInt32 scale
)
3928 AbsoluteTime deadline
;
3931 clock_interval_to_deadline(interval
, scale
, &deadline
);
3934 pending
= thread_call_enter_delayed(fAckTimer
, deadline
);
3935 if (pending
) release();
3938 //*********************************************************************************
3939 // [private] stop_ack_timer
3940 //*********************************************************************************
3942 void IOService::stop_ack_timer ( void )
3946 pending
= thread_call_cancel(fAckTimer
);
3947 if (pending
) release();
3950 //*********************************************************************************
3951 // [static] settleTimerExpired
3953 // Inside PM work loop's gate.
3954 //*********************************************************************************
3957 IOService::actionAckTimerExpired (
3959 void * arg0
, void * arg1
,
3960 void * arg2
, void * arg3
)
3962 IOService
* me
= (IOService
*) target
;
3965 // done will be true if the timer tick unblocks the machine state,
3966 // otherwise no need to signal the work loop.
3968 done
= me
->ackTimerTick();
3969 if (done
&& gIOPMReplyQueue
)
3970 gIOPMReplyQueue
->signalWorkAvailable();
3972 return kIOReturnSuccess
;
3975 //*********************************************************************************
3976 // ack_timer_expired
3978 // Thread call function. Holds a retain while the callout is in flight.
3979 //*********************************************************************************
3982 IOService::ack_timer_expired ( thread_call_param_t arg0
, thread_call_param_t arg1
)
3984 IOService
* me
= (IOService
*) arg0
;
3988 gIOPMWorkLoop
->runAction(&actionAckTimerExpired
, me
);
3993 //*********************************************************************************
3994 // settleTimerExpired
3996 // Inside PM work loop's gate.
3997 //*********************************************************************************
4000 settleTimerExpired (
4002 void * arg0
, void * arg1
,
4003 void * arg2
, void * arg3
)
4005 IOService
* me
= (IOService
*) target
;
4006 me
->settleTimerExpired();
4007 return kIOReturnSuccess
;
4010 //*********************************************************************************
4011 // settle_timer_expired
4013 // Thread call function. Holds a retain while the callout is in flight.
4014 //*********************************************************************************
4017 settle_timer_expired ( thread_call_param_t arg0
, thread_call_param_t arg1
)
4019 IOService
* me
= (IOService
*) arg0
;
4021 if (gIOPMWorkLoop
&& gIOPMReplyQueue
)
4023 gIOPMWorkLoop
->runAction(settleTimerExpired
, me
);
4024 gIOPMReplyQueue
->signalWorkAvailable();
4029 //*********************************************************************************
4030 // [private] start_parent_change
4032 // Here we begin the processing of a power change initiated by our parent.
4033 //*********************************************************************************
4035 IOReturn
IOService::start_parent_change ( const changeNoteItem
* changeNote
)
4037 fHeadNoteFlags
= changeNote
->flags
;
4038 fHeadNoteState
= changeNote
->newStateNumber
;
4039 fHeadNoteOutputFlags
= changeNote
->outputPowerCharacter
;
4040 fHeadNoteDomainState
= changeNote
->domainState
;
4041 fHeadNoteParent
= changeNote
->parent
;
4042 fHeadNoteCapabilityFlags
= changeNote
->capabilityFlags
;
4044 PM_ASSERT_IN_GATE();
4045 OUR_PMLog( kPMLogStartParentChange
, fHeadNoteState
, fCurrentPowerState
);
4047 // Power domain is lowering power
4048 if ( fHeadNoteState
< fCurrentPowerState
)
4051 changeNote
->singleParentState
,
4052 fHeadNoteParent
, true );
4054 // tell apps and kernel clients
4055 fInitialChange
= false;
4056 fMachineState
= kIOPM_ParentDownTellPriorityClientsPowerDown
;
4057 tellChangeDown1(fHeadNoteState
);
4058 return IOPMWillAckLater
;
4061 // Power domain is raising power
4062 if ( fHeadNoteState
> fCurrentPowerState
)
4064 IOPMPowerState
* powerStatePtr
;
4066 if ( fDesiredPowerState
> fCurrentPowerState
)
4068 if ( fDesiredPowerState
< fHeadNoteState
)
4070 // We power up, but not all the way
4071 fHeadNoteState
= fDesiredPowerState
;
4072 powerStatePtr
= &fPowerStates
[fHeadNoteState
];
4073 fHeadNoteOutputFlags
= powerStatePtr
->outputPowerCharacter
;
4074 fHeadNoteCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4075 OUR_PMLog(kPMLogAmendParentChange
, fHeadNoteState
, 0);
4078 // We don't need to change
4079 fHeadNoteState
= fCurrentPowerState
;
4080 powerStatePtr
= &fPowerStates
[fHeadNoteState
];
4081 fHeadNoteOutputFlags
= powerStatePtr
->outputPowerCharacter
;
4082 fHeadNoteCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4083 OUR_PMLog(kPMLogAmendParentChange
, fHeadNoteState
, 0);
4087 if ((fHeadNoteState
> fCurrentPowerState
) &&
4088 (fHeadNoteFlags
& IOPMDomainDidChange
))
4090 // Parent did change up - start our change up
4091 fInitialChange
= false;
4092 fMachineState
= kIOPM_ParentUpSetPowerState
;
4094 return IOPMWillAckLater
;
4098 return IOPMAckImplied
;
4101 //*********************************************************************************
4102 // [private] start_our_change
4104 // Here we begin the processing of a power change initiated by us.
4105 //*********************************************************************************
4107 void IOService::start_our_change ( const changeNoteItem
* changeNote
)
4109 fHeadNoteFlags
= changeNote
->flags
;
4110 fHeadNoteState
= changeNote
->newStateNumber
;
4111 fHeadNoteOutputFlags
= changeNote
->outputPowerCharacter
;
4112 fHeadNoteCapabilityFlags
= changeNote
->capabilityFlags
;
4114 PM_ASSERT_IN_GATE();
4116 OUR_PMLog( kPMLogStartDeviceChange
, fHeadNoteState
, fCurrentPowerState
);
4118 // can our driver switch to the new state?
4119 if (( fHeadNoteCapabilityFlags
& IOPMNotAttainable
) ||
4120 ((fMaxCapability
< fHeadNoteState
) && (!fWeAreRoot
)))
4122 // mark the change note un-actioned
4123 fHeadNoteFlags
|= IOPMNotDone
;
4125 // no, ask the parent to do it then
4128 ask_parent(fHeadNoteState
);
4134 if ( !fInitialChange
)
4136 if ( fHeadNoteState
== fCurrentPowerState
)
4138 // we initiated a null change; forget it
4143 fInitialChange
= false;
4146 if ( fHeadNoteState
< fCurrentPowerState
)
4148 // yes, in case we have to wait for acks
4149 fMachineState
= kIOPM_OurChangeTellClientsPowerDown
;
4150 fDoNotPowerDown
= false;
4152 // ask apps and kernel clients if we can drop power
4153 fOutOfBandParameter
= kNotifyApps
;
4154 askChangeDown(fHeadNoteState
);
4156 // in case they don't all ack
4157 fMachineState
= kIOPM_OurChangeSetPowerState
;
4158 // notify interested drivers and children
4163 //*********************************************************************************
4164 // [private] ask_parent
4166 // Call the power domain parent to ask for a higher power state in the domain
4167 // or to suggest a lower power state.
4168 //*********************************************************************************
4170 IOReturn
IOService::ask_parent ( unsigned long requestedState
)
4174 IOPowerConnection
* connection
;
4176 const IOPMPowerState
* powerStatePtr
;
4177 unsigned long ourRequest
;
4179 PM_ASSERT_IN_GATE();
4180 if (requestedState
>= fNumberOfPowerStates
)
4183 powerStatePtr
= &fPowerStates
[requestedState
];
4184 ourRequest
= powerStatePtr
->inputPowerRequirement
;
4186 if ( powerStatePtr
->capabilityFlags
& (kIOPMChildClamp
| kIOPMPreventIdleSleep
) )
4188 ourRequest
|= kIOPMPreventIdleSleep
;
4190 if ( powerStatePtr
->capabilityFlags
& (kIOPMChildClamp2
| kIOPMPreventSystemSleep
) )
4192 ourRequest
|= kIOPMPreventSystemSleep
;
4195 // is this a new desire?
4196 if ( fPreviousRequest
== ourRequest
)
4198 // no, the parent knows already, just return
4206 fPreviousRequest
= ourRequest
;
4208 iter
= getParentIterator(gIOPowerPlane
);
4211 while ( (next
= iter
->getNextObject()) )
4213 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
4215 parent
= (IOService
*)connection
->copyParentEntry(gIOPowerPlane
);
4217 if ( parent
->requestPowerDomainState(
4218 ourRequest
, connection
, IOPMLowestState
) != IOPMNoErr
)
4220 OUR_PMLog(kPMLogRequestDenied
, fPreviousRequest
, 0);
4232 //*********************************************************************************
4233 // [private] notifyControllingDriver
4234 //*********************************************************************************
4236 bool IOService::notifyControllingDriver ( void )
4238 DriverCallParam
* param
;
4239 unsigned long powerState
;
4241 PM_ASSERT_IN_GATE();
4242 assert( fDriverCallBusy
== false );
4243 assert( fDriverCallParamCount
== 0 );
4244 assert( fControllingDriver
);
4246 powerState
= fHeadNoteState
;
4247 if (fPowerStates
[powerState
].capabilityFlags
& IOPMNotAttainable
)
4248 return false; // state not attainable
4250 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4253 param
= IONew(DriverCallParam
, 1);
4255 return false; // no memory
4257 fDriverCallParamPtr
= (void *) param
;
4258 fDriverCallParamSlots
= 1;
4261 param
->Target
= fControllingDriver
;
4262 fDriverCallParamCount
= 1;
4266 // Machine state for this object will stall waiting for a reply
4267 // from the callout thread.
4270 fDriverCallBusy
= true;
4272 thread_call_enter( fDriverCallEntry
);
4276 //*********************************************************************************
4277 // [private] notifyControllingDriverDone
4278 //*********************************************************************************
4280 void IOService::notifyControllingDriverDone( void )
4282 DriverCallParam
* param
;
4285 PM_ASSERT_IN_GATE();
4286 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4288 assert( fDriverCallBusy
== false );
4289 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
4293 assert(fDriverCallParamCount
== 1);
4295 // the return value from setPowerState()
4296 result
= param
->Result
;
4298 if ((result
== IOPMAckImplied
) || (result
< 0))
4300 // child return IOPMAckImplied
4303 else if (fDriverTimer
)
4305 assert(fDriverTimer
== -1);
4307 // Driver has not acked, and has returned a positive result.
4308 // Enforce a minimum permissible timeout value.
4309 // Make the min value large enough so timeout is less likely
4310 // to occur if a driver misinterpreted that the return value
4311 // should be in microsecond units. And make it large enough
4312 // to be noticeable if a driver neglects to ack.
4314 if (result
< kMinAckTimeoutTicks
)
4315 result
= kMinAckTimeoutTicks
;
4317 fDriverTimer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
4319 // else, child has already acked and driver_timer reset to 0.
4321 fDriverCallParamCount
= 0;
4325 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
4330 // Hop back to original machine state path.
4331 fMachineState
= fNextMachineState
;
4334 //*********************************************************************************
4335 // [public virtual] askChangeDown
4337 // Ask registered applications and kernel clients if we can change to a lower
4340 // Subclass can override this to send a different message type. Parameter is
4341 // the destination state number.
4343 // Return true if we don't have to wait for acknowledgements
4344 //*********************************************************************************
4346 bool IOService::askChangeDown ( unsigned long stateNum
)
4348 return tellClientsWithResponse( kIOMessageCanDevicePowerOff
);
4351 //*********************************************************************************
4352 // [public] tellChangeDown1
4354 // Notify registered applications and kernel clients that we are definitely
4357 // Return true if we don't have to wait for acknowledgements
4358 //*********************************************************************************
4360 bool IOService::tellChangeDown1 ( unsigned long stateNum
)
4362 fOutOfBandParameter
= kNotifyApps
;
4363 return tellChangeDown(stateNum
);
4366 //*********************************************************************************
4367 // [public] tellChangeDown2
4369 // Notify priority clients that we are definitely dropping power.
4371 // Return true if we don't have to wait for acknowledgements
4372 //*********************************************************************************
4374 bool IOService::tellChangeDown2 ( unsigned long stateNum
)
4376 fOutOfBandParameter
= kNotifyPriority
;
4377 return tellChangeDown(stateNum
);
4380 //*********************************************************************************
4381 // [public virtual] tellChangeDown
4383 // Notify registered applications and kernel clients that we are definitely
4386 // Subclass can override this to send a different message type. Parameter is
4387 // the destination state number.
4389 // Return true if we don't have to wait for acknowledgements
4390 //*********************************************************************************
4392 bool IOService::tellChangeDown ( unsigned long stateNum
)
4394 return tellClientsWithResponse( kIOMessageDeviceWillPowerOff
);
4397 //*********************************************************************************
4398 // cleanClientResponses
4400 //*********************************************************************************
4402 static void logAppTimeouts ( OSObject
* object
, void * context
)
4404 struct context
*theContext
= (struct context
*)context
;
4407 if( !OSDynamicCast( IOService
, object
) ) {
4408 flag
= theContext
->responseFlags
->getObject(theContext
->counter
);
4409 if (kOSBooleanTrue
!= flag
)
4411 OSString
* clientID
= 0;
4412 theContext
->us
->messageClient(theContext
->msgType
, object
, &clientID
);
4413 PM_ERROR(theContext
->errorLog
, clientID
? clientID
->getCStringNoCopy() : "");
4415 clientID
->release();
4417 theContext
->counter
+= 1;
4421 void IOService::cleanClientResponses ( bool logErrors
)
4423 struct context theContext
;
4425 if (logErrors
&& fResponseArray
) {
4426 theContext
.responseFlags
= fResponseArray
;
4427 theContext
.serialNumber
= fSerialNumber
;
4428 theContext
.counter
= 0;
4429 theContext
.msgType
= kIOMessageCopyClientID
;
4430 theContext
.us
= this;
4431 theContext
.maxTimeRequested
= 0;
4432 theContext
.stateNumber
= fHeadNoteState
;
4433 theContext
.stateFlags
= fHeadNoteCapabilityFlags
;
4434 theContext
.errorLog
= "PM notification timeout (%s)\n";
4436 switch ( fOutOfBandParameter
) {
4438 applyToInterested(gIOAppPowerStateInterest
, logAppTimeouts
, (void *) &theContext
);
4439 case kNotifyPriority
:
4447 // get rid of this stuff
4448 fResponseArray
->release();
4449 fResponseArray
= NULL
;
4455 //*********************************************************************************
4456 // [public] tellClientsWithResponse
4458 // Notify registered applications and kernel clients that we are definitely
4461 // Return true if we don't have to wait for acknowledgements
4462 //*********************************************************************************
4464 bool IOService::tellClientsWithResponse ( int messageType
)
4466 struct context theContext
;
4468 PM_ASSERT_IN_GATE();
4470 fResponseArray
= OSArray::withCapacity( 1 );
4473 theContext
.responseFlags
= fResponseArray
;
4474 theContext
.serialNumber
= fSerialNumber
;
4475 theContext
.counter
= 0;
4476 theContext
.msgType
= messageType
;
4477 theContext
.us
= this;
4478 theContext
.maxTimeRequested
= 0;
4479 theContext
.stateNumber
= fHeadNoteState
;
4480 theContext
.stateFlags
= fHeadNoteCapabilityFlags
;
4482 switch ( fOutOfBandParameter
) {
4484 applyToInterested(gIOAppPowerStateInterest
,
4485 pmTellAppWithResponse
, (void *)&theContext
);
4486 applyToInterested(gIOGeneralInterest
,
4487 pmTellClientWithResponse
, (void *)&theContext
);
4489 case kNotifyPriority
:
4490 applyToInterested(gIOPriorityPowerStateInterest
,
4491 pmTellClientWithResponse
, (void *)&theContext
);
4495 // do we have to wait for somebody?
4496 if ( !checkForDone() )
4498 OUR_PMLog(kPMLogStartAckTimer
,theContext
.maxTimeRequested
, 0);
4499 start_ack_timer( theContext
.maxTimeRequested
/ 1000, kMillisecondScale
);
4503 // everybody responded
4504 fResponseArray
->release();
4505 fResponseArray
= NULL
;
4506 // cleanClientResponses(false);
4511 //*********************************************************************************
4512 // [static private] pmTellAppWithResponse
4514 // We send a message to an application, and we expect a response, so we compute a
4515 // cookie we can identify the response with.
4516 //*********************************************************************************
4518 void IOService::pmTellAppWithResponse ( OSObject
* object
, void * context
)
4520 struct context
* theContext
= (struct context
*) context
;
4521 IOServicePM
* pwrMgt
= theContext
->us
->pwrMgt
;
4524 if( OSDynamicCast( IOService
, object
) )
4526 // Automatically 'ack' in kernel clients
4527 theContext
->responseFlags
->setObject(theContext
->counter
, kOSBooleanTrue
);
4529 const char *who
= ((IOService
*) object
)->getName();
4530 fPlatform
->PMLog(who
,
4531 kPMLogClientAcknowledge
, theContext
->msgType
, * (UInt32
*) object
);
4533 UInt32 refcon
= ((theContext
->serialNumber
& 0xFFFF)<<16)
4534 + (theContext
->counter
& 0xFFFF);
4535 OUR_PMLog(kPMLogAppNotify
, theContext
->msgType
, refcon
);
4537 #if LOG_APP_RESPONSE_TIMES
4539 clock_get_uptime(&now
);
4540 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&now
), sizeof(uint64_t) * 8);
4543 theContext
->responseFlags
->setObject(theContext
->counter
, num
);
4548 theContext
->responseFlags
->setObject(theContext
->counter
, kOSBooleanFalse
);
4550 theContext
->us
->messageClient(theContext
->msgType
, object
, (void *)refcon
);
4551 if ( theContext
->maxTimeRequested
< k30seconds
)
4553 theContext
->maxTimeRequested
= k30seconds
;
4556 theContext
->counter
+= 1;
4560 //*********************************************************************************
4561 // [static private] pmTellClientWithResponse
4563 // We send a message to an in-kernel client, and we expect a response, so we compute a
4564 // cookie we can identify the response with.
4565 // If it doesn't understand the notification (it is not power-management savvy)
4566 // we won't wait for it to prepare for sleep. If it tells us via a return code
4567 // in the passed struct that it is currently ready, we won't wait for it to prepare.
4568 // If it tells us via the return code in the struct that it does need time, we will chill.
4569 //*********************************************************************************
4571 void IOService::pmTellClientWithResponse ( OSObject
* object
, void * context
)
4573 struct context
*theContext
= (struct context
*)context
;
4574 IOPowerStateChangeNotification notify
;
4579 refcon
= ((theContext
->serialNumber
& 0xFFFF)<<16) + (theContext
->counter
& 0xFFFF);
4580 theContext
->responseFlags
->setObject(theContext
->counter
, kOSBooleanFalse
);
4582 IOServicePM
* pwrMgt
= theContext
->us
->pwrMgt
;
4583 if (gIOKitDebug
& kIOLogPower
) {
4584 OUR_PMLog(kPMLogClientNotify
, refcon
, (UInt32
) theContext
->msgType
);
4585 if (OSDynamicCast(IOService
, object
)) {
4586 const char *who
= ((IOService
*) object
)->getName();
4587 fPlatform
->PMLog(who
,
4588 kPMLogClientNotify
, * (UInt32
*) object
, (UInt32
) object
);
4589 } else if (OSDynamicCast(_IOServiceInterestNotifier
, object
)) {
4590 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
4591 OUR_PMLog(kPMLogClientNotify
, (UInt32
) n
->handler
, 0);
4595 notify
.powerRef
= (void *)refcon
;
4596 notify
.returnValue
= 0;
4597 notify
.stateNumber
= theContext
->stateNumber
;
4598 notify
.stateFlags
= theContext
->stateFlags
;
4599 retCode
= theContext
->us
->messageClient(theContext
->msgType
,object
,(void *)¬ify
);
4600 if ( retCode
== kIOReturnSuccess
)
4602 if ( notify
.returnValue
== 0 )
4604 // client doesn't want time to respond
4605 theContext
->responseFlags
->replaceObject(theContext
->counter
, kOSBooleanTrue
);
4606 OUR_PMLog(kPMLogClientAcknowledge
, refcon
, (UInt32
) object
);
4608 // it does want time, and it hasn't responded yet
4609 theFlag
= theContext
->responseFlags
->getObject(theContext
->counter
);
4610 if ( kOSBooleanTrue
!= theFlag
)
4612 // so note its time requirement
4613 if ( theContext
->maxTimeRequested
< notify
.returnValue
)
4615 theContext
->maxTimeRequested
= notify
.returnValue
;
4620 OUR_PMLog(kPMLogClientAcknowledge
, refcon
, 0);
4621 // not a client of ours
4622 // so we won't be waiting for response
4623 theContext
->responseFlags
->replaceObject(theContext
->counter
, kOSBooleanTrue
);
4625 theContext
->counter
+= 1;
4628 //*********************************************************************************
4629 // [public virtual] tellNoChangeDown
4631 // Notify registered applications and kernel clients that we are not
4634 // Subclass can override this to send a different message type. Parameter is
4635 // the aborted destination state number.
4636 //*********************************************************************************
4638 void IOService::tellNoChangeDown ( unsigned long )
4640 return tellClients( kIOMessageDeviceWillNotPowerOff
);
4643 //*********************************************************************************
4644 // [public virtual] tellChangeUp
4646 // Notify registered applications and kernel clients that we are raising power.
4648 // Subclass can override this to send a different message type. Parameter is
4649 // the aborted destination state number.
4650 //*********************************************************************************
4652 void IOService::tellChangeUp ( unsigned long )
4654 return tellClients( kIOMessageDeviceHasPoweredOn
);
4657 //*********************************************************************************
4658 // [public] tellClients
4660 // Notify registered applications and kernel clients of something.
4661 //*********************************************************************************
4663 void IOService::tellClients ( int messageType
)
4665 struct context theContext
;
4667 theContext
.msgType
= messageType
;
4668 theContext
.us
= this;
4669 theContext
.stateNumber
= fHeadNoteState
;
4670 theContext
.stateFlags
= fHeadNoteCapabilityFlags
;
4672 applyToInterested(gIOPriorityPowerStateInterest
,tellClient
,(void *)&theContext
);
4673 applyToInterested(gIOAppPowerStateInterest
,tellClient
, (void *)&theContext
);
4674 applyToInterested(gIOGeneralInterest
,tellClient
, (void *)&theContext
);
4677 //*********************************************************************************
4678 // [global] tellClient
4680 // Notify a registered application or kernel client of something.
4681 //*********************************************************************************
4683 void tellClient ( OSObject
* object
, void * context
)
4685 struct context
* theContext
= (struct context
*) context
;
4686 IOPowerStateChangeNotification notify
;
4688 notify
.powerRef
= (void *) 0;
4689 notify
.returnValue
= 0;
4690 notify
.stateNumber
= theContext
->stateNumber
;
4691 notify
.stateFlags
= theContext
->stateFlags
;
4693 theContext
->us
->messageClient(theContext
->msgType
, object
, ¬ify
);
4696 //*********************************************************************************
4697 // [private] checkForDone
4698 //*********************************************************************************
4700 bool IOService::checkForDone ( void )
4705 if ( fResponseArray
== NULL
)
4710 for ( i
= 0; ; i
++ )
4712 theFlag
= fResponseArray
->getObject(i
);
4713 if ( theFlag
== NULL
)
4717 if ( kOSBooleanTrue
!= theFlag
)
4725 //*********************************************************************************
4726 // [public] responseValid
4727 //*********************************************************************************
4729 bool IOService::responseValid ( unsigned long x
, int pid
)
4731 UInt16 serialComponent
;
4732 UInt16 ordinalComponent
;
4734 unsigned long refcon
= (unsigned long) x
;
4736 serialComponent
= (refcon
>> 16) & 0xFFFF;
4737 ordinalComponent
= (refcon
& 0xFFFF);
4739 if ( serialComponent
!= fSerialNumber
)
4744 if ( fResponseArray
== NULL
)
4749 theFlag
= fResponseArray
->getObject(ordinalComponent
);
4757 if ((num
= OSDynamicCast(OSNumber
, theFlag
)))
4759 #if LOG_APP_RESPONSE_TIMES
4764 clock_get_uptime(&now
);
4765 AbsoluteTime_to_scalar(&start
) = num
->unsigned64BitValue();
4766 SUB_ABSOLUTETIME(&now
, &start
);
4767 absolutetime_to_nanoseconds(now
, &nsec
);
4770 if (nsec
> LOG_APP_RESPONSE_TIMES
)
4772 OSString
* name
= IOCopyLogNameForPID(pid
);
4773 PM_DEBUG("PM response took %d ms (%s)\n", NS_TO_MS(nsec
),
4774 name
? name
->getCStringNoCopy() : "");
4779 theFlag
= kOSBooleanFalse
;
4782 if ( kOSBooleanFalse
== theFlag
)
4784 fResponseArray
->replaceObject(ordinalComponent
, kOSBooleanTrue
);
4790 //*********************************************************************************
4791 // [public virtual] allowPowerChange
4793 // Our power state is about to lower, and we have notified applications
4794 // and kernel clients, and one of them has acknowledged. If this is the last to do
4795 // so, and all acknowledgements are positive, we continue with the power change.
4797 // We serialize this processing with timer expiration with a command gate on the
4798 // power management workloop, which the timer expiration is command gated to as well.
4799 //*********************************************************************************
4801 IOReturn
IOService::allowPowerChange ( unsigned long refcon
)
4803 IOPMRequest
* request
;
4808 return kIOReturnSuccess
;
4811 request
= acquirePMRequest( this, kIOPMRequestTypeAllowPowerChange
);
4814 PM_ERROR("%s::%s no memory\n", getName(), __FUNCTION__
);
4815 return kIOReturnNoMemory
;
4818 request
->fArg0
= (void *) refcon
;
4819 request
->fArg1
= (void *) proc_selfpid();
4820 submitPMRequest( request
);
4822 return kIOReturnSuccess
;
4825 IOReturn
serializedAllowPowerChange ( OSObject
*owner
, void * refcon
, void *, void *, void *)
4827 // [deprecated] public
4828 return kIOReturnUnsupported
;
4831 IOReturn
IOService::serializedAllowPowerChange2 ( unsigned long refcon
)
4833 // [deprecated] public
4834 return kIOReturnUnsupported
;
4837 //*********************************************************************************
4838 // [public virtual] cancelPowerChange
4840 // Our power state is about to lower, and we have notified applications
4841 // and kernel clients, and one of them has vetoed the change. If this is the last
4842 // client to respond, we abandon the power change.
4844 // We serialize this processing with timer expiration with a command gate on the
4845 // power management workloop, which the timer expiration is command gated to as well.
4846 //*********************************************************************************
4848 IOReturn
IOService::cancelPowerChange ( unsigned long refcon
)
4850 IOPMRequest
* request
;
4855 return kIOReturnSuccess
;
4858 request
= acquirePMRequest( this, kIOPMRequestTypeCancelPowerChange
);
4861 PM_ERROR("%s::%s no memory\n", getName(), __FUNCTION__
);
4862 return kIOReturnNoMemory
;
4865 request
->fArg0
= (void *) refcon
;
4866 request
->fArg1
= (void *) proc_selfpid();
4867 submitPMRequest( request
);
4869 return kIOReturnSuccess
;
4872 IOReturn
serializedCancelPowerChange ( OSObject
*owner
, void * refcon
, void *, void *, void *)
4874 // [deprecated] public
4875 return kIOReturnUnsupported
;
4878 IOReturn
IOService::serializedCancelPowerChange2 ( unsigned long refcon
)
4880 // [deprecated] public
4881 return kIOReturnUnsupported
;
4885 //*********************************************************************************
4886 // c_PM_clamp_Timer_Expired (C Func)
4888 // Called when our clamp timer expires...we will call the object method.
4889 //*********************************************************************************
4891 static void c_PM_Clamp_Timer_Expired ( OSObject
* client
, IOTimerEventSource
* )
4894 ((IOService
*)client
)->PM_Clamp_Timer_Expired ();
4898 //*********************************************************************************
4899 // PM_Clamp_Timer_Expired
4901 // called when clamp timer expires...set power state to 0.
4902 //*********************************************************************************
4904 void IOService::PM_Clamp_Timer_Expired ( void )
4907 if ( ! initialized
)
4913 changePowerStateToPriv (0);
4917 //*********************************************************************************
4920 // Set to highest available power state for a minimum of duration milliseconds
4921 //*********************************************************************************
4923 #define kFiveMinutesInNanoSeconds (300 * NSEC_PER_SEC)
4925 void IOService::clampPowerOn ( unsigned long duration
)
4928 changePowerStateToPriv (fNumberOfPowerStates
-1);
4930 if ( pwrMgt
->clampTimerEventSrc
== NULL
) {
4931 pwrMgt
->clampTimerEventSrc
= IOTimerEventSource::timerEventSource(this,
4932 c_PM_Clamp_Timer_Expired
);
4934 IOWorkLoop
* workLoop
= getPMworkloop ();
4936 if ( !pwrMgt
->clampTimerEventSrc
|| !workLoop
||
4937 ( workLoop
->addEventSource( pwrMgt
->clampTimerEventSrc
) != kIOReturnSuccess
) ) {
4942 pwrMgt
->clampTimerEventSrc
->setTimeout(300*USEC_PER_SEC
, USEC_PER_SEC
);
4946 //*********************************************************************************
4947 // [public virtual] setPowerState
4949 // Does nothing here. This should be implemented in a subclass driver.
4950 //*********************************************************************************
4952 IOReturn
IOService::setPowerState (
4953 unsigned long powerStateOrdinal
, IOService
* whatDevice
)
4958 //*********************************************************************************
4959 // [public virtual] maxCapabilityForDomainState
4961 // Finds the highest power state in the array whose input power
4962 // requirement is equal to the input parameter. Where a more intelligent
4963 // decision is possible, override this in the subclassed driver.
4964 //*********************************************************************************
4966 unsigned long IOService::maxCapabilityForDomainState ( IOPMPowerFlags domainState
)
4970 if (fNumberOfPowerStates
== 0 )
4974 for ( i
= fNumberOfPowerStates
- 1; i
>= 0; i
-- )
4976 if ( (domainState
& fPowerStates
[i
].inputPowerRequirement
) ==
4977 fPowerStates
[i
].inputPowerRequirement
)
4985 //*********************************************************************************
4986 // [public virtual] initialPowerStateForDomainState
4988 // Finds the highest power state in the array whose input power
4989 // requirement is equal to the input parameter. Where a more intelligent
4990 // decision is possible, override this in the subclassed driver.
4991 //*********************************************************************************
4993 unsigned long IOService::initialPowerStateForDomainState ( IOPMPowerFlags domainState
)
4997 if (fNumberOfPowerStates
== 0 )
5001 for ( i
= fNumberOfPowerStates
- 1; i
>= 0; i
-- )
5003 if ( (domainState
& fPowerStates
[i
].inputPowerRequirement
) ==
5004 fPowerStates
[i
].inputPowerRequirement
)
5012 //*********************************************************************************
5013 // [public virtual] powerStateForDomainState
5015 // Finds the highest power state in the array whose input power
5016 // requirement is equal to the input parameter. Where a more intelligent
5017 // decision is possible, override this in the subclassed driver.
5018 //*********************************************************************************
5020 unsigned long IOService::powerStateForDomainState ( IOPMPowerFlags domainState
)
5024 if (fNumberOfPowerStates
== 0 )
5028 for ( i
= fNumberOfPowerStates
- 1; i
>= 0; i
-- )
5030 if ( (domainState
& fPowerStates
[i
].inputPowerRequirement
) ==
5031 fPowerStates
[i
].inputPowerRequirement
)
5039 //*********************************************************************************
5040 // [public virtual] didYouWakeSystem
5042 // Does nothing here. This should be implemented in a subclass driver.
5043 //*********************************************************************************
5045 bool IOService::didYouWakeSystem ( void )
5050 //*********************************************************************************
5051 // [public virtual] powerStateWillChangeTo
5053 // Does nothing here. This should be implemented in a subclass driver.
5054 //*********************************************************************************
5056 IOReturn
IOService::powerStateWillChangeTo ( IOPMPowerFlags
, unsigned long, IOService
* )
5058 return kIOPMAckImplied
;
5061 //*********************************************************************************
5062 // [public virtual] powerStateDidChangeTo
5064 // Does nothing here. This should be implemented in a subclass driver.
5065 //*********************************************************************************
5067 IOReturn
IOService::powerStateDidChangeTo ( IOPMPowerFlags
, unsigned long, IOService
* )
5069 return kIOPMAckImplied
;
5072 //*********************************************************************************
5073 // [public virtual] powerChangeDone
5075 // Called from PM work loop thread.
5076 // Does nothing here. This should be implemented in a subclass policy-maker.
5077 //*********************************************************************************
5079 void IOService::powerChangeDone ( unsigned long )
5083 //*********************************************************************************
5084 // [public virtual] newTemperature
5086 // Does nothing here. This should be implemented in a subclass driver.
5087 //*********************************************************************************
5089 IOReturn
IOService::newTemperature ( long currentTemp
, IOService
* whichZone
)
5094 //*********************************************************************************
5095 // [public virtual] systemWillShutdown
5097 // System shutdown and restart notification.
5098 //*********************************************************************************
5100 void IOService::systemWillShutdown( IOOptionBits specifier
)
5102 IOPMrootDomain
* rootDomain
= IOService::getPMRootDomain();
5104 rootDomain
->acknowledgeSystemWillShutdown( this );
5107 //*********************************************************************************
5108 // [private static] acquirePMRequest
5109 //*********************************************************************************
5112 IOService::acquirePMRequest( IOService
* target
, IOOptionBits requestType
)
5114 IOPMRequest
* request
;
5118 request
= IOPMRequest::create();
5121 request
->init( target
, requestType
);
5126 //*********************************************************************************
5127 // [private static] releasePMRequest
5128 //*********************************************************************************
5130 void IOService::releasePMRequest( IOPMRequest
* request
)
5139 //*********************************************************************************
5140 // [private] submitPMRequest
5141 //*********************************************************************************
5143 void IOService::submitPMRequest( IOPMRequest
* request
)
5146 assert( gIOPMReplyQueue
);
5147 assert( gIOPMRequestQueue
);
5149 PM_TRACE("[+ %02lx] %p [%p %s] %p %p %p\n",
5150 request
->getType(), request
,
5151 request
->getTarget(), request
->getTarget()->getName(),
5152 request
->fArg0
, request
->fArg1
, request
->fArg2
);
5154 if (request
->isReply())
5155 gIOPMReplyQueue
->queuePMRequest( request
);
5157 gIOPMRequestQueue
->queuePMRequest( request
);
5160 void IOService::submitPMRequest( IOPMRequest
** requests
, IOItemCount count
)
5163 assert( count
> 0 );
5164 assert( gIOPMRequestQueue
);
5166 for (IOItemCount i
= 0; i
< count
; i
++)
5168 IOPMRequest
* req
= requests
[i
];
5169 PM_TRACE("[+ %02lx] %p [%p %s] %p %p %p\n",
5170 req
->getType(), req
,
5171 req
->getTarget(), req
->getTarget()->getName(),
5172 req
->fArg0
, req
->fArg1
, req
->fArg2
);
5175 gIOPMRequestQueue
->queuePMRequestChain( requests
, count
);
5178 //*********************************************************************************
5179 // [private] servicePMRequestQueue
5180 //*********************************************************************************
5182 bool IOService::servicePMRequestQueue(
5183 IOPMRequest
* request
,
5184 IOPMRequestQueue
* queue
)
5186 // Calling PM methods without PMinit() is not allowed, fail the requests.
5190 PM_DEBUG("[%s] %s: PM not initialized\n", getName(), __FUNCTION__
);
5194 // Create an IOPMWorkQueue on demand, when the initial PM request is
5199 // Allocate and attach an IOPMWorkQueue on demand to avoid taking
5200 // the work loop lock in PMinit(), which may deadlock with certain
5201 // drivers / families.
5203 fPMWorkQueue
= IOPMWorkQueue::create(
5205 /* Work */ OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
5206 &IOService::servicePMRequest
),
5207 /* Done */ OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
5208 &IOService::retirePMRequest
)
5212 (gIOPMWorkLoop
->addEventSource(fPMWorkQueue
) != kIOReturnSuccess
))
5214 PM_ERROR("[%s] %s: addEventSource failed\n",
5215 getName(), __FUNCTION__
);
5216 fPMWorkQueue
->release();
5222 PM_ERROR("[%s] %s: not ready (type %02lx)\n",
5223 getName(), __FUNCTION__
, request
->getType());
5228 fPMWorkQueue
->queuePMRequest(request
);
5229 return false; // do not signal more
5232 gIOPMFreeQueue
->queuePMRequest( request
);
5233 return false; // do not signal more
5236 //*********************************************************************************
5237 // [private] servicePMFreeQueue
5239 // Called by IOPMFreeQueue to recycle a completed request.
5240 //*********************************************************************************
5242 bool IOService::servicePMFreeQueue(
5243 IOPMRequest
* request
,
5244 IOPMRequestQueue
* queue
)
5246 bool more
= request
->hasParentRequest();
5247 releasePMRequest( request
);
5251 //*********************************************************************************
5252 // [private] retirePMRequest
5254 // Called by IOPMWorkQueue to retire a completed request.
5255 //*********************************************************************************
5257 bool IOService::retirePMRequest( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
5259 assert(request
&& queue
);
5261 PM_TRACE("[- %02lx] %p [%p %s] State %ld, Busy %ld\n",
5262 request
->getType(), request
, this, getName(),
5263 fMachineState
, gIOPMBusyCount
);
5265 // Catch requests created by PM_idle_timer_expiration().
5267 if ((request
->getType() == kIOPMRequestTypeActivityTickle
) &&
5268 (request
->fArg1
== (void *) false))
5270 // Idle timer power drop request completed.
5271 // Restart the idle timer if deviceDesire can go lower, otherwise set
5272 // a flag so we know to restart idle timer when deviceDesire goes up.
5274 if (fDeviceDesire
> 0)
5275 start_PM_idle_timer();
5277 fActivityTimerStopped
= true;
5280 gIOPMFreeQueue
->queuePMRequest( request
);
5284 //*********************************************************************************
5285 // [private] isPMBlocked
5287 // Check if machine state transition is blocked.
5288 //*********************************************************************************
5290 bool IOService::isPMBlocked ( IOPMRequest
* request
, int count
)
5295 if (kIOPM_Finished
== fMachineState
)
5298 if (kIOPM_DriverThreadCallDone
== fMachineState
)
5300 // 5 = kDriverCallInformPreChange
5301 // 6 = kDriverCallInformPostChange
5302 // 7 = kDriverCallSetPowerState
5303 if (fDriverCallBusy
) reason
= 5 + fDriverCallReason
;
5307 // Waiting on driver's setPowerState() timeout.
5313 // Child or interested driver acks pending.
5314 if (fHeadNotePendingAcks
)
5319 // Waiting on apps or priority power interest clients.
5325 // Waiting on settle timer expiration.
5332 fWaitReason
= reason
;
5338 PM_TRACE("[B %02lx] %p [%p %s] State %ld, Reason %d\n",
5339 request
->getType(), request
, this, getName(),
5340 fMachineState
, reason
);
5349 //*********************************************************************************
5350 // [private] servicePMRequest
5352 // Service a request from our work queue.
5353 //*********************************************************************************
5355 bool IOService::servicePMRequest( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
5360 assert(request
&& queue
);
5362 while (isPMBlocked(request
, loop
++) == false)
5364 PM_TRACE("[W %02lx] %p [%p %s] State %ld\n",
5365 request
->getType(), request
, this, getName(), fMachineState
);
5367 fPMRequest
= request
;
5369 // Every PM machine states must be handled in one of the cases below.
5371 switch ( fMachineState
)
5373 case kIOPM_Finished
:
5374 executePMRequest( request
);
5377 case kIOPM_OurChangeTellClientsPowerDown
:
5378 // our change, was it vetoed?
5379 if (fDesiredPowerState
> fHeadNoteState
)
5381 PM_DEBUG("%s: idle cancel\n", fName
);
5382 fDoNotPowerDown
= true;
5384 if (!fDoNotPowerDown
)
5386 // no, we can continue
5387 OurChangeTellClientsPowerDown();
5391 // yes, rescind the warning
5392 tellNoChangeDown(fHeadNoteState
);
5393 // mark the change note un-actioned
5394 fHeadNoteFlags
|= IOPMNotDone
;
5400 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
5401 OurChangeTellPriorityClientsPowerDown();
5404 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
5405 OurChangeNotifyInterestedDriversWillChange();
5408 case kIOPM_OurChangeSetPowerState
:
5409 OurChangeSetPowerState();
5412 case kIOPM_OurChangeWaitForPowerSettle
:
5413 OurChangeWaitForPowerSettle();
5416 case kIOPM_OurChangeNotifyInterestedDriversDidChange
:
5417 OurChangeNotifyInterestedDriversDidChange();
5420 case kIOPM_OurChangeFinish
:
5424 case kIOPM_ParentDownTellPriorityClientsPowerDown
:
5425 ParentDownTellPriorityClientsPowerDown();
5428 case kIOPM_ParentDownNotifyInterestedDriversWillChange
:
5429 ParentDownNotifyInterestedDriversWillChange();
5432 case kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange
:
5433 ParentDownNotifyDidChangeAndAcknowledgeChange();
5436 case kIOPM_ParentDownSetPowerState
:
5437 ParentDownSetPowerState();
5440 case kIOPM_ParentDownWaitForPowerSettle
:
5441 ParentDownWaitForPowerSettle();
5444 case kIOPM_ParentDownAcknowledgeChange
:
5445 ParentDownAcknowledgeChange();
5448 case kIOPM_ParentUpSetPowerState
:
5449 ParentUpSetPowerState();
5452 case kIOPM_ParentUpWaitForSettleTime
:
5453 ParentUpWaitForSettleTime();
5456 case kIOPM_ParentUpNotifyInterestedDriversDidChange
:
5457 ParentUpNotifyInterestedDriversDidChange();
5460 case kIOPM_ParentUpAcknowledgePowerChange
:
5461 ParentUpAcknowledgePowerChange();
5464 case kIOPM_DriverThreadCallDone
:
5465 if (fDriverCallReason
== kDriverCallSetPowerState
)
5466 notifyControllingDriverDone();
5468 notifyInterestedDriversDone();
5471 case kIOPM_NotifyChildrenDone
:
5472 notifyChildrenDone();
5476 IOPanic("servicePMWorkQueue: unknown machine state");
5481 if (fMachineState
== kIOPM_Finished
)
5483 //PM_TRACE("[%s] PM End: Request %p (type %02lx)\n",
5484 // getName(), request, request->getType());
5493 //*********************************************************************************
5494 // [private] executePMRequest
5495 //*********************************************************************************
5497 void IOService::executePMRequest( IOPMRequest
* request
)
5499 assert( kIOPM_Finished
== fMachineState
);
5501 switch (request
->getType())
5503 case kIOPMRequestTypePMStop
:
5504 handlePMstop( request
);
5507 case kIOPMRequestTypeAddPowerChild1
:
5508 addPowerChild1( request
);
5511 case kIOPMRequestTypeAddPowerChild2
:
5512 addPowerChild2( request
);
5515 case kIOPMRequestTypeAddPowerChild3
:
5516 addPowerChild3( request
);
5519 case kIOPMRequestTypeRegisterPowerDriver
:
5520 handleRegisterPowerDriver( request
);
5523 case kIOPMRequestTypeAdjustPowerState
:
5527 case kIOPMRequestTypeMakeUsable
:
5528 handleMakeUsable( request
);
5531 case kIOPMRequestTypeTemporaryPowerClamp
:
5533 handleMakeUsable( request
);
5536 case kIOPMRequestTypePowerDomainWillChange
:
5537 handlePowerDomainWillChangeTo( request
);
5540 case kIOPMRequestTypePowerDomainDidChange
:
5541 handlePowerDomainDidChangeTo( request
);
5544 case kIOPMRequestTypeChangePowerStateTo
:
5545 handleChangePowerStateTo( request
);
5548 case kIOPMRequestTypeChangePowerStateToPriv
:
5549 handleChangePowerStateToPriv( request
);
5552 case kIOPMRequestTypePowerOverrideOnPriv
:
5553 case kIOPMRequestTypePowerOverrideOffPriv
:
5554 handlePowerOverrideChanged( request
);
5557 case kIOPMRequestTypeActivityTickle
:
5560 bool setDeviceDesire
= false;
5564 // Power rise from activity tickle.
5565 unsigned long ticklePowerState
= (unsigned long) request
->fArg0
;
5566 if ((fDeviceDesire
< ticklePowerState
) &&
5567 (ticklePowerState
< fNumberOfPowerStates
))
5569 setDeviceDesire
= true;
5570 fIdleTimerMinPowerState
= ticklePowerState
;
5573 else if (fDeviceDesire
> fIdleTimerMinPowerState
)
5575 // Power drop from idle timer expiration.
5576 request
->fArg0
= (void *) (fDeviceDesire
- 1);
5577 setDeviceDesire
= true;
5580 if (setDeviceDesire
)
5582 // handleChangePowerStateToPriv() does not check the
5583 // request type, as long as the args are appropriate
5584 // for kIOPMRequestTypeChangePowerStateToPriv.
5586 request
->fArg1
= (void *) false;
5587 handleChangePowerStateToPriv( request
);
5593 IOPanic("executePMRequest: unknown request type");
5597 //*********************************************************************************
5598 // [private] servicePMReplyQueue
5599 //*********************************************************************************
5601 bool IOService::servicePMReplyQueue( IOPMRequest
* request
, IOPMRequestQueue
* queue
)
5605 assert( request
&& queue
);
5606 assert( request
->isReply() );
5608 PM_TRACE("[A %02lx] %p [%p %s] State %ld\n",
5609 request
->getType(), request
, this, getName(), fMachineState
);
5611 switch ( request
->getType() )
5613 case kIOPMRequestTypeAllowPowerChange
:
5614 case kIOPMRequestTypeCancelPowerChange
:
5615 // Check if we are expecting this response.
5616 if (responseValid((unsigned long) request
->fArg0
, (int) request
->fArg1
))
5618 if (kIOPMRequestTypeCancelPowerChange
== request
->getType())
5619 fDoNotPowerDown
= true;
5624 if ( fResponseArray
)
5626 fResponseArray
->release();
5627 fResponseArray
= NULL
;
5634 case kIOPMRequestTypeAckPowerChange
:
5635 more
= handleAcknowledgePowerChange( request
);
5638 case kIOPMRequestTypeAckSetPowerState
:
5639 if (fDriverTimer
== -1)
5641 // driver acked while setPowerState() call is in-flight.
5642 // take this ack, return value from setPowerState() is irrelevant.
5643 OUR_PMLog(kPMLogDriverAcknowledgeSet
,
5644 (UInt32
) this, fDriverTimer
);
5647 else if (fDriverTimer
> 0)
5649 // expected ack, stop the timer
5652 #if LOG_SETPOWER_TIMES
5653 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
5654 if (nsec
> LOG_SETPOWER_TIMES
)
5655 PM_DEBUG("%s::setPowerState(%p, %lu -> %lu) async took %d ms\n",
5656 fName
, this, fCurrentPowerState
, fHeadNoteState
, NS_TO_MS(nsec
));
5658 OUR_PMLog(kPMLogDriverAcknowledgeSet
, (UInt32
) this, fDriverTimer
);
5665 OUR_PMLog(kPMLogAcknowledgeErr4
, (UInt32
) this, 0);
5669 case kIOPMRequestTypeInterestChanged
:
5670 handleInterestChanged( request
);
5675 IOPanic("servicePMReplyQueue: unknown reply type");
5678 releasePMRequest( request
);
5682 //*********************************************************************************
5683 // IOPMRequest Class
5685 // Requests from PM clients, and also used for inter-object messaging within PM.
5686 //*********************************************************************************
5688 OSDefineMetaClassAndStructors( IOPMRequest
, IOCommand
);
5690 IOPMRequest
* IOPMRequest::create( void )
5692 IOPMRequest
* me
= OSTypeAlloc(IOPMRequest
);
5693 if (me
&& !me
->init(0, kIOPMRequestTypeInvalid
))
5701 bool IOPMRequest::init( IOService
* target
, IOOptionBits type
)
5703 if (!IOCommand::init())
5710 fArg0
= fArg1
= fArg2
= 0;
5718 void IOPMRequest::reset( void )
5720 assert( fChildCount
== 0 );
5722 fType
= kIOPMRequestTypeInvalid
;
5726 fParent
->fChildCount
--;
5737 //*********************************************************************************
5738 // IOPMRequestQueue Class
5740 // Global queues. As PM-aware drivers load and unload, their IOPMWorkQueue's are
5741 // created and deallocated. IOPMRequestQueue are created once and never released.
5742 //*********************************************************************************
5744 OSDefineMetaClassAndStructors( IOPMRequestQueue
, IOEventSource
);
5746 IOPMRequestQueue
* IOPMRequestQueue::create( IOService
* inOwner
, Action inAction
)
5748 IOPMRequestQueue
* me
= OSTypeAlloc(IOPMRequestQueue
);
5749 if (me
&& !me
->init(inOwner
, inAction
))
5757 bool IOPMRequestQueue::init( IOService
* inOwner
, Action inAction
)
5759 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
))
5762 queue_init(&fQueue
);
5763 fLock
= IOLockAlloc();
5764 return (fLock
!= 0);
5767 void IOPMRequestQueue::free( void )
5774 return IOEventSource::free();
5777 void IOPMRequestQueue::queuePMRequest( IOPMRequest
* request
)
5781 queue_enter(&fQueue
, request
, IOPMRequest
*, fCommandChain
);
5782 IOLockUnlock(fLock
);
5783 if (workLoop
) signalWorkAvailable();
5787 IOPMRequestQueue::queuePMRequestChain( IOPMRequest
** requests
, IOItemCount count
)
5791 assert(requests
&& count
);
5797 queue_enter(&fQueue
, next
, IOPMRequest
*, fCommandChain
);
5799 IOLockUnlock(fLock
);
5800 if (workLoop
) signalWorkAvailable();
5803 bool IOPMRequestQueue::checkForWork( void )
5805 Action dqAction
= (Action
) action
;
5806 IOPMRequest
* request
;
5810 IOLockLock( fLock
);
5812 while (!queue_empty(&fQueue
))
5814 queue_remove_first( &fQueue
, request
, IOPMRequest
*, fCommandChain
);
5815 IOLockUnlock( fLock
);
5816 target
= request
->getTarget();
5818 more
|= (*dqAction
)( target
, request
, this );
5819 IOLockLock( fLock
);
5822 IOLockUnlock( fLock
);
5826 void IOPMRequestQueue::signalWorkAvailable( void )
5828 IOEventSource::signalWorkAvailable();
5831 //*********************************************************************************
5832 // IOPMWorkQueue Class
5834 // Every object in the power plane that has handled a PM request, will have an
5835 // instance of IOPMWorkQueue allocated for it.
5836 //*********************************************************************************
5838 OSDefineMetaClassAndStructors( IOPMWorkQueue
, IOEventSource
);
5841 IOPMWorkQueue::create( IOService
* inOwner
, Action work
, Action retire
)
5843 IOPMWorkQueue
* me
= OSTypeAlloc(IOPMWorkQueue
);
5844 if (me
&& !me
->init(inOwner
, work
, retire
))
5852 bool IOPMWorkQueue::init( IOService
* inOwner
, Action work
, Action retire
)
5854 if (!work
|| !retire
||
5855 !IOEventSource::init(inOwner
, (IOEventSourceAction
)0))
5858 queue_init(&fWorkQueue
);
5861 fRetireAction
= retire
;
5866 void IOPMWorkQueue::queuePMRequest( IOPMRequest
* request
)
5869 assert( onThread() );
5872 queue_enter(&fWorkQueue
, request
, IOPMRequest
*, fCommandChain
);
5876 bool IOPMWorkQueue::checkForWork( void )
5878 IOPMRequest
* request
;
5879 IOService
* target
= (IOService
*) owner
;
5882 while (!queue_empty(&fWorkQueue
))
5884 request
= (IOPMRequest
*) queue_first(&fWorkQueue
);
5885 assert(request
->getTarget() == target
);
5886 if (request
->hasChildRequest()) break;
5887 done
= (*fWorkAction
)( target
, request
, this );
5890 assert(gIOPMBusyCount
> 0);
5891 if (gIOPMBusyCount
) gIOPMBusyCount
--;
5892 queue_remove_first(&fWorkQueue
, request
, IOPMRequest
*, fCommandChain
);
5893 (*fRetireAction
)( target
, request
, this );
5899 OSDefineMetaClassAndStructors(IOServicePM
, OSObject
)
5901 //*********************************************************************************
5904 // Serialize IOServicePM for debugging.
5905 //*********************************************************************************
5908 setPMProperty( OSDictionary
* dict
, const char * key
, unsigned long value
)
5910 OSNumber
* num
= OSNumber::withNumber(value
, sizeof(value
) * 8);
5913 dict
->setObject(key
, num
);
5918 bool IOServicePM::serialize( OSSerialize
* s
) const
5920 OSDictionary
* dict
;
5923 dict
= OSDictionary::withCapacity(8);
5926 setPMProperty( dict
, "CurrentPowerState", CurrentPowerState
);
5927 if (DesiredPowerState
!= CurrentPowerState
)
5928 setPMProperty( dict
, "DesiredPowerState", DesiredPowerState
);
5929 if (kIOPM_Finished
!= MachineState
)
5930 setPMProperty( dict
, "MachineState", MachineState
);
5932 setPMProperty( dict
, "ChildrenPowerState", ChildrenDesire
);
5934 setPMProperty( dict
, "DeviceChangePowerState", DeviceDesire
);
5936 setPMProperty( dict
, "DriverChangePowerState", DriverDesire
);
5937 if (DeviceOverrides
)
5938 dict
->setObject( "PowerOverrideOn", kOSBooleanTrue
);
5940 ok
= dict
->serialize(s
);