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@
32 #include <IOKit/assert.h>
33 #include <IOKit/IOKitDebug.h>
34 #include <IOKit/IOLib.h>
35 #include <IOKit/IOMessage.h>
36 #include <IOKit/IOPlatformExpert.h>
37 #include <IOKit/IOService.h>
38 #include <IOKit/IOEventSource.h>
39 #include <IOKit/IOWorkLoop.h>
40 #include <IOKit/IOCommand.h>
41 #include <IOKit/IOTimeStamp.h>
43 #include <IOKit/pwr_mgt/IOPMlog.h>
44 #include <IOKit/pwr_mgt/IOPMinformee.h>
45 #include <IOKit/pwr_mgt/IOPMinformeeList.h>
46 #include <IOKit/pwr_mgt/IOPowerConnection.h>
47 #include <IOKit/pwr_mgt/RootDomain.h>
48 #include <IOKit/pwr_mgt/IOPMPrivate.h>
51 #include <sys/proc_internal.h>
52 #include <libkern/OSDebug.h>
54 // Required for notification instrumentation
55 #include "IOServicePrivate.h"
56 #include "IOServicePMPrivate.h"
57 #include "IOKitKernelInternal.h"
59 static void settle_timer_expired(thread_call_param_t
, thread_call_param_t
);
60 static void idle_timer_expired(thread_call_param_t
, thread_call_param_t
);
61 static void tellKernelClientApplier(OSObject
* object
, void * arg
);
62 static void tellAppClientApplier(OSObject
* object
, void * arg
);
64 static uint64_t computeTimeDeltaNS( const AbsoluteTime
* start
)
69 clock_get_uptime(&now
);
70 SUB_ABSOLUTETIME(&now
, start
);
71 absolutetime_to_nanoseconds(now
, &nsec
);
76 OSDefineMetaClassAndStructors(IOPMprot
, OSObject
)
79 // Container class for recording system power events
80 OSDefineMetaClassAndStructors( PMEventDetails
, OSObject
);
82 //******************************************************************************
84 //******************************************************************************
86 static bool gIOPMInitialized
= false;
87 static uint32_t gIOPMBusyCount
= 0;
88 static uint32_t gIOPMWorkCount
= 0;
89 static uint32_t gIOPMTickleGeneration
= 0;
90 static IOWorkLoop
* gIOPMWorkLoop
= 0;
91 static IOPMRequestQueue
* gIOPMRequestQueue
= 0;
92 static IOPMRequestQueue
* gIOPMReplyQueue
= 0;
93 static IOPMWorkQueue
* gIOPMWorkQueue
= 0;
94 static IOPMCompletionQueue
* gIOPMFreeQueue
= 0;
95 static IOPMRequest
* gIOPMRequest
= 0;
96 static IOService
* gIOPMRootNode
= 0;
97 static IOPlatformExpert
* gPlatform
= 0;
99 static const OSSymbol
* gIOPMPowerClientDevice
= 0;
100 static const OSSymbol
* gIOPMPowerClientDriver
= 0;
101 static const OSSymbol
* gIOPMPowerClientChildProxy
= 0;
102 static const OSSymbol
* gIOPMPowerClientChildren
= 0;
104 static const OSSymbol
* gIOPMPowerClientAdvisoryTickle
= 0;
105 static bool gIOPMAdvisoryTickleEnabled
= true;
107 static uint32_t getPMRequestType( void )
109 uint32_t type
= kIOPMRequestTypeInvalid
;
111 type
= gIOPMRequest
->getType();
115 //******************************************************************************
117 //******************************************************************************
119 #define PM_ERROR(x...) do { kprintf(x); IOLog(x); } while (false)
120 #define PM_LOG(x...) do { kprintf(x); } while (false)
122 #define PM_LOG1(x...) do { \
123 if (kIOLogDebugPower & gIOKitDebug) \
124 kprintf(x); } while (false)
126 #define PM_LOG2(x...) do { \
127 if (kIOLogDebugPower & gIOKitDebug) \
128 kprintf(x); } while (false)
131 #define PM_LOG3(x...) do { kprintf(x); } while (false)
133 #define PM_LOG3(x...)
136 #define RD_LOG(x...) do { \
137 if ((kIOLogPMRootDomain & gIOKitDebug) && \
138 (getPMRootDomain() == this)) \
139 kprintf("PMRD: " x); } while (false)
141 #define PM_ASSERT_IN_GATE(x) \
143 assert(gIOPMWorkLoop->inGate()); \
146 #define PM_LOCK() IOLockLock(fPMLock)
147 #define PM_UNLOCK() IOLockUnlock(fPMLock)
148 #define PM_LOCK_SLEEP(event, dl) IOLockSleepDeadline(fPMLock, event, dl, THREAD_UNINT)
149 #define PM_LOCK_WAKEUP(event) IOLockWakeup(fPMLock, event, false)
151 #define ns_per_us 1000
152 #define k30Seconds (30*1000000)
153 #define kMinAckTimeoutTicks (10*1000000)
154 #define kIOPMTardyAckSPSKey "IOPMTardyAckSetPowerState"
155 #define kIOPMTardyAckPSCKey "IOPMTardyAckPowerStateChange"
156 #define kPwrMgtKey "IOPowerManagement"
158 #define OUR_PMLog(t, a, b) do { \
159 if (gIOKitDebug & kIOLogPower) \
160 pwrMgt->pmPrint(t, a, b); \
161 if (gIOKitTrace & kIOTracePowerMgmt) \
162 pwrMgt->pmTrace(t, a, b); \
165 #define NS_TO_MS(nsec) ((int)((nsec) / 1000000ULL))
166 #define NS_TO_US(nsec) ((int)((nsec) / 1000ULL))
169 #define SUPPORT_IDLE_CANCEL 1
172 #define kIOPMPowerStateMax 0xFFFFFFFF
173 #define kInvalidTicklePowerState (-1)
175 #define kNoTickleCancelWindow (60ULL * 1000ULL * 1000ULL * 1000ULL)
177 #define IS_PM_ROOT (this == gIOPMRootNode)
178 #define IS_ROOT_DOMAIN (getPMRootDomain() == this)
179 #define IS_POWER_DROP (fHeadNotePowerState < fCurrentPowerState)
180 #define IS_POWER_RISE (fHeadNotePowerState > fCurrentPowerState)
182 // log setPowerStates longer than (ns):
183 #define LOG_SETPOWER_TIMES (50ULL * 1000ULL * 1000ULL)
184 // log app responses longer than (ns):
185 #define LOG_APP_RESPONSE_TIMES (100ULL * 1000ULL * 1000ULL)
186 // use message tracer to log messages longer than (ns):
187 #define LOG_APP_RESPONSE_MSG_TRACER (3 * 1000ULL * 1000ULL * 1000ULL)
190 kReserveDomainPower
= 1
194 do { assert(kIOPM_BadMachineState == fSavedMachineState); \
195 assert(kIOPM_BadMachineState != n); \
196 fSavedMachineState = n; } while (false)
199 do { assert(kIOPM_BadMachineState != fSavedMachineState); \
200 fMachineState = fSavedMachineState; \
201 fSavedMachineState = kIOPM_BadMachineState; } while (false)
203 #define PM_ACTION_0(a) \
204 do { if (fPMActions.a) { \
205 (fPMActions.a)(fPMActions.target, this, &fPMActions); } \
208 #define PM_ACTION_2(a, x, y) \
209 do { if (fPMActions.a) { \
210 (fPMActions.a)(fPMActions.target, this, &fPMActions, x, y); } \
213 static OSNumber
* copyClientIDForNotification(
215 IOPMInterestContext
*context
);
217 static void logClientIDForNotification(
219 IOPMInterestContext
*context
,
220 const char *logString
);
222 //*********************************************************************************
225 // Check kgmacros after modifying machine states.
226 //*********************************************************************************
231 kIOPM_OurChangeTellClientsPowerDown
= 1,
232 kIOPM_OurChangeTellPriorityClientsPowerDown
= 2,
233 kIOPM_OurChangeNotifyInterestedDriversWillChange
= 3,
234 kIOPM_OurChangeSetPowerState
= 4,
235 kIOPM_OurChangeWaitForPowerSettle
= 5,
236 kIOPM_OurChangeNotifyInterestedDriversDidChange
= 6,
237 kIOPM_OurChangeTellCapabilityDidChange
= 7,
238 kIOPM_OurChangeFinish
= 8,
240 kIOPM_ParentChangeTellPriorityClientsPowerDown
= 10,
241 kIOPM_ParentChangeNotifyInterestedDriversWillChange
= 11,
242 kIOPM_ParentChangeSetPowerState
= 12,
243 kIOPM_ParentChangeWaitForPowerSettle
= 13,
244 kIOPM_ParentChangeNotifyInterestedDriversDidChange
= 14,
245 kIOPM_ParentChangeTellCapabilityDidChange
= 15,
246 kIOPM_ParentChangeAcknowledgePowerChange
= 16,
248 kIOPM_NotifyChildrenStart
= 17,
249 kIOPM_NotifyChildrenOrdered
= 18,
250 kIOPM_NotifyChildrenDelayed
= 19,
251 kIOPM_SyncTellClientsPowerDown
= 20,
252 kIOPM_SyncTellPriorityClientsPowerDown
= 21,
253 kIOPM_SyncNotifyWillChange
= 22,
254 kIOPM_SyncNotifyDidChange
= 23,
255 kIOPM_SyncTellCapabilityDidChange
= 24,
256 kIOPM_SyncFinish
= 25,
257 kIOPM_TellCapabilityChangeDone
= 26,
258 kIOPM_DriverThreadCallDone
= 27,
260 kIOPM_BadMachineState
= 0xFFFFFFFF
265 Power Management defines a few roles that drivers can play in their own,
266 and other drivers', power management. We briefly define those here.
268 Many drivers implement their policy maker and power controller within the same
269 IOService object, but that is not required.
272 * Virtual IOService PM methods a "policy maker" may implement
273 * maxCapabilityForDomainState()
274 * initialPowerStateForDomainState()
275 * powerStateForDomainState()
277 * Virtual IOService PM methods a "policy maker" may CALL
280 == Power Controller ==
281 * Virtual IOService PM methods a "power controller" may implement
284 * Virtual IOService PM methods a "power controller" may CALL
286 * registerPowerDriver()
288 =======================
289 There are two different kinds of power state changes.
290 * One is initiated by a subclassed device object which has either decided
291 to change power state, or its controlling driver has suggested it, or
292 some other driver wants to use the idle device and has asked it to become
294 * The second kind of power state change is initiated by the power domain
296 The two are handled through different code paths.
298 We maintain a queue of "change notifications," or change notes.
299 * Usually the queue is empty.
300 * When it isn't, usually there is one change note in it
301 * It's possible to have more than one power state change pending at one
302 time, so a queue is implemented.
304 * The subclass device decides it's idle and initiates a change to a lower
305 power state. This causes interested parties to be notified, but they
306 don't all acknowledge right away. This causes the change note to sit
307 in the queue until all the acks are received. During this time, the
308 device decides it isn't idle anymore and wants to raise power back up
309 again. This change can't be started, however, because the previous one
310 isn't complete yet, so the second one waits in the queue. During this
311 time, the parent decides to lower or raise the power state of the entire
312 power domain and notifies the device, and that notification goes into
313 the queue, too, and can't be actioned until the others are.
316 This is how a power change initiated by the subclass device is handled:
317 -> First, all interested parties are notified of the change via their
318 powerStateWillChangeTo method. If they all don't acknowledge via return
319 code, then we have to wait. If they do, or when they finally all
320 acknowledge via our acknowledgePowerChange method, then we can continue.
321 -> We call the controlling driver, instructing it to change to the new state
322 -> Then we wait for power to settle. If there is no settling-time, or after
324 -> we notify interested parties again, this time via their
325 powerStateDidChangeTo methods.
326 -> When they have all acked, we're done.
327 If we lowered power and don't need the power domain to be in its current power
328 state, we suggest to the parent that it lower the power domain state.
330 == PowerDomainDownInitiated ==
331 How a change to a lower power domain state initiated by the parent is handled:
332 -> First, we figure out what power state we will be in when the new domain
334 -> Then all interested parties are notified that we are moving to that new
336 -> When they have acknowledged, we call the controlling driver to assume
337 that state and we wait for power to settle.
338 -> Then we acknowledge our preparedness to our parent. When all its
339 interested parties have acknowledged,
340 -> it lowers power and then notifies its interested parties again.
341 -> When we get this call, we notify our interested parties that the power
342 state has changed, and when they have all acknowledged, we're done.
344 == PowerDomainUpInitiated ==
345 How a change to a higher power domain state initiated by the parent is handled:
346 -> We figure out what power state we will be in when the new domain state is
348 -> If it is different from our current state we acknowledge the parent.
349 -> When all the parent's interested parties have acknowledged, it raises
350 power in the domain and waits for power to settle.
351 -> Then it notifies everyone that the new state has been reached.
352 -> When we get this call, we call the controlling driver, instructing it to
353 assume the new state, and wait for power to settle.
354 -> Then we notify our interested parties. When they all acknowledge we are
357 In either of the two power domain state cases above, it is possible that we
358 will not be changing state even though the domain is.
360 * A change to a lower domain state may not affect us because we are already
361 in a low enough state,
362 * We will not take advantage of a change to a higher domain state, because
363 we have no need of the higher power. In such cases, there is nothing to
364 do but acknowledge the parent. So when the parent calls our
365 powerDomainWillChange method, and we decide that we will not be changing
366 state, we merely acknowledge the parent, via return code, and wait.
367 When the parent subsequently calls powerStateDidChange, we acknowledge again
368 via return code, and the change is complete.
370 == 4 Paths Through State Machine ==
371 Power state changes are processed in a state machine, and since there are four
372 varieties of power state changes, there are four major paths through the state
375 == 5. No Need To change ==
376 The fourth is nearly trivial. In this path, the parent is changing the domain
377 state, but we are not changing the device state. The change starts when the
378 parent calls powerDomainWillChange. All we do is acknowledge the parent. When
379 the parent calls powerStateDidChange, we acknowledge the parent again, and
382 == 1. OurChange Down == XXX gvdl
383 The first is fairly simple. It starts:
384 * when a power domain child calls requestPowerDomainState and we decide to
385 change power states to accomodate the child,
386 * or if our power-controlling driver calls changePowerStateTo,
387 * or if some other driver which is using our device calls makeUsable,
388 * or if a subclassed object calls changePowerStateToPriv.
389 These are all power changes initiated by us, not forced upon us by the parent.
391 -> We start by notifying interested parties.
392 -> If they all acknowledge via return code, we can go on to state
394 -> Otherwise, we start the ack timer and wait for the stragglers to
395 acknowlege by calling acknowledgePowerChange.
396 -> We move on to state "msSetPowerState" when all the
397 stragglers have acknowledged, or when the ack timer expires on
398 all those which didn't acknowledge.
399 In "msSetPowerState" we call the power-controlling driver to change the
400 power state of the hardware.
401 -> If it returns saying it has done so, we go on to state
402 "msWaitForPowerSettle".
403 -> Otherwise, we have to wait for it, so we set the ack timer and wait.
404 -> When it calls acknowledgeSetPowerState, or when the ack timer
406 In "msWaitForPowerSettle", we look in the power state array to see if
407 there is any settle time required when changing from our current state to the
409 -> If not, we go right away to "msNotifyInterestedDriversDidChange".
410 -> Otherwise, we set the settle timer and wait. When it expires, we move on.
411 In "msNotifyInterestedDriversDidChange" state, we notify all our
412 interested parties via their powerStateDidChange methods that we have finished
413 changing power state.
414 -> If they all acknowledge via return code, we move on to "msFinish".
415 -> Otherwise we set the ack timer and wait. When they have all
416 acknowledged, or when the ack timer has expired for those that didn't,
417 we move on to "msFinish".
418 In "msFinish" we remove the used change note from the head of the queue
419 and start the next one if one exists.
421 == 2. Parent Change Down ==
422 Start at Stage 2 of OurChange Down XXX gvdl
425 Start at Stage 4 of OurChange Down XXX gvdl
427 Note all parent requested changes need to acknowledge the power has changed to the parent when done.
430 //*********************************************************************************
433 // Initialize power management.
434 //*********************************************************************************
436 void IOService::PMinit ( void )
440 if ( !gIOPMInitialized
)
442 gPlatform
= getPlatform();
443 gIOPMWorkLoop
= IOWorkLoop::workLoop();
446 gIOPMRequestQueue
= IOPMRequestQueue::create(
447 this, OSMemberFunctionCast(IOPMRequestQueue::Action
,
448 this, &IOService::servicePMRequestQueue
));
450 gIOPMReplyQueue
= IOPMRequestQueue::create(
451 this, OSMemberFunctionCast(IOPMRequestQueue::Action
,
452 this, &IOService::servicePMReplyQueue
));
454 gIOPMWorkQueue
= IOPMWorkQueue::create(
456 OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
457 &IOService::servicePMRequest
),
458 OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
459 &IOService::retirePMRequest
));
461 gIOPMFreeQueue
= IOPMCompletionQueue::create(
462 this, OSMemberFunctionCast(IOPMCompletionQueue::Action
,
463 this, &IOService::servicePMFreeQueue
));
465 if (gIOPMWorkLoop
->addEventSource(gIOPMRequestQueue
) !=
468 gIOPMRequestQueue
->release();
469 gIOPMRequestQueue
= 0;
472 if (gIOPMWorkLoop
->addEventSource(gIOPMReplyQueue
) !=
475 gIOPMReplyQueue
->release();
479 if (gIOPMWorkLoop
->addEventSource(gIOPMWorkQueue
) !=
482 gIOPMWorkQueue
->release();
486 if (gIOPMWorkLoop
->addEventSource(gIOPMFreeQueue
) !=
489 gIOPMFreeQueue
->release();
493 gIOPMPowerClientDevice
=
494 OSSymbol::withCStringNoCopy( "DevicePowerState" );
496 gIOPMPowerClientDriver
=
497 OSSymbol::withCStringNoCopy( "DriverPowerState" );
499 gIOPMPowerClientChildProxy
=
500 OSSymbol::withCStringNoCopy( "ChildProxyPowerState" );
502 gIOPMPowerClientChildren
=
503 OSSymbol::withCStringNoCopy( "ChildrenPowerState" );
505 gIOPMPowerClientAdvisoryTickle
=
506 OSSymbol::withCStringNoCopy( "AdvisoryTicklePowerState" );
509 if (gIOPMRequestQueue
&& gIOPMReplyQueue
&& gIOPMFreeQueue
)
510 gIOPMInitialized
= true;
512 if (!gIOPMInitialized
)
515 pwrMgt
= new IOServicePM
;
517 setProperty(kPwrMgtKey
, pwrMgt
);
519 queue_init(&pwrMgt
->WorkChain
);
520 queue_init(&pwrMgt
->RequestHead
);
521 queue_init(&pwrMgt
->PMDriverCallQueue
);
524 fPMLock
= IOLockAlloc();
525 fInterestedDrivers
= new IOPMinformeeList
;
526 fInterestedDrivers
->initialize();
527 fDesiredPowerState
= 0;
529 fInitialPowerChange
= true;
530 fInitialSetPowerState
= true;
531 fPreviousRequestPowerFlags
= 0;
532 fDeviceOverrideEnabled
= false;
533 fMachineState
= kIOPM_Finished
;
534 fSavedMachineState
= kIOPM_BadMachineState
;
535 fIdleTimerMinPowerState
= 0;
536 fActivityLock
= IOLockAlloc();
537 fStrictTreeOrder
= false;
538 fActivityTicklePowerState
= kInvalidTicklePowerState
;
539 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
540 fControllingDriver
= NULL
;
542 fNumberOfPowerStates
= 0;
543 fCurrentPowerState
= 0;
544 fParentsCurrentPowerFlags
= 0;
547 fParentsKnowState
= false;
549 fResponseArray
= NULL
;
550 fNotifyClientArray
= NULL
;
551 fCurrentPowerConsumption
= kIOPMUnknown
;
552 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
554 if (!gIOPMRootNode
&& (getParentEntry(gIOPowerPlane
) == getRegistryRoot()))
556 gIOPMRootNode
= this;
557 fParentsKnowState
= true;
559 else if (getProperty(kIOPMResetPowerStateOnWakeKey
) == kOSBooleanTrue
)
561 fResetPowerStateOnWake
= true;
564 fAckTimer
= thread_call_allocate(
565 &IOService::ack_timer_expired
, (thread_call_param_t
)this);
566 fSettleTimer
= thread_call_allocate(
567 &settle_timer_expired
, (thread_call_param_t
)this);
568 fIdleTimer
= thread_call_allocate(
569 &idle_timer_expired
, (thread_call_param_t
)this);
570 fDriverCallEntry
= thread_call_allocate(
571 (thread_call_func_t
) &IOService::pmDriverCallout
, this);
572 assert(fDriverCallEntry
);
574 // Check for powerChangeDone override.
575 if (OSMemberFunctionCast(void (*)(void),
576 getResourceService(), &IOService::powerChangeDone
) !=
577 OSMemberFunctionCast(void (*)(void),
578 this, &IOService::powerChangeDone
))
580 fPCDFunctionOverride
= true;
584 IOPMprot
* prot
= new IOPMprot
;
588 prot
->ourName
= fName
;
589 prot
->thePlatform
= gPlatform
;
594 pm_vars
= (void *) (uintptr_t) true;
601 //*********************************************************************************
604 // Free the data created by PMinit. Only called from IOService::free().
605 //*********************************************************************************
607 void IOService::PMfree ( void )
614 assert(fMachineState
== kIOPM_Finished
);
615 assert(fInsertInterestSet
== NULL
);
616 assert(fRemoveInterestSet
== NULL
);
617 assert(fNotifyChildArray
== NULL
);
618 assert(queue_empty(&pwrMgt
->RequestHead
));
619 assert(queue_empty(&fPMDriverCallQueue
));
621 if ( fSettleTimer
) {
622 thread_call_cancel(fSettleTimer
);
623 thread_call_free(fSettleTimer
);
627 thread_call_cancel(fAckTimer
);
628 thread_call_free(fAckTimer
);
632 thread_call_cancel(fIdleTimer
);
633 thread_call_free(fIdleTimer
);
636 if ( fDriverCallEntry
) {
637 thread_call_free(fDriverCallEntry
);
638 fDriverCallEntry
= NULL
;
644 if ( fActivityLock
) {
645 IOLockFree(fActivityLock
);
646 fActivityLock
= NULL
;
648 if ( fInterestedDrivers
) {
649 fInterestedDrivers
->release();
650 fInterestedDrivers
= NULL
;
652 if (fDriverCallParamSlots
&& fDriverCallParamPtr
) {
653 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
654 fDriverCallParamPtr
= 0;
655 fDriverCallParamSlots
= 0;
657 if ( fResponseArray
) {
658 fResponseArray
->release();
659 fResponseArray
= NULL
;
661 if ( fNotifyClientArray
) {
662 fNotifyClientArray
->release();
663 fNotifyClientArray
= NULL
;
665 if (fPowerStates
&& fNumberOfPowerStates
) {
666 IODelete(fPowerStates
, IOPMPSEntry
, fNumberOfPowerStates
);
667 fNumberOfPowerStates
= 0;
671 fPowerClients
->release();
688 void IOService::PMDebug( uint32_t event
, uintptr_t param1
, uintptr_t param2
)
690 OUR_PMLog(event
, param1
, param2
);
693 //*********************************************************************************
694 // [public] joinPMtree
696 // A policy-maker calls its nub here when initializing, to be attached into
697 // the power management hierarchy. The default function is to call the
698 // platform expert, which knows how to do it. This method is overridden
699 // by a nub subclass which may either know how to do it, or may need to
700 // take other action.
702 // This may be the only "power management" method used in a nub,
703 // meaning it may not be initialized for power management.
704 //*********************************************************************************
706 void IOService::joinPMtree ( IOService
* driver
)
708 IOPlatformExpert
* platform
;
710 platform
= getPlatform();
711 assert(platform
!= 0);
712 platform
->PMRegisterDevice(this, driver
);
716 //*********************************************************************************
717 // [deprecated] youAreRoot
719 // Power Managment is informing us that we are the root power domain.
720 //*********************************************************************************
722 IOReturn
IOService::youAreRoot ( void )
726 #endif /* !__LP64__ */
728 //*********************************************************************************
731 // Immediately stop driver callouts. Schedule an async stop request to detach
733 //*********************************************************************************
735 void IOService::PMstop ( void )
737 IOPMRequest
* request
;
744 if (fLockedFlags
.PMStop
)
746 PM_LOG2("%s: PMstop() already stopped\n", fName
);
751 // Inhibit future driver calls.
752 fLockedFlags
.PMStop
= true;
754 // Wait for all prior driver calls to finish.
755 waitForPMDriverCall();
759 // The rest of the work is performed async.
760 request
= acquirePMRequest( this, kIOPMRequestTypePMStop
);
763 PM_LOG2("%s: %p PMstop\n", getName(), this);
764 submitPMRequest( request
);
768 //*********************************************************************************
769 // [private] handlePMstop
771 // Disconnect the node from all parents and children in the power plane.
772 //*********************************************************************************
774 void IOService::handlePMstop ( IOPMRequest
* request
)
778 IOPowerConnection
* connection
;
779 IOService
* theChild
;
780 IOService
* theParent
;
783 PM_LOG2("%s: %p %s start\n", getName(), this, __FUNCTION__
);
785 // remove driver from prevent system sleep lists
786 getPMRootDomain()->updatePreventIdleSleepList(this, false);
787 getPMRootDomain()->updatePreventSystemSleepList(this, false);
789 // remove the property
790 removeProperty(kPwrMgtKey
);
793 iter
= getParentIterator(gIOPowerPlane
);
796 while ( (next
= iter
->getNextObject()) )
798 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
800 theParent
= (IOService
*)connection
->copyParentEntry(gIOPowerPlane
);
803 theParent
->removePowerChild(connection
);
804 theParent
->release();
811 // detach IOConnections
812 detachAbove( gIOPowerPlane
);
814 // no more power state changes
815 fParentsKnowState
= false;
818 iter
= getChildIterator(gIOPowerPlane
);
821 while ( (next
= iter
->getNextObject()) )
823 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
825 theChild
= ((IOService
*)(connection
->copyChildEntry(gIOPowerPlane
)));
828 // detach nub from child
829 connection
->detachFromChild(theChild
, gIOPowerPlane
);
832 // detach us from nub
833 detachFromChild(connection
, gIOPowerPlane
);
839 // Remove all interested drivers from the list, including the power
840 // controlling driver.
842 // Usually, the controlling driver and the policy-maker functionality
843 // are implemented by the same object, and without the deregistration,
844 // the object will be holding an extra retain on itself, and cannot
847 if ( fInterestedDrivers
)
849 IOPMinformeeList
* list
= fInterestedDrivers
;
853 while ((item
= list
->firstInList()))
855 list
->removeFromList(item
->whatObject
);
860 // Clear idle period to prevent idleTimerExpired() from servicing
861 // idle timer expirations.
863 fIdleTimerPeriod
= 0;
864 if (fIdleTimer
&& thread_call_cancel(fIdleTimer
))
867 PM_LOG2("%s: %p %s done\n", getName(), this, __FUNCTION__
);
870 //*********************************************************************************
871 // [public] addPowerChild
873 // Power Management is informing us who our children are.
874 //*********************************************************************************
876 IOReturn
IOService::addPowerChild ( IOService
* child
)
878 IOPowerConnection
* connection
= 0;
879 IOPMRequest
* requests
[3] = {0, 0, 0};
884 return kIOReturnBadArgument
;
886 if (!initialized
|| !child
->initialized
)
887 return IOPMNotYetInitialized
;
889 OUR_PMLog( kPMLogAddChild
, (uintptr_t) child
, 0 );
892 // Is this child already one of our children?
894 iter
= child
->getParentIterator( gIOPowerPlane
);
897 IORegistryEntry
* entry
;
900 while ((next
= iter
->getNextObject()))
902 if ((entry
= OSDynamicCast(IORegistryEntry
, next
)) &&
903 isChild(entry
, gIOPowerPlane
))
913 PM_LOG("%s: %s (%p) is already a child\n",
914 getName(), child
->getName(), child
);
918 // Add the child to the power plane immediately, but the
919 // joining connection is marked as not ready.
920 // We want the child to appear in the power plane before
921 // returning to the caller, but don't want the caller to
922 // block on the PM work loop.
924 connection
= new IOPowerConnection
;
928 // Create a chain of PM requests to perform the bottom-half
929 // work from the PM work loop.
931 requests
[0] = acquirePMRequest(
933 /* type */ kIOPMRequestTypeAddPowerChild1
);
935 requests
[1] = acquirePMRequest(
937 /* type */ kIOPMRequestTypeAddPowerChild2
);
939 requests
[2] = acquirePMRequest(
941 /* type */ kIOPMRequestTypeAddPowerChild3
);
943 if (!requests
[0] || !requests
[1] || !requests
[2])
946 requests
[0]->attachNextRequest( requests
[1] );
947 requests
[1]->attachNextRequest( requests
[2] );
950 connection
->start(this);
951 connection
->setAwaitingAck(false);
952 connection
->setReadyFlag(false);
954 attachToChild( connection
, gIOPowerPlane
);
955 connection
->attachToChild( child
, gIOPowerPlane
);
957 // connection needs to be released
958 requests
[0]->fArg0
= connection
;
959 requests
[1]->fArg0
= connection
;
960 requests
[2]->fArg0
= connection
;
962 submitPMRequest( requests
, 3 );
963 return kIOReturnSuccess
;
967 if (connection
) connection
->release();
968 if (requests
[0]) releasePMRequest(requests
[0]);
969 if (requests
[1]) releasePMRequest(requests
[1]);
970 if (requests
[2]) releasePMRequest(requests
[2]);
972 // Silent failure, to prevent platform drivers from adding the child
973 // to the root domain.
975 return kIOReturnSuccess
;
978 //*********************************************************************************
979 // [private] addPowerChild1
981 // Step 1/3 of adding a power child. Called on the power parent.
982 //*********************************************************************************
984 void IOService::addPowerChild1 ( IOPMRequest
* request
)
986 unsigned long tempDesire
= 0;
988 // Make us temporary usable before adding the child.
991 OUR_PMLog( kPMLogMakeUsable
, kPMLogMakeUsable
, 0 );
993 if (fControllingDriver
&& inPlane(gIOPowerPlane
) && fParentsKnowState
)
995 tempDesire
= fNumberOfPowerStates
- 1;
998 if (tempDesire
&& (IS_PM_ROOT
|| (fMaxPowerState
>= tempDesire
)))
1000 adjustPowerState(tempDesire
);
1004 //*********************************************************************************
1005 // [private] addPowerChild2
1007 // Step 2/3 of adding a power child. Called on the joining child.
1008 // Execution blocked behind addPowerChild1.
1009 //*********************************************************************************
1011 void IOService::addPowerChild2 ( IOPMRequest
* request
)
1013 IOPowerConnection
* connection
= (IOPowerConnection
*) request
->fArg0
;
1015 IOPMPowerFlags powerFlags
;
1017 unsigned long powerState
;
1018 unsigned long tempDesire
;
1020 PM_ASSERT_IN_GATE();
1021 parent
= (IOService
*) connection
->getParentEntry(gIOPowerPlane
);
1023 if (!parent
|| !inPlane(gIOPowerPlane
))
1025 PM_LOG("%s: addPowerChild2 not in power plane\n", getName());
1029 // Parent will be waiting for us to complete this stage.
1030 // It is safe to directly access parent's vars.
1032 knowsState
= (parent
->fPowerStates
) && (parent
->fParentsKnowState
);
1033 powerState
= parent
->fCurrentPowerState
;
1036 powerFlags
= parent
->fPowerStates
[powerState
].outputPowerFlags
;
1040 // Set our power parent.
1042 OUR_PMLog(kPMLogSetParent
, knowsState
, powerFlags
);
1044 setParentInfo( powerFlags
, connection
, knowsState
);
1046 connection
->setReadyFlag(true);
1048 if ( fControllingDriver
&& fParentsKnowState
)
1050 fMaxPowerState
= fControllingDriver
->maxCapabilityForDomainState(fParentsCurrentPowerFlags
);
1051 // initially change into the state we are already in
1052 tempDesire
= fControllingDriver
->initialPowerStateForDomainState(fParentsCurrentPowerFlags
);
1053 fPreviousRequestPowerFlags
= (IOPMPowerFlags
)(-1);
1054 adjustPowerState(tempDesire
);
1057 getPMRootDomain()->tagPowerPlaneService(this, &fPMActions
);
1060 //*********************************************************************************
1061 // [private] addPowerChild3
1063 // Step 3/3 of adding a power child. Called on the parent.
1064 // Execution blocked behind addPowerChild2.
1065 //*********************************************************************************
1067 void IOService::addPowerChild3 ( IOPMRequest
* request
)
1069 IOPowerConnection
* connection
= (IOPowerConnection
*) request
->fArg0
;
1071 IOPMrootDomain
* rootDomain
= getPMRootDomain();
1073 PM_ASSERT_IN_GATE();
1074 child
= (IOService
*) connection
->getChildEntry(gIOPowerPlane
);
1076 if (child
&& inPlane(gIOPowerPlane
))
1078 if ((this != rootDomain
) && child
->getProperty("IOPMStrictTreeOrder"))
1080 PM_LOG1("%s: strict PM order enforced\n", getName());
1081 fStrictTreeOrder
= true;
1085 rootDomain
->joinAggressiveness( child
);
1089 PM_LOG("%s: addPowerChild3 not in power plane\n", getName());
1092 connection
->release();
1096 //*********************************************************************************
1097 // [deprecated] setPowerParent
1099 // Power Management is informing us who our parent is.
1100 // If we have a controlling driver, find out, given our newly-informed
1101 // power domain state, what state it would be in, and then tell it
1102 // to assume that state.
1103 //*********************************************************************************
1105 IOReturn
IOService::setPowerParent (
1106 IOPowerConnection
* theParent
, bool stateKnown
, IOPMPowerFlags powerFlags
)
1108 return kIOReturnUnsupported
;
1110 #endif /* !__LP64__ */
1112 //*********************************************************************************
1113 // [public] removePowerChild
1115 // Called on a parent whose child is being removed by PMstop().
1116 //*********************************************************************************
1118 IOReturn
IOService::removePowerChild ( IOPowerConnection
* theNub
)
1120 IORegistryEntry
* theChild
;
1122 PM_ASSERT_IN_GATE();
1123 OUR_PMLog( kPMLogRemoveChild
, 0, 0 );
1127 // detach nub from child
1128 theChild
= theNub
->copyChildEntry(gIOPowerPlane
);
1131 theNub
->detachFromChild(theChild
, gIOPowerPlane
);
1132 theChild
->release();
1134 // detach from the nub
1135 detachFromChild(theNub
, gIOPowerPlane
);
1137 // Are we awaiting an ack from this child?
1138 if ( theNub
->getAwaitingAck() )
1140 // yes, pretend we got one
1141 theNub
->setAwaitingAck(false);
1142 if (fHeadNotePendingAcks
!= 0 )
1144 // that's one fewer ack to worry about
1145 fHeadNotePendingAcks
--;
1147 // is that the last?
1148 if ( fHeadNotePendingAcks
== 0 )
1152 // Request unblocked, work queue
1153 // should re-scan all busy requests.
1154 gIOPMWorkQueue
->incrementProducerCount();
1161 // A child has gone away, re-scan children desires and clamp bits.
1162 // The fPendingAdjustPowerRequest helps to reduce redundant parent work.
1164 if (!fAdjustPowerScheduled
)
1166 IOPMRequest
* request
;
1167 request
= acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState
);
1170 submitPMRequest( request
);
1171 fAdjustPowerScheduled
= true;
1178 //*********************************************************************************
1179 // [public] registerPowerDriver
1181 // A driver has called us volunteering to control power to our device.
1182 //*********************************************************************************
1184 IOReturn
IOService::registerPowerDriver (
1185 IOService
* powerDriver
,
1186 IOPMPowerState
* powerStates
,
1187 unsigned long numberOfStates
)
1189 IOPMRequest
* request
;
1190 IOPMPSEntry
* powerStatesCopy
= 0;
1193 return IOPMNotYetInitialized
;
1195 // Validate arguments.
1196 if (!powerStates
|| (numberOfStates
< 2))
1198 OUR_PMLog(kPMLogControllingDriverErr5
, numberOfStates
, 0);
1199 return kIOReturnBadArgument
;
1202 if (!powerDriver
|| !powerDriver
->initialized
)
1204 OUR_PMLog(kPMLogControllingDriverErr4
, 0, 0);
1205 return kIOReturnBadArgument
;
1208 if (powerStates
[0].version
!= kIOPMPowerStateVersion1
)
1210 OUR_PMLog(kPMLogControllingDriverErr1
, powerStates
[0].version
, 0);
1211 return kIOReturnBadArgument
;
1215 // Make a copy of the supplied power state array.
1216 powerStatesCopy
= IONew(IOPMPSEntry
, numberOfStates
);
1217 if (!powerStatesCopy
)
1220 for (uint32_t i
= 0; i
< numberOfStates
; i
++)
1222 powerStatesCopy
[i
].capabilityFlags
= powerStates
[i
].capabilityFlags
;
1223 powerStatesCopy
[i
].outputPowerFlags
= powerStates
[i
].outputPowerCharacter
;
1224 powerStatesCopy
[i
].inputPowerFlags
= powerStates
[i
].inputPowerRequirement
;
1225 powerStatesCopy
[i
].staticPower
= powerStates
[i
].staticPower
;
1226 powerStatesCopy
[i
].settleUpTime
= powerStates
[i
].settleUpTime
;
1227 powerStatesCopy
[i
].settleDownTime
= powerStates
[i
].settleDownTime
;
1230 request
= acquirePMRequest( this, kIOPMRequestTypeRegisterPowerDriver
);
1234 powerDriver
->retain();
1235 request
->fArg0
= (void *) powerDriver
;
1236 request
->fArg1
= (void *) powerStatesCopy
;
1237 request
->fArg2
= (void *) numberOfStates
;
1239 submitPMRequest( request
);
1240 return kIOReturnSuccess
;
1244 if (powerStatesCopy
)
1245 IODelete(powerStatesCopy
, IOPMPSEntry
, numberOfStates
);
1246 return kIOReturnNoMemory
;
1249 //*********************************************************************************
1250 // [private] handleRegisterPowerDriver
1251 //*********************************************************************************
1253 void IOService::handleRegisterPowerDriver ( IOPMRequest
* request
)
1255 IOService
* powerDriver
= (IOService
*) request
->fArg0
;
1256 IOPMPSEntry
* powerStates
= (IOPMPSEntry
*) request
->fArg1
;
1257 unsigned long numberOfStates
= (unsigned long) request
->fArg2
;
1262 PM_ASSERT_IN_GATE();
1263 assert(powerStates
);
1264 assert(powerDriver
);
1265 assert(numberOfStates
> 1);
1267 if ( !fNumberOfPowerStates
)
1269 OUR_PMLog(kPMLogControllingDriver
,
1270 (unsigned long) numberOfStates
,
1271 (unsigned long) kIOPMPowerStateVersion1
);
1273 fPowerStates
= powerStates
;
1274 fNumberOfPowerStates
= numberOfStates
;
1275 fControllingDriver
= powerDriver
;
1276 fCurrentCapabilityFlags
= fPowerStates
[0].capabilityFlags
;
1278 // make a mask of all the character bits we know about
1279 fOutputPowerCharacterFlags
= 0;
1280 for ( i
= 0; i
< numberOfStates
; i
++ ) {
1281 fOutputPowerCharacterFlags
|= fPowerStates
[i
].outputPowerFlags
;
1282 if (!fDeviceUsablePowerState
&&
1283 (fPowerStates
[i
].capabilityFlags
& IOPMDeviceUsable
))
1285 // The minimum power state that the device is usable
1286 fDeviceUsablePowerState
= i
;
1290 // Register powerDriver as interested, unless already done.
1291 // We don't want to register the default implementation since
1292 // it does nothing. One ramification of not always registering
1293 // is the one fewer retain count held.
1295 root
= getPlatform()->getProvider();
1298 ((OSMemberFunctionCast(void (*)(void),
1299 root
, &IOService::powerStateDidChangeTo
)) !=
1300 ((OSMemberFunctionCast(void (*)(void),
1301 this, &IOService::powerStateDidChangeTo
)))) ||
1302 ((OSMemberFunctionCast(void (*)(void),
1303 root
, &IOService::powerStateWillChangeTo
)) !=
1304 ((OSMemberFunctionCast(void (*)(void),
1305 this, &IOService::powerStateWillChangeTo
)))))
1307 if (fInterestedDrivers
->findItem(powerDriver
) == NULL
)
1310 fInterestedDrivers
->appendNewInformee(powerDriver
);
1315 // Examine all existing power clients and perform limit check.
1319 iter
= OSCollectionIterator::withCollection(fPowerClients
);
1322 const OSSymbol
* client
;
1323 while ((client
= (const OSSymbol
*) iter
->getNextObject()))
1325 uint32_t powerState
= getPowerStateForClient(client
);
1326 if (powerState
>= numberOfStates
)
1328 updatePowerClient(client
, numberOfStates
- 1);
1335 if ( inPlane(gIOPowerPlane
) && fParentsKnowState
)
1337 unsigned long tempDesire
;
1338 fMaxPowerState
= fControllingDriver
->maxCapabilityForDomainState(fParentsCurrentPowerFlags
);
1339 // initially change into the state we are already in
1340 tempDesire
= fControllingDriver
->initialPowerStateForDomainState(fParentsCurrentPowerFlags
);
1341 adjustPowerState(tempDesire
);
1346 OUR_PMLog(kPMLogControllingDriverErr2
, numberOfStates
, 0);
1347 IODelete(powerStates
, IOPMPSEntry
, numberOfStates
);
1350 powerDriver
->release();
1353 //*********************************************************************************
1354 // [public] registerInterestedDriver
1356 // Add the caller to our list of interested drivers and return our current
1357 // power state. If we don't have a power-controlling driver yet, we will
1358 // call this interested driver again later when we do get a driver and find
1359 // out what the current power state of the device is.
1360 //*********************************************************************************
1362 IOPMPowerFlags
IOService::registerInterestedDriver ( IOService
* driver
)
1364 IOPMRequest
* request
;
1367 if (!driver
|| !initialized
|| !fInterestedDrivers
)
1371 signal
= (!fInsertInterestSet
&& !fRemoveInterestSet
);
1372 if (fInsertInterestSet
== NULL
)
1373 fInsertInterestSet
= OSSet::withCapacity(4);
1374 if (fInsertInterestSet
)
1376 fInsertInterestSet
->setObject(driver
);
1377 if (fRemoveInterestSet
)
1378 fRemoveInterestSet
->removeObject(driver
);
1384 request
= acquirePMRequest( this, kIOPMRequestTypeInterestChanged
);
1386 submitPMRequest( request
);
1389 // This return value cannot be trusted, but return a value
1390 // for those clients that care.
1392 OUR_PMLog(kPMLogInterestedDriver
, kIOPMDeviceUsable
, 2);
1393 return kIOPMDeviceUsable
;
1396 //*********************************************************************************
1397 // [public] deRegisterInterestedDriver
1398 //*********************************************************************************
1400 IOReturn
IOService::deRegisterInterestedDriver ( IOService
* driver
)
1402 IOPMinformeeList
* list
;
1403 IOPMinformee
* item
;
1404 IOPMRequest
* request
;
1408 return kIOReturnBadArgument
;
1409 if (!initialized
|| !fInterestedDrivers
)
1410 return IOPMNotPowerManaged
;
1413 signal
= (!fRemoveInterestSet
&& !fInsertInterestSet
);
1414 if (fRemoveInterestSet
== NULL
)
1415 fRemoveInterestSet
= OSSet::withCapacity(4);
1416 if (fRemoveInterestSet
)
1418 fRemoveInterestSet
->setObject(driver
);
1419 if (fInsertInterestSet
)
1420 fInsertInterestSet
->removeObject(driver
);
1422 list
= fInterestedDrivers
;
1423 item
= list
->findItem(driver
);
1424 if (item
&& item
->active
)
1426 item
->active
= false;
1427 waitForPMDriverCall( driver
);
1434 request
= acquirePMRequest( this, kIOPMRequestTypeInterestChanged
);
1436 submitPMRequest( request
);
1442 //*********************************************************************************
1443 // [private] handleInterestChanged
1445 // Handle interest added or removed.
1446 //*********************************************************************************
1448 void IOService::handleInterestChanged( IOPMRequest
* request
)
1451 IOPMinformee
* informee
;
1452 IOPMinformeeList
* list
= fInterestedDrivers
;
1456 if (fInsertInterestSet
)
1458 while ((driver
= (IOService
*) fInsertInterestSet
->getAnyObject()))
1460 if (list
->findItem(driver
) == NULL
)
1462 informee
= list
->appendNewInformee(driver
);
1464 fInsertInterestSet
->removeObject(driver
);
1466 fInsertInterestSet
->release();
1467 fInsertInterestSet
= 0;
1470 if (fRemoveInterestSet
)
1472 while ((driver
= (IOService
*) fRemoveInterestSet
->getAnyObject()))
1474 informee
= list
->findItem(driver
);
1477 // Clean-up async interest acknowledgement
1478 if (fHeadNotePendingAcks
&& informee
->timer
)
1480 informee
->timer
= 0;
1481 fHeadNotePendingAcks
--;
1483 list
->removeFromList(driver
);
1485 fRemoveInterestSet
->removeObject(driver
);
1487 fRemoveInterestSet
->release();
1488 fRemoveInterestSet
= 0;
1494 //*********************************************************************************
1495 // [public] acknowledgePowerChange
1497 // After we notified one of the interested drivers or a power-domain child
1498 // of an impending change in power, it has called to say it is now
1499 // prepared for the change. If this object is the last to
1500 // acknowledge this change, we take whatever action we have been waiting
1502 // That may include acknowledging to our parent. In this case, we do it
1503 // last of all to insure that this doesn't cause the parent to call us some-
1504 // where else and alter data we are relying on here (like the very existance
1505 // of a "current change note".)
1506 //*********************************************************************************
1508 IOReturn
IOService::acknowledgePowerChange ( IOService
* whichObject
)
1510 IOPMRequest
* request
;
1513 return IOPMNotYetInitialized
;
1515 return kIOReturnBadArgument
;
1517 request
= acquirePMRequest( this, kIOPMRequestTypeAckPowerChange
);
1519 return kIOReturnNoMemory
;
1521 whichObject
->retain();
1522 request
->fArg0
= whichObject
;
1524 submitPMRequest( request
);
1528 //*********************************************************************************
1529 // [private] handleAcknowledgePowerChange
1530 //*********************************************************************************
1532 bool IOService::handleAcknowledgePowerChange ( IOPMRequest
* request
)
1534 IOPMinformee
* informee
;
1535 unsigned long childPower
= kIOPMUnknown
;
1536 IOService
* theChild
;
1537 IOService
* whichObject
;
1538 bool all_acked
= false;
1540 PM_ASSERT_IN_GATE();
1541 whichObject
= (IOService
*) request
->fArg0
;
1542 assert(whichObject
);
1544 // one of our interested drivers?
1545 informee
= fInterestedDrivers
->findItem( whichObject
);
1546 if ( informee
== NULL
)
1548 if ( !isChild(whichObject
, gIOPowerPlane
) )
1550 OUR_PMLog(kPMLogAcknowledgeErr1
, 0, 0);
1553 OUR_PMLog(kPMLogChildAcknowledge
, fHeadNotePendingAcks
, 0);
1556 OUR_PMLog(kPMLogDriverAcknowledge
, fHeadNotePendingAcks
, 0);
1559 if ( fHeadNotePendingAcks
!= 0 )
1561 assert(fPowerStates
!= NULL
);
1563 // yes, make sure we're expecting acks
1564 if ( informee
!= NULL
)
1566 // it's an interested driver
1567 // make sure we're expecting this ack
1568 if ( informee
->timer
!= 0 )
1570 #if LOG_SETPOWER_TIMES
1571 if (informee
->timer
> 0)
1573 uint64_t nsec
= computeTimeDeltaNS(&informee
->startTime
);
1574 if (nsec
> LOG_SETPOWER_TIMES
)
1575 PM_LOG("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) async took %d ms\n",
1576 informee
->whatObject
->getName(),
1577 (fDriverCallReason
== kDriverCallInformPreChange
) ? "Will" : "Did",
1578 informee
->whatObject
,
1579 fName
, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_US(nsec
));
1581 uint16_t logType
= (fDriverCallReason
== kDriverCallInformPreChange
)
1582 ? kIOPMEventTypePSWillChangeTo
1583 : kIOPMEventTypePSDidChangeTo
;
1585 PMEventDetails
*details
= PMEventDetails::eventDetails(
1589 informee
->whatObject
->getName(),
1593 getPMRootDomain()->recordAndReleasePMEventGated( details
);
1597 informee
->timer
= 0;
1598 // that's one fewer to worry about
1599 fHeadNotePendingAcks
--;
1601 // this driver has already acked
1602 OUR_PMLog(kPMLogAcknowledgeErr2
, 0, 0);
1606 // make sure we're expecting this ack
1607 if ( ((IOPowerConnection
*)whichObject
)->getAwaitingAck() )
1609 // that's one fewer to worry about
1610 fHeadNotePendingAcks
--;
1611 ((IOPowerConnection
*)whichObject
)->setAwaitingAck(false);
1612 theChild
= (IOService
*)whichObject
->copyChildEntry(gIOPowerPlane
);
1615 childPower
= theChild
->currentPowerConsumption();
1616 theChild
->release();
1618 if ( childPower
== kIOPMUnknown
)
1620 fHeadNotePowerArrayEntry
->staticPower
= kIOPMUnknown
;
1622 if (fHeadNotePowerArrayEntry
->staticPower
!= kIOPMUnknown
)
1624 fHeadNotePowerArrayEntry
->staticPower
+= childPower
;
1630 if ( fHeadNotePendingAcks
== 0 ) {
1631 // yes, stop the timer
1633 // and now we can continue
1637 OUR_PMLog(kPMLogAcknowledgeErr3
, 0, 0); // not expecting anybody to ack
1642 whichObject
->release();
1647 //*********************************************************************************
1648 // [public] acknowledgeSetPowerState
1650 // After we instructed our controlling driver to change power states,
1651 // it has called to say it has finished doing so.
1652 // We continue to process the power state change.
1653 //*********************************************************************************
1655 IOReturn
IOService::acknowledgeSetPowerState ( void )
1657 IOPMRequest
* request
;
1660 return IOPMNotYetInitialized
;
1662 request
= acquirePMRequest( this, kIOPMRequestTypeAckSetPowerState
);
1664 return kIOReturnNoMemory
;
1666 submitPMRequest( request
);
1667 return kIOReturnSuccess
;
1670 //*********************************************************************************
1671 // [private] adjustPowerState
1672 //*********************************************************************************
1674 void IOService::adjustPowerState ( uint32_t clamp
)
1676 PM_ASSERT_IN_GATE();
1677 computeDesiredState(clamp
, false);
1678 if (fControllingDriver
&& fParentsKnowState
&& inPlane(gIOPowerPlane
))
1680 IOPMPowerChangeFlags changeFlags
= kIOPMSelfInitiated
;
1682 // Indicate that children desires must be ignored, and do not ask
1683 // apps for permission to drop power. This is used by root domain
1684 // for demand sleep.
1686 if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)
1687 changeFlags
|= (kIOPMIgnoreChildren
| kIOPMSkipAskPowerDown
);
1690 /* flags */ changeFlags
,
1691 /* power state */ fDesiredPowerState
,
1692 /* domain flags */ 0,
1694 /* parent flags */ 0);
1698 //*********************************************************************************
1699 // [public] synchronizePowerTree
1700 //*********************************************************************************
1702 IOReturn
IOService::synchronizePowerTree (
1703 IOOptionBits options
,
1704 IOService
* notifyRoot
)
1706 IOPMRequest
* request_c
= 0;
1707 IOPMRequest
* request_s
;
1709 if (this != getPMRootDomain())
1710 return kIOReturnBadArgument
;
1712 return kIOPMNotYetInitialized
;
1718 // Cancels don't need to be synchronized.
1719 nr
= acquirePMRequest(notifyRoot
, kIOPMRequestTypeChildNotifyDelayCancel
);
1720 if (nr
) submitPMRequest(nr
);
1721 nr
= acquirePMRequest(getPMRootDomain(), kIOPMRequestTypeChildNotifyDelayCancel
);
1722 if (nr
) submitPMRequest(nr
);
1725 request_s
= acquirePMRequest( this, kIOPMRequestTypeSynchronizePowerTree
);
1727 goto error_no_memory
;
1729 if (options
& kIOPMSyncCancelPowerDown
)
1730 request_c
= acquirePMRequest( this, kIOPMRequestTypeIdleCancel
);
1733 request_c
->attachNextRequest( request_s
);
1734 submitPMRequest(request_c
);
1737 request_s
->fArg0
= (void *)(uintptr_t) options
;
1738 submitPMRequest(request_s
);
1740 return kIOReturnSuccess
;
1743 if (request_c
) releasePMRequest(request_c
);
1744 if (request_s
) releasePMRequest(request_s
);
1745 return kIOReturnNoMemory
;
1748 //*********************************************************************************
1749 // [private] handleSynchronizePowerTree
1750 //*********************************************************************************
1752 void IOService::handleSynchronizePowerTree ( IOPMRequest
* request
)
1754 PM_ASSERT_IN_GATE();
1755 if (fControllingDriver
&& fParentsKnowState
&& inPlane(gIOPowerPlane
) &&
1756 (fCurrentPowerState
== fNumberOfPowerStates
- 1))
1758 IOOptionBits options
= (uintptr_t) request
->fArg0
;
1761 /* flags */ kIOPMSelfInitiated
| kIOPMSynchronize
|
1762 (options
& kIOPMSyncNoChildNotify
),
1763 /* power state */ fCurrentPowerState
,
1764 /* domain flags */ 0,
1766 /* parent flags */ 0);
1771 //*********************************************************************************
1772 // [deprecated] powerDomainWillChangeTo
1774 // Called by the power-hierarchy parent notifying of a new power state
1775 // in the power domain.
1776 // We enqueue a parent power-change to our queue of power changes.
1777 // This may or may not cause us to change power, depending on what
1778 // kind of change is occuring in the domain.
1779 //*********************************************************************************
1781 IOReturn
IOService::powerDomainWillChangeTo (
1782 IOPMPowerFlags newPowerFlags
,
1783 IOPowerConnection
* whichParent
)
1786 return kIOReturnUnsupported
;
1788 #endif /* !__LP64__ */
1790 //*********************************************************************************
1791 // [private] handlePowerDomainWillChangeTo
1792 //*********************************************************************************
1794 void IOService::handlePowerDomainWillChangeTo ( IOPMRequest
* request
)
1796 IOPMPowerFlags parentPowerFlags
= (IOPMPowerFlags
) request
->fArg0
;
1797 IOPowerConnection
* whichParent
= (IOPowerConnection
*) request
->fArg1
;
1798 IOPMPowerChangeFlags parentChangeFlags
= (IOPMPowerChangeFlags
)(uintptr_t) request
->fArg2
;
1799 IOPMPowerChangeFlags myChangeFlags
;
1802 IOPowerConnection
* connection
;
1803 IOPMPowerStateIndex maxPowerState
;
1804 IOPMPowerFlags combinedPowerFlags
;
1805 bool savedParentsKnowState
;
1806 IOReturn result
= IOPMAckImplied
;
1808 PM_ASSERT_IN_GATE();
1809 OUR_PMLog(kPMLogWillChange
, parentPowerFlags
, 0);
1811 if (!inPlane(gIOPowerPlane
) || !whichParent
|| !whichParent
->getAwaitingAck())
1813 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__
);
1817 savedParentsKnowState
= fParentsKnowState
;
1819 // Combine parents' output power flags.
1821 combinedPowerFlags
= 0;
1823 iter
= getParentIterator(gIOPowerPlane
);
1826 while ( (next
= iter
->getNextObject()) )
1828 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
1830 if ( connection
== whichParent
)
1831 combinedPowerFlags
|= parentPowerFlags
;
1833 combinedPowerFlags
|= connection
->parentCurrentPowerFlags();
1839 // If our initial change has yet to occur, then defer the power change
1840 // until after the power domain has completed its power transition.
1842 if ( fControllingDriver
&& !fInitialPowerChange
)
1844 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1845 combinedPowerFlags
);
1847 // Use kIOPMSynchronize below instead of kIOPMRootBroadcastFlags
1848 // to avoid propagating the root change flags if any service must
1849 // change power state due to root's will-change notification.
1850 // Root does not change power state for kIOPMSynchronize.
1852 myChangeFlags
= kIOPMParentInitiated
| kIOPMDomainWillChange
|
1853 (parentChangeFlags
& kIOPMSynchronize
);
1855 result
= startPowerChange(
1856 /* flags */ myChangeFlags
,
1857 /* power state */ maxPowerState
,
1858 /* domain flags */ combinedPowerFlags
,
1859 /* connection */ whichParent
,
1860 /* parent flags */ parentPowerFlags
);
1863 // If parent is dropping power, immediately update the parent's
1864 // capability flags. Any future merging of parent(s) combined
1865 // power flags should account for this power drop.
1867 if (parentChangeFlags
& kIOPMDomainPowerDrop
)
1869 setParentInfo(parentPowerFlags
, whichParent
, true);
1872 // Parent is expecting an ACK from us. If we did not embark on a state
1873 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
1874 // still required to issue an ACK to our parent.
1876 if (IOPMAckImplied
== result
)
1879 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
1883 parent
->acknowledgePowerChange( whichParent
);
1889 // Drop the retain from notifyChild().
1890 if (whichParent
) whichParent
->release();
1894 //*********************************************************************************
1895 // [deprecated] powerDomainDidChangeTo
1897 // Called by the power-hierarchy parent after the power state of the power domain
1898 // has settled at a new level.
1899 // We enqueue a parent power-change to our queue of power changes.
1900 // This may or may not cause us to change power, depending on what
1901 // kind of change is occuring in the domain.
1902 //*********************************************************************************
1904 IOReturn
IOService::powerDomainDidChangeTo (
1905 IOPMPowerFlags newPowerFlags
,
1906 IOPowerConnection
* whichParent
)
1909 return kIOReturnUnsupported
;
1911 #endif /* !__LP64__ */
1913 //*********************************************************************************
1914 // [private] handlePowerDomainDidChangeTo
1915 //*********************************************************************************
1917 void IOService::handlePowerDomainDidChangeTo ( IOPMRequest
* request
)
1919 IOPMPowerFlags parentPowerFlags
= (IOPMPowerFlags
) request
->fArg0
;
1920 IOPowerConnection
* whichParent
= (IOPowerConnection
*) request
->fArg1
;
1921 IOPMPowerChangeFlags parentChangeFlags
= (IOPMPowerChangeFlags
)(uintptr_t) request
->fArg2
;
1922 IOPMPowerChangeFlags myChangeFlags
;
1923 IOPMPowerStateIndex maxPowerState
;
1924 IOPMPowerStateIndex initialDesire
= 0;
1925 bool computeDesire
= false;
1926 bool desireChanged
= false;
1927 bool savedParentsKnowState
;
1928 IOReturn result
= IOPMAckImplied
;
1930 PM_ASSERT_IN_GATE();
1931 OUR_PMLog(kPMLogDidChange
, parentPowerFlags
, 0);
1933 if (!inPlane(gIOPowerPlane
) || !whichParent
|| !whichParent
->getAwaitingAck())
1935 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__
);
1939 savedParentsKnowState
= fParentsKnowState
;
1941 setParentInfo(parentPowerFlags
, whichParent
, true);
1943 if ( fControllingDriver
)
1945 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1946 fParentsCurrentPowerFlags
);
1948 if (fInitialPowerChange
)
1950 computeDesire
= true;
1951 initialDesire
= fControllingDriver
->initialPowerStateForDomainState(
1952 fParentsCurrentPowerFlags
);
1954 else if (parentChangeFlags
& kIOPMRootChangeUp
)
1956 if (fAdvisoryTickleUsed
)
1958 // On system wake, re-compute the desired power state since
1959 // gIOPMAdvisoryTickleEnabled will change for a full wake,
1960 // which is an input to computeDesiredState(). This is not
1961 // necessary for a dark wake because powerChangeDone() will
1962 // handle the dark to full wake case, but it does no harm.
1964 desireChanged
= true;
1967 if (fResetPowerStateOnWake
)
1969 // Query the driver for the desired power state on system wake.
1970 // Default implementation returns the lowest power state.
1972 IOPMPowerStateIndex wakePowerState
=
1973 fControllingDriver
->initialPowerStateForDomainState(
1974 kIOPMRootDomainState
| kIOPMPowerOn
);
1976 // fDesiredPowerState was adjusted before going to sleep
1977 // with fDeviceDesire at min.
1979 if (wakePowerState
> fDesiredPowerState
)
1981 // Must schedule a power adjustment if we changed the
1982 // device desire. That will update the desired domain
1983 // power on the parent power connection and ping the
1984 // power parent if necessary.
1986 updatePowerClient(gIOPMPowerClientDevice
, wakePowerState
);
1987 desireChanged
= true;
1992 if (computeDesire
|| desireChanged
)
1993 computeDesiredState(initialDesire
, false);
1995 // Absorb and propagate parent's broadcast flags
1996 myChangeFlags
= kIOPMParentInitiated
| kIOPMDomainDidChange
|
1997 (parentChangeFlags
& kIOPMRootBroadcastFlags
);
1999 result
= startPowerChange(
2000 /* flags */ myChangeFlags
,
2001 /* power state */ maxPowerState
,
2002 /* domain flags */ fParentsCurrentPowerFlags
,
2003 /* connection */ whichParent
,
2004 /* parent flags */ 0);
2007 // Parent is expecting an ACK from us. If we did not embark on a state
2008 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
2009 // still required to issue an ACK to our parent.
2011 if (IOPMAckImplied
== result
)
2014 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
2018 parent
->acknowledgePowerChange( whichParent
);
2023 // If the parent registers its power driver late, then this is the
2024 // first opportunity to tell our parent about our desire. Or if the
2025 // child's desire changed during a parent change notify.
2027 if ((!savedParentsKnowState
&& fParentsKnowState
) || desireChanged
)
2029 PM_LOG1("%s::powerDomainDidChangeTo parentsKnowState %d\n",
2030 getName(), fParentsKnowState
);
2031 requestDomainPower( fDesiredPowerState
);
2035 // Drop the retain from notifyChild().
2036 if (whichParent
) whichParent
->release();
2039 //*********************************************************************************
2040 // [private] setParentInfo
2042 // Set our connection data for one specific parent, and then combine all the parent
2044 //*********************************************************************************
2046 void IOService::setParentInfo (
2047 IOPMPowerFlags newPowerFlags
,
2048 IOPowerConnection
* whichParent
,
2053 IOPowerConnection
* conn
;
2055 PM_ASSERT_IN_GATE();
2057 // set our connection data
2058 whichParent
->setParentCurrentPowerFlags(newPowerFlags
);
2059 whichParent
->setParentKnowsState(knowsState
);
2061 // recompute our parent info
2062 fParentsCurrentPowerFlags
= 0;
2063 fParentsKnowState
= true;
2065 iter
= getParentIterator(gIOPowerPlane
);
2068 while ( (next
= iter
->getNextObject()) )
2070 if ( (conn
= OSDynamicCast(IOPowerConnection
, next
)) )
2072 fParentsKnowState
&= conn
->parentKnowsState();
2073 fParentsCurrentPowerFlags
|= conn
->parentCurrentPowerFlags();
2080 //******************************************************************************
2081 // [private] trackSystemSleepPreventers
2082 //******************************************************************************
2084 void IOService::trackSystemSleepPreventers(
2085 IOPMPowerStateIndex oldPowerState
,
2086 IOPMPowerStateIndex newPowerState
,
2087 IOPMPowerChangeFlags changeFlags __unused
)
2089 IOPMPowerFlags oldCapability
, newCapability
;
2091 oldCapability
= fPowerStates
[oldPowerState
].capabilityFlags
&
2092 (kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
2093 newCapability
= fPowerStates
[newPowerState
].capabilityFlags
&
2094 (kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
2096 if (fHeadNoteChangeFlags
& kIOPMInitialPowerChange
)
2098 if (oldCapability
== newCapability
)
2101 if ((oldCapability
^ newCapability
) & kIOPMPreventIdleSleep
)
2103 #if SUPPORT_IDLE_CANCEL
2104 if ((oldCapability
& kIOPMPreventIdleSleep
) == 0)
2106 IOPMRequest
* cancelRequest
;
2108 cancelRequest
= acquirePMRequest( getPMRootDomain(), kIOPMRequestTypeIdleCancel
);
2111 submitPMRequest( cancelRequest
);
2116 getPMRootDomain()->updatePreventIdleSleepList(this,
2117 ((oldCapability
& kIOPMPreventIdleSleep
) == 0));
2120 if ((oldCapability
^ newCapability
) & kIOPMPreventSystemSleep
)
2123 getPMRootDomain()->updatePreventSystemSleepList(this,
2124 ((oldCapability
& kIOPMPreventSystemSleep
) == 0));
2128 //*********************************************************************************
2129 // [public] requestPowerDomainState
2131 // Called on a power parent when a child's power requirement changes.
2132 //*********************************************************************************
2134 IOReturn
IOService::requestPowerDomainState(
2135 IOPMPowerFlags childRequestPowerFlags
,
2136 IOPowerConnection
* childConnection
,
2137 unsigned long specification
)
2139 IOPMPowerStateIndex ps
;
2140 IOPMPowerFlags outputPowerFlags
;
2142 IOPMRequest
* subRequest
;
2143 bool adjustPower
= false;
2146 return IOPMNotYetInitialized
;
2148 if (gIOPMWorkLoop
->onThread() == false)
2150 PM_LOG("%s::requestPowerDomainState\n", getName());
2151 return kIOReturnSuccess
;
2154 OUR_PMLog(kPMLogRequestDomain
, childRequestPowerFlags
, specification
);
2156 if (!isChild(childConnection
, gIOPowerPlane
))
2157 return kIOReturnNotAttached
;
2159 if (!fControllingDriver
|| !fNumberOfPowerStates
)
2160 return kIOReturnNotReady
;
2162 child
= (IOService
*) childConnection
->getChildEntry(gIOPowerPlane
);
2165 // Merge in the power flags contributed by this power parent
2166 // at its current or impending power state.
2168 outputPowerFlags
= fPowerStates
[fCurrentPowerState
].outputPowerFlags
;
2169 if (fMachineState
!= kIOPM_Finished
)
2171 if (IS_POWER_DROP
&& !IS_ROOT_DOMAIN
)
2173 // Use the lower power state when dropping power.
2174 // Must be careful since a power drop can be canceled
2175 // from the following states:
2176 // - kIOPM_OurChangeTellClientsPowerDown
2177 // - kIOPM_OurChangeTellPriorityClientsPowerDown
2179 // The child must not wait for this parent to raise power
2180 // if the power drop was cancelled. The solution is to cancel
2181 // the power drop if possible, then schedule an adjustment to
2182 // re-evaluate the parent's power state.
2184 // Root domain is excluded to avoid idle sleep issues. And permit
2185 // root domain children to pop up when system is going to sleep.
2187 if ((fMachineState
== kIOPM_OurChangeTellClientsPowerDown
) ||
2188 (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
))
2190 fDoNotPowerDown
= true; // cancel power drop
2191 adjustPower
= true; // schedule an adjustment
2192 PM_LOG1("%s: power drop cancelled in state %u by %s\n",
2193 getName(), fMachineState
, child
->getName());
2197 // Beyond cancellation point, report the impending state.
2199 fPowerStates
[fHeadNotePowerState
].outputPowerFlags
;
2202 else if (IS_POWER_RISE
)
2204 // When raising power, must report the output power flags from
2205 // child's perspective. A child power request may arrive while
2206 // parent is transitioning upwards. If a request arrives after
2207 // setParentInfo() has already recorded the output power flags
2208 // for the next power state, then using the power supplied by
2209 // fCurrentPowerState is incorrect, and might cause the child
2210 // to wait when it should not.
2212 outputPowerFlags
= childConnection
->parentCurrentPowerFlags();
2215 child
->fHeadNoteDomainTargetFlags
|= outputPowerFlags
;
2217 // Map child's requested power flags to one of our power state.
2219 for (ps
= 0; ps
< fNumberOfPowerStates
; ps
++)
2221 if ((fPowerStates
[ps
].outputPowerFlags
& childRequestPowerFlags
) ==
2222 (fOutputPowerCharacterFlags
& childRequestPowerFlags
))
2225 if (ps
>= fNumberOfPowerStates
)
2227 ps
= 0; // should never happen
2230 // Conditions that warrants a power adjustment on this parent.
2231 // Adjust power will also propagate any changes to the child's
2232 // prevent idle/sleep flags towards the root domain.
2234 if (!childConnection
->childHasRequestedPower() ||
2235 (ps
!= childConnection
->getDesiredDomainState()))
2238 #if ENABLE_DEBUG_LOGS
2241 PM_LOG("requestPowerDomainState[%s]: %s, init %d, %u->%u\n",
2242 getName(), child
->getName(),
2243 !childConnection
->childHasRequestedPower(),
2244 (uint32_t) childConnection
->getDesiredDomainState(),
2249 // Record the child's desires on the connection.
2250 childConnection
->setChildHasRequestedPower();
2251 childConnection
->setDesiredDomainState( ps
);
2253 // Schedule a request to re-evaluate all children desires and
2254 // adjust power state. Submit a request if one wasn't pending,
2255 // or if the current request is part of a call tree.
2257 if (adjustPower
&& !fDeviceOverrideEnabled
&&
2258 (!fAdjustPowerScheduled
|| gIOPMRequest
->getRootRequest()))
2260 subRequest
= acquirePMRequest(
2261 this, kIOPMRequestTypeAdjustPowerState
, gIOPMRequest
);
2264 submitPMRequest( subRequest
);
2265 fAdjustPowerScheduled
= true;
2269 return kIOReturnSuccess
;
2272 //*********************************************************************************
2273 // [public] temporaryPowerClampOn
2275 // A power domain wants to clamp its power on till it has children which
2276 // will thendetermine the power domain state.
2278 // We enter the highest state until addPowerChild is called.
2279 //*********************************************************************************
2281 IOReturn
IOService::temporaryPowerClampOn ( void )
2283 return requestPowerState( gIOPMPowerClientChildProxy
, kIOPMPowerStateMax
);
2286 //*********************************************************************************
2287 // [public] makeUsable
2289 // Some client of our device is asking that we become usable. Although
2290 // this has not come from a subclassed device object, treat it exactly
2291 // as if it had. In this way, subsequent requests for lower power from
2292 // a subclassed device object will pre-empt this request.
2294 // We treat this as a subclass object request to switch to the
2295 // highest power state.
2296 //*********************************************************************************
2298 IOReturn
IOService::makeUsable ( void )
2300 OUR_PMLog(kPMLogMakeUsable
, 0, 0);
2301 return requestPowerState( gIOPMPowerClientDevice
, kIOPMPowerStateMax
);
2304 //*********************************************************************************
2305 // [public] currentCapability
2306 //*********************************************************************************
2308 IOPMPowerFlags
IOService::currentCapability ( void )
2311 return IOPMNotPowerManaged
;
2313 return fCurrentCapabilityFlags
;
2316 //*********************************************************************************
2317 // [public] changePowerStateTo
2319 // Called by our power-controlling driver to change power state. The new desired
2320 // power state is computed and compared against the current power state. If those
2321 // power states differ, then a power state change is initiated.
2322 //*********************************************************************************
2324 IOReturn
IOService::changePowerStateTo ( unsigned long ordinal
)
2326 OUR_PMLog(kPMLogChangeStateTo
, ordinal
, 0);
2327 return requestPowerState( gIOPMPowerClientDriver
, ordinal
);
2330 //*********************************************************************************
2331 // [protected] changePowerStateToPriv
2333 // Called by our driver subclass to change power state. The new desired power
2334 // state is computed and compared against the current power state. If those
2335 // power states differ, then a power state change is initiated.
2336 //*********************************************************************************
2338 IOReturn
IOService::changePowerStateToPriv ( unsigned long ordinal
)
2340 OUR_PMLog(kPMLogChangeStateToPriv
, ordinal
, 0);
2341 return requestPowerState( gIOPMPowerClientDevice
, ordinal
);
2344 //*********************************************************************************
2345 // [protected] changePowerStateWithOverrideTo
2347 // Called by our driver subclass to change power state. The new desired power
2348 // state is computed and compared against the current power state. If those
2349 // power states differ, then a power state change is initiated.
2350 // Override enforced - Children and Driver desires are ignored.
2351 //*********************************************************************************
2353 IOReturn
IOService::changePowerStateWithOverrideTo ( unsigned long ordinal
)
2355 IOPMRequest
* request
;
2358 return kIOPMNotYetInitialized
;
2360 OUR_PMLog(kPMLogChangeStateToPriv
, ordinal
, 0);
2362 request
= acquirePMRequest( this, kIOPMRequestTypeRequestPowerStateOverride
);
2364 return kIOReturnNoMemory
;
2366 gIOPMPowerClientDevice
->retain();
2367 request
->fArg0
= (void *) ordinal
;
2368 request
->fArg1
= (void *) gIOPMPowerClientDevice
;
2372 request
->installCompletionAction( action
, target
, param
);
2375 // Prevent needless downwards power transitions by clamping power
2376 // until the scheduled request is executed.
2378 if (gIOPMWorkLoop
->inGate() && (ordinal
< fNumberOfPowerStates
))
2380 fTempClampPowerState
= max(fTempClampPowerState
, ordinal
);
2382 fOverrideMaxPowerState
= ordinal
;
2383 request
->fArg2
= (void *) (uintptr_t) true;
2386 submitPMRequest( request
);
2390 //*********************************************************************************
2391 // [private] requestPowerState
2392 //*********************************************************************************
2394 IOReturn
IOService::requestPowerState (
2395 const OSSymbol
* client
,
2398 IOPMRequest
* request
;
2401 return kIOReturnBadArgument
;
2403 return kIOPMNotYetInitialized
;
2405 request
= acquirePMRequest( this, kIOPMRequestTypeRequestPowerState
);
2407 return kIOReturnNoMemory
;
2410 request
->fArg0
= (void *) state
;
2411 request
->fArg1
= (void *) client
;
2415 request
->installCompletionAction( action
, target
, param
);
2418 // Prevent needless downwards power transitions by clamping power
2419 // until the scheduled request is executed.
2421 if (gIOPMWorkLoop
->inGate() && (state
< fNumberOfPowerStates
))
2423 fTempClampPowerState
= max(fTempClampPowerState
, state
);
2425 request
->fArg2
= (void *) (uintptr_t) true;
2428 submitPMRequest( request
);
2432 //*********************************************************************************
2433 // [private] handleRequestPowerState
2434 //*********************************************************************************
2436 void IOService::handleRequestPowerState ( IOPMRequest
* request
)
2438 const OSSymbol
* client
= (const OSSymbol
*) request
->fArg1
;
2439 uint32_t state
= (uint32_t)(uintptr_t) request
->fArg0
;
2441 PM_ASSERT_IN_GATE();
2444 assert(fTempClampCount
!= 0);
2445 if (fTempClampCount
) fTempClampCount
--;
2446 if (!fTempClampCount
) fTempClampPowerState
= 0;
2449 if (fNumberOfPowerStates
&& (state
>= fNumberOfPowerStates
))
2450 state
= fNumberOfPowerStates
- 1;
2452 // The power suppression due to changePowerStateWithOverrideTo() expires
2453 // upon the next "device" power request - changePowerStateToPriv().
2455 if ((getPMRequestType() != kIOPMRequestTypeRequestPowerStateOverride
) &&
2456 (client
== gIOPMPowerClientDevice
))
2457 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
2460 (client
!= gIOPMPowerClientDevice
) &&
2461 (client
!= gIOPMPowerClientDriver
) &&
2462 (client
!= gIOPMPowerClientChildProxy
))
2463 removePowerClient(client
);
2465 updatePowerClient(client
, state
);
2471 //*********************************************************************************
2472 // [private] Helper functions to update/remove power clients.
2473 //*********************************************************************************
2475 void IOService::updatePowerClient( const OSSymbol
* client
, uint32_t powerState
)
2478 fPowerClients
= OSDictionary::withCapacity(4);
2479 if (fPowerClients
&& client
)
2481 OSNumber
* num
= (OSNumber
*) fPowerClients
->getObject(client
);
2483 num
->setValue(powerState
);
2486 num
= OSNumber::withNumber(powerState
, 32);
2489 fPowerClients
->setObject(client
, num
);
2496 void IOService::removePowerClient( const OSSymbol
* client
)
2498 if (fPowerClients
&& client
)
2499 fPowerClients
->removeObject(client
);
2502 uint32_t IOService::getPowerStateForClient( const OSSymbol
* client
)
2504 uint32_t powerState
= 0;
2506 if (fPowerClients
&& client
)
2508 OSNumber
* num
= (OSNumber
*) fPowerClients
->getObject(client
);
2509 if (num
) powerState
= num
->unsigned32BitValue();
2514 //*********************************************************************************
2515 // [protected] powerOverrideOnPriv
2516 //*********************************************************************************
2518 IOReturn
IOService::powerOverrideOnPriv ( void )
2520 IOPMRequest
* request
;
2523 return IOPMNotYetInitialized
;
2525 if (gIOPMWorkLoop
->inGate())
2527 fDeviceOverrideEnabled
= true;
2531 request
= acquirePMRequest( this, kIOPMRequestTypePowerOverrideOnPriv
);
2533 return kIOReturnNoMemory
;
2535 submitPMRequest( request
);
2539 //*********************************************************************************
2540 // [protected] powerOverrideOffPriv
2541 //*********************************************************************************
2543 IOReturn
IOService::powerOverrideOffPriv ( void )
2545 IOPMRequest
* request
;
2548 return IOPMNotYetInitialized
;
2550 if (gIOPMWorkLoop
->inGate())
2552 fDeviceOverrideEnabled
= false;
2556 request
= acquirePMRequest( this, kIOPMRequestTypePowerOverrideOffPriv
);
2558 return kIOReturnNoMemory
;
2560 submitPMRequest( request
);
2564 //*********************************************************************************
2565 // [private] handlePowerOverrideChanged
2566 //*********************************************************************************
2568 void IOService::handlePowerOverrideChanged ( IOPMRequest
* request
)
2570 PM_ASSERT_IN_GATE();
2571 if (request
->getType() == kIOPMRequestTypePowerOverrideOnPriv
)
2573 OUR_PMLog(kPMLogOverrideOn
, 0, 0);
2574 fDeviceOverrideEnabled
= true;
2578 OUR_PMLog(kPMLogOverrideOff
, 0, 0);
2579 fDeviceOverrideEnabled
= false;
2585 //*********************************************************************************
2586 // [private] computeDesiredState
2587 //*********************************************************************************
2589 void IOService::computeDesiredState( unsigned long localClamp
, bool computeOnly
)
2593 IOPowerConnection
* connection
;
2594 uint32_t desiredState
= 0;
2595 uint32_t newPowerState
= 0;
2596 bool hasChildren
= false;
2598 // Desired power state is always 0 without a controlling driver.
2600 if (!fNumberOfPowerStates
)
2602 fDesiredPowerState
= 0;
2603 //PM_LOG("%s::%s no controlling driver\n", getName(), __FUNCTION__);
2607 // Examine the children's desired power state.
2609 iter
= getChildIterator(gIOPowerPlane
);
2612 while ((next
= iter
->getNextObject()))
2614 if ((connection
= OSDynamicCast(IOPowerConnection
, next
)))
2616 if (connection
->getReadyFlag() == false)
2618 PM_LOG3("[%s] %s: connection not ready\n",
2619 getName(), __FUNCTION__
);
2622 if (connection
->childHasRequestedPower())
2624 if (connection
->getDesiredDomainState() > desiredState
)
2625 desiredState
= connection
->getDesiredDomainState();
2631 updatePowerClient(gIOPMPowerClientChildren
, desiredState
);
2633 removePowerClient(gIOPMPowerClientChildren
);
2635 // Iterate through all power clients to determine the min power state.
2637 iter
= OSCollectionIterator::withCollection(fPowerClients
);
2640 const OSSymbol
* client
;
2641 while ((client
= (const OSSymbol
*) iter
->getNextObject()))
2643 // Ignore child and driver when override is in effect.
2644 if ((fDeviceOverrideEnabled
||
2645 (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)) &&
2646 ((client
== gIOPMPowerClientChildren
) ||
2647 (client
== gIOPMPowerClientDriver
)))
2650 // Ignore child proxy when children are present.
2651 if (hasChildren
&& (client
== gIOPMPowerClientChildProxy
))
2654 // Advisory tickles are irrelevant unless system is in full wake
2655 if (client
== gIOPMPowerClientAdvisoryTickle
&&
2656 !gIOPMAdvisoryTickleEnabled
)
2659 desiredState
= getPowerStateForClient(client
);
2660 assert(desiredState
< fNumberOfPowerStates
);
2662 desiredState
, client
->getCStringNoCopy());
2664 newPowerState
= max(newPowerState
, desiredState
);
2666 if (client
== gIOPMPowerClientDevice
)
2667 fDeviceDesire
= desiredState
;
2672 // Factor in the temporary power desires.
2674 newPowerState
= max(newPowerState
, localClamp
);
2675 newPowerState
= max(newPowerState
, fTempClampPowerState
);
2677 // Limit check against max power override.
2679 newPowerState
= min(newPowerState
, fOverrideMaxPowerState
);
2681 // Limit check against number of power states.
2683 if (newPowerState
>= fNumberOfPowerStates
)
2684 newPowerState
= fNumberOfPowerStates
- 1;
2686 fDesiredPowerState
= newPowerState
;
2688 PM_LOG1(" temp %u, clamp %u, current %u, new %u\n",
2689 (uint32_t) localClamp
, (uint32_t) fTempClampPowerState
,
2690 (uint32_t) fCurrentPowerState
, newPowerState
);
2694 // Restart idle timer if possible when device desire has increased.
2695 // Or if an advisory desire exists.
2697 if (fIdleTimerPeriod
&& fIdleTimerStopped
)
2702 // Invalidate cached tickle power state when desires change, and not
2703 // due to a tickle request. In case the driver has requested a lower
2704 // power state, but the tickle is caching a higher power state which
2705 // will drop future tickles until the cached value is lowered or in-
2706 // validated. The invalidation must occur before the power transition
2707 // to avoid dropping a necessary tickle.
2709 if ((getPMRequestType() != kIOPMRequestTypeActivityTickle
) &&
2710 (fActivityTicklePowerState
!= kInvalidTicklePowerState
))
2712 IOLockLock(fActivityLock
);
2713 fActivityTicklePowerState
= kInvalidTicklePowerState
;
2714 IOLockUnlock(fActivityLock
);
2719 //*********************************************************************************
2720 // [public] currentPowerConsumption
2722 //*********************************************************************************
2724 unsigned long IOService::currentPowerConsumption ( void )
2727 return kIOPMUnknown
;
2729 return fCurrentPowerConsumption
;
2732 //*********************************************************************************
2733 // [deprecated] getPMworkloop
2734 //*********************************************************************************
2736 IOWorkLoop
* IOService::getPMworkloop ( void )
2738 return gIOPMWorkLoop
;
2743 //*********************************************************************************
2744 // Power Parent/Children Applier
2745 //*********************************************************************************
2748 applyToPowerChildren(
2749 IOService
* service
,
2750 IOServiceApplierFunction applier
,
2752 IOOptionBits options
)
2754 PM_ASSERT_IN_GATE();
2756 IORegistryEntry
* entry
;
2757 IORegistryIterator
* iter
;
2758 IOPowerConnection
* connection
;
2761 iter
= IORegistryIterator::iterateOver(service
, gIOPowerPlane
, options
);
2764 while ((entry
= iter
->getNextObject()))
2766 // Get child of IOPowerConnection objects
2767 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)))
2769 child
= (IOService
*) connection
->copyChildEntry(gIOPowerPlane
);
2772 (*applier
)(child
, context
);
2783 IOService
* service
,
2784 IOServiceApplierFunction applier
,
2786 IOOptionBits options
)
2788 PM_ASSERT_IN_GATE();
2790 IORegistryEntry
* entry
;
2791 IORegistryIterator
* iter
;
2792 IOPowerConnection
* connection
;
2795 iter
= IORegistryIterator::iterateOver(service
, gIOPowerPlane
,
2796 options
| kIORegistryIterateParents
);
2799 while ((entry
= iter
->getNextObject()))
2801 // Get child of IOPowerConnection objects
2802 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)))
2804 parent
= (IOService
*) connection
->copyParentEntry(gIOPowerPlane
);
2807 (*applier
)(parent
, context
);
2816 #endif /* NOT_YET */
2819 // MARK: Activity Tickle & Idle Timer
2821 void IOService::setAdvisoryTickleEnable( bool enable
)
2823 gIOPMAdvisoryTickleEnabled
= enable
;
2826 //*********************************************************************************
2827 // [public] activityTickle
2829 // The tickle with parameter kIOPMSuperclassPolicy1 causes the activity
2830 // flag to be set, and the device state checked. If the device has been
2831 // powered down, it is powered up again.
2832 // The tickle with parameter kIOPMSubclassPolicy is ignored here and
2833 // should be intercepted by a subclass.
2834 //*********************************************************************************
2836 bool IOService::activityTickle ( unsigned long type
, unsigned long stateNumber
)
2838 IOPMRequest
* request
;
2839 bool noPowerChange
= true;
2840 uint32_t tickleFlags
;
2843 return true; // no power change
2845 if ((type
== kIOPMSuperclassPolicy1
) && stateNumber
)
2847 IOLockLock(fActivityLock
);
2849 // Record device activity for the idle timer handler.
2851 fDeviceWasActive
= true;
2852 fActivityTickleCount
++;
2853 clock_get_uptime(&fDeviceActiveTimestamp
);
2855 PM_ACTION_0(actionActivityTickle
);
2857 // Record the last tickle power state.
2858 // This helps to filter out redundant tickles as
2859 // this function may be called from the data path.
2861 if (fActivityTicklePowerState
< (int)stateNumber
)
2863 fActivityTicklePowerState
= stateNumber
;
2864 noPowerChange
= false;
2866 tickleFlags
= kTickleTypeActivity
| kTickleTypePowerRise
;
2867 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
2870 request
->fArg0
= (void *) stateNumber
;
2871 request
->fArg1
= (void *) tickleFlags
;
2872 request
->fArg2
= (void *) gIOPMTickleGeneration
;
2873 submitPMRequest(request
);
2877 IOLockUnlock(fActivityLock
);
2880 else if ((type
== kIOPMActivityTickleTypeAdvisory
) &&
2881 ((stateNumber
= fDeviceUsablePowerState
)))
2883 IOLockLock(fActivityLock
);
2885 fAdvisoryTickled
= true;
2887 if (fAdvisoryTicklePowerState
!= (int)stateNumber
)
2889 fAdvisoryTicklePowerState
= stateNumber
;
2890 noPowerChange
= false;
2892 tickleFlags
= kTickleTypeAdvisory
| kTickleTypePowerRise
;
2893 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
2896 request
->fArg0
= (void *) stateNumber
;
2897 request
->fArg1
= (void *) tickleFlags
;
2898 request
->fArg2
= (void *) gIOPMTickleGeneration
;
2899 submitPMRequest(request
);
2903 IOLockUnlock(fActivityLock
);
2906 // Returns false if the activityTickle might cause a transition to a
2907 // higher powered state, true otherwise.
2909 return noPowerChange
;
2912 //*********************************************************************************
2913 // [private] handleActivityTickle
2914 //*********************************************************************************
2916 void IOService::handleActivityTickle ( IOPMRequest
* request
)
2918 uint32_t ticklePowerState
= (uint32_t)(uintptr_t) request
->fArg0
;
2919 uint32_t tickleFlags
= (uint32_t)(uintptr_t) request
->fArg1
;
2920 uint32_t tickleGeneration
= (uint32_t)(uintptr_t) request
->fArg2
;
2921 bool adjustPower
= false;
2923 PM_ASSERT_IN_GATE();
2924 if (fResetPowerStateOnWake
&& (tickleGeneration
!= gIOPMTickleGeneration
))
2926 // Drivers that don't want power restored on wake will drop any
2927 // tickles that pre-dates the current system wake. The model is
2928 // that each wake is a fresh start, with power state depressed
2929 // until a new tickle or an explicit power up request from the
2930 // driver. It is possible for the PM work loop to enter the
2931 // system sleep path with tickle requests queued.
2936 if (tickleFlags
& kTickleTypeActivity
)
2938 if (tickleFlags
& kTickleTypePowerRise
)
2940 if ((ticklePowerState
> fDeviceDesire
) &&
2941 (ticklePowerState
< fNumberOfPowerStates
))
2943 fIdleTimerMinPowerState
= ticklePowerState
;
2944 updatePowerClient(gIOPMPowerClientDevice
, ticklePowerState
);
2948 else if (fDeviceDesire
> fIdleTimerMinPowerState
)
2950 // Power drop due to idle timer expiration.
2951 // Do not allow idle timer to reduce power below tickle power.
2952 // This prevents the idle timer from decreasing the device desire
2953 // to zero and cancelling the effect of a pre-sleep tickle when
2954 // system wakes up to doze state, while the device is unable to
2955 // raise its power state to satisfy the tickle.
2957 ticklePowerState
= fDeviceDesire
- 1;
2958 updatePowerClient(gIOPMPowerClientDevice
, ticklePowerState
);
2962 else // advisory tickle
2964 if (tickleFlags
& kTickleTypePowerRise
)
2966 if ((ticklePowerState
== fDeviceUsablePowerState
) &&
2967 (ticklePowerState
< fNumberOfPowerStates
))
2969 updatePowerClient(gIOPMPowerClientAdvisoryTickle
, ticklePowerState
);
2970 fHasAdvisoryDesire
= true;
2971 fAdvisoryTickleUsed
= true;
2976 IOLockLock(fActivityLock
);
2977 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
2978 IOLockUnlock(fActivityLock
);
2981 else if (fHasAdvisoryDesire
)
2983 removePowerClient(gIOPMPowerClientAdvisoryTickle
);
2984 fHasAdvisoryDesire
= false;
2995 //******************************************************************************
2996 // [public] setIdleTimerPeriod
2998 // A subclass policy-maker is using our standard idleness detection service.
2999 // Start the idle timer. Period is in seconds.
3000 //******************************************************************************
3002 IOReturn
IOService::setIdleTimerPeriod ( unsigned long period
)
3005 return IOPMNotYetInitialized
;
3007 OUR_PMLog(kPMLogSetIdleTimerPeriod
, period
, fIdleTimerPeriod
);
3009 IOPMRequest
* request
=
3010 acquirePMRequest( this, kIOPMRequestTypeSetIdleTimerPeriod
);
3012 return kIOReturnNoMemory
;
3014 request
->fArg0
= (void *) period
;
3015 submitPMRequest( request
);
3017 return kIOReturnSuccess
;
3020 IOReturn
IOService::setIgnoreIdleTimer( bool ignore
)
3023 return IOPMNotYetInitialized
;
3025 OUR_PMLog(kIOPMRequestTypeIgnoreIdleTimer
, ignore
, 0);
3027 IOPMRequest
* request
=
3028 acquirePMRequest( this, kIOPMRequestTypeIgnoreIdleTimer
);
3030 return kIOReturnNoMemory
;
3032 request
->fArg0
= (void *) ignore
;
3033 submitPMRequest( request
);
3035 return kIOReturnSuccess
;
3038 //******************************************************************************
3039 // [public] nextIdleTimeout
3041 // Returns how many "seconds from now" the device should idle into its
3042 // next lowest power state.
3043 //******************************************************************************
3045 SInt32
IOService::nextIdleTimeout(
3046 AbsoluteTime currentTime
,
3047 AbsoluteTime lastActivity
,
3048 unsigned int powerState
)
3055 // Calculate time difference using funky macro from clock.h.
3056 delta
= currentTime
;
3057 SUB_ABSOLUTETIME(&delta
, &lastActivity
);
3059 // Figure it in seconds.
3060 absolutetime_to_nanoseconds(delta
, &delta_ns
);
3061 delta_secs
= (SInt32
)(delta_ns
/ NSEC_PER_SEC
);
3063 // Be paranoid about delta somehow exceeding timer period.
3064 if (delta_secs
< (int) fIdleTimerPeriod
)
3065 delay_secs
= (int) fIdleTimerPeriod
- delta_secs
;
3067 delay_secs
= (int) fIdleTimerPeriod
;
3069 return (SInt32
)delay_secs
;
3072 //*********************************************************************************
3073 // [public] start_PM_idle_timer
3074 //*********************************************************************************
3076 void IOService::start_PM_idle_timer ( void )
3078 static const int maxTimeout
= 100000;
3079 static const int minTimeout
= 1;
3080 AbsoluteTime uptime
, deadline
;
3084 if (!initialized
|| !fIdleTimerPeriod
)
3087 IOLockLock(fActivityLock
);
3089 clock_get_uptime(&uptime
);
3091 // Subclasses may modify idle sleep algorithm
3092 idle_in
= nextIdleTimeout(uptime
, fDeviceActiveTimestamp
, fCurrentPowerState
);
3094 // Check for out-of range responses
3095 if (idle_in
> maxTimeout
)
3097 // use standard implementation
3098 idle_in
= IOService::nextIdleTimeout(uptime
,
3099 fDeviceActiveTimestamp
,
3100 fCurrentPowerState
);
3101 } else if (idle_in
< minTimeout
) {
3102 idle_in
= fIdleTimerPeriod
;
3105 IOLockUnlock(fActivityLock
);
3108 clock_interval_to_absolutetime_interval(idle_in
, kSecondScale
, &deadline
);
3109 ADD_ABSOLUTETIME(&deadline
, &uptime
);
3110 pending
= thread_call_enter_delayed(fIdleTimer
, deadline
);
3111 if (pending
) release();
3114 //*********************************************************************************
3115 // [private] restartIdleTimer
3116 //*********************************************************************************
3118 void IOService::restartIdleTimer( void )
3120 if (fDeviceDesire
!= 0)
3122 fIdleTimerStopped
= false;
3123 fActivityTickleCount
= 0;
3124 clock_get_uptime(&fIdleTimerStartTime
);
3125 start_PM_idle_timer();
3127 else if (fHasAdvisoryDesire
)
3129 fIdleTimerStopped
= false;
3130 start_PM_idle_timer();
3134 fIdleTimerStopped
= true;
3138 //*********************************************************************************
3139 // idle_timer_expired
3140 //*********************************************************************************
3143 idle_timer_expired (
3144 thread_call_param_t arg0
, thread_call_param_t arg1
)
3146 IOService
* me
= (IOService
*) arg0
;
3149 gIOPMWorkLoop
->runAction(
3150 OSMemberFunctionCast(IOWorkLoop::Action
, me
,
3151 &IOService::idleTimerExpired
),
3157 //*********************************************************************************
3158 // [private] idleTimerExpired
3160 // The idle timer has expired. If there has been activity since the last
3161 // expiration, just restart the timer and return. If there has not been
3162 // activity, switch to the next lower power state and restart the timer.
3163 //*********************************************************************************
3165 void IOService::idleTimerExpired( void )
3167 IOPMRequest
* request
;
3168 bool restartTimer
= true;
3169 uint32_t tickleFlags
;
3171 if ( !initialized
|| !fIdleTimerPeriod
|| fIdleTimerStopped
||
3172 fLockedFlags
.PMStop
)
3175 IOLockLock(fActivityLock
);
3177 // Check for device activity (tickles) over last timer period.
3179 if (fDeviceWasActive
)
3181 // Device was active - do not drop power, restart timer.
3182 fDeviceWasActive
= false;
3184 else if (!fIdleTimerIgnored
)
3186 // No device activity - drop power state by one level.
3187 // Decrement the cached tickle power state when possible.
3188 // This value may be (-1) before activityTickle() is called,
3189 // but the power drop request must be issued regardless.
3191 if (fActivityTicklePowerState
> 0)
3192 fActivityTicklePowerState
--;
3194 tickleFlags
= kTickleTypeActivity
| kTickleTypePowerDrop
;
3195 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
3198 request
->fArg0
= (void *) 0; // irrelevant
3199 request
->fArg1
= (void *) tickleFlags
;
3200 request
->fArg2
= (void *) gIOPMTickleGeneration
;
3201 submitPMRequest( request
);
3203 // Do not restart timer until after the tickle request has been
3206 restartTimer
= false;
3210 if (fAdvisoryTickled
)
3212 fAdvisoryTickled
= false;
3214 else if (fHasAdvisoryDesire
)
3216 // Want new tickles to turn into pm request after we drop the lock
3217 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
3219 tickleFlags
= kTickleTypeAdvisory
| kTickleTypePowerDrop
;
3220 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
3223 request
->fArg0
= (void *) 0; // irrelevant
3224 request
->fArg1
= (void *) tickleFlags
;
3225 request
->fArg2
= (void *) gIOPMTickleGeneration
;
3226 submitPMRequest( request
);
3228 // Do not restart timer until after the tickle request has been
3231 restartTimer
= false;
3235 IOLockUnlock(fActivityLock
);
3238 start_PM_idle_timer();
3242 //*********************************************************************************
3243 // [deprecated] PM_idle_timer_expiration
3244 //*********************************************************************************
3246 void IOService::PM_idle_timer_expiration ( void )
3250 //*********************************************************************************
3251 // [deprecated] command_received
3252 //*********************************************************************************
3254 void IOService::command_received ( void *statePtr
, void *, void * , void * )
3257 #endif /* !__LP64__ */
3259 //*********************************************************************************
3260 // [public] setAggressiveness
3262 // Pass on the input parameters to all power domain children. All those which are
3263 // power domains will pass it on to their children, etc.
3264 //*********************************************************************************
3266 IOReturn
IOService::setAggressiveness ( unsigned long type
, unsigned long newLevel
)
3268 return kIOReturnSuccess
;
3271 //*********************************************************************************
3272 // [public] getAggressiveness
3274 // Called by the user client.
3275 //*********************************************************************************
3277 IOReturn
IOService::getAggressiveness ( unsigned long type
, unsigned long * currentLevel
)
3279 IOPMrootDomain
* rootDomain
= getPMRootDomain();
3282 return kIOReturnNotReady
;
3284 return rootDomain
->getAggressiveness( type
, currentLevel
);
3287 //*********************************************************************************
3288 // [public] getPowerState
3290 //*********************************************************************************
3292 UInt32
IOService::getPowerState ( void )
3297 return fCurrentPowerState
;
3301 //*********************************************************************************
3302 // [deprecated] systemWake
3304 // Pass this to all power domain children. All those which are
3305 // power domains will pass it on to their children, etc.
3306 //*********************************************************************************
3308 IOReturn
IOService::systemWake ( void )
3312 IOPowerConnection
* connection
;
3313 IOService
* theChild
;
3315 iter
= getChildIterator(gIOPowerPlane
);
3318 while ( (next
= iter
->getNextObject()) )
3320 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
3322 if (connection
->getReadyFlag() == false)
3324 PM_LOG3("[%s] %s: connection not ready\n",
3325 getName(), __FUNCTION__
);
3329 theChild
= (IOService
*)connection
->copyChildEntry(gIOPowerPlane
);
3332 theChild
->systemWake();
3333 theChild
->release();
3340 if ( fControllingDriver
!= NULL
)
3342 if ( fControllingDriver
->didYouWakeSystem() )
3351 //*********************************************************************************
3352 // [deprecated] temperatureCriticalForZone
3353 //*********************************************************************************
3355 IOReturn
IOService::temperatureCriticalForZone ( IOService
* whichZone
)
3357 IOService
* theParent
;
3360 OUR_PMLog(kPMLogCriticalTemp
, 0, 0);
3362 if ( inPlane(gIOPowerPlane
) && !IS_PM_ROOT
)
3364 theNub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
3367 theParent
= (IOService
*)theNub
->copyParentEntry(gIOPowerPlane
);
3371 theParent
->temperatureCriticalForZone(whichZone
);
3372 theParent
->release();
3378 #endif /* !__LP64__ */
3381 // MARK: Power Change (Common)
3383 //*********************************************************************************
3384 // [private] startPowerChange
3386 // All power state changes starts here.
3387 //*********************************************************************************
3389 IOReturn
IOService::startPowerChange(
3390 IOPMPowerChangeFlags changeFlags
,
3391 IOPMPowerStateIndex powerState
,
3392 IOPMPowerFlags domainFlags
,
3393 IOPowerConnection
* parentConnection
,
3394 IOPMPowerFlags parentFlags
)
3396 PM_ASSERT_IN_GATE();
3397 assert( fMachineState
== kIOPM_Finished
);
3398 assert( powerState
< fNumberOfPowerStates
);
3400 if (powerState
>= fNumberOfPowerStates
)
3401 return IOPMAckImplied
;
3403 fIsPreChange
= true;
3404 PM_ACTION_2(actionPowerChangeOverride
, &powerState
, &changeFlags
);
3406 // Forks to either Driver or Parent initiated power change paths.
3408 fHeadNoteChangeFlags
= changeFlags
;
3409 fHeadNotePowerState
= powerState
;
3410 fHeadNotePowerArrayEntry
= &fPowerStates
[ powerState
];
3411 fHeadNoteParentConnection
= NULL
;
3413 if (changeFlags
& kIOPMSelfInitiated
)
3415 if (changeFlags
& kIOPMSynchronize
)
3423 assert(changeFlags
& kIOPMParentInitiated
);
3424 fHeadNoteDomainFlags
= domainFlags
;
3425 fHeadNoteParentFlags
= parentFlags
;
3426 fHeadNoteParentConnection
= parentConnection
;
3427 return ParentChangeStart();
3431 //*********************************************************************************
3432 // [private] notifyInterestedDrivers
3433 //*********************************************************************************
3435 bool IOService::notifyInterestedDrivers ( void )
3437 IOPMinformee
* informee
;
3438 IOPMinformeeList
* list
= fInterestedDrivers
;
3439 DriverCallParam
* param
;
3442 PM_ASSERT_IN_GATE();
3443 assert( fDriverCallParamCount
== 0 );
3444 assert( fHeadNotePendingAcks
== 0 );
3446 fHeadNotePendingAcks
= 0;
3448 count
= list
->numberOfItems();
3450 goto done
; // no interested drivers
3452 // Allocate an array of interested drivers and their return values
3453 // for the callout thread. Everything else is still "owned" by the
3454 // PM work loop, which can run to process acknowledgePowerChange()
3457 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3458 if (count
> fDriverCallParamSlots
)
3460 if (fDriverCallParamSlots
)
3462 assert(fDriverCallParamPtr
);
3463 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
3464 fDriverCallParamPtr
= 0;
3465 fDriverCallParamSlots
= 0;
3468 param
= IONew(DriverCallParam
, count
);
3470 goto done
; // no memory
3472 fDriverCallParamPtr
= (void *) param
;
3473 fDriverCallParamSlots
= count
;
3476 informee
= list
->firstInList();
3478 for (IOItemCount i
= 0; i
< count
; i
++)
3480 informee
->timer
= -1;
3481 param
[i
].Target
= informee
;
3483 informee
= list
->nextInList( informee
);
3486 fDriverCallParamCount
= count
;
3487 fHeadNotePendingAcks
= count
;
3489 // Block state machine and wait for callout completion.
3490 assert(!fDriverCallBusy
);
3491 fDriverCallBusy
= true;
3492 thread_call_enter( fDriverCallEntry
);
3496 // Return false if there are no interested drivers or could not schedule
3497 // callout thread due to error.
3501 //*********************************************************************************
3502 // [private] notifyInterestedDriversDone
3503 //*********************************************************************************
3505 void IOService::notifyInterestedDriversDone ( void )
3507 IOPMinformee
* informee
;
3509 DriverCallParam
* param
;
3512 PM_ASSERT_IN_GATE();
3513 assert( fDriverCallBusy
== false );
3514 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
3516 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3517 count
= fDriverCallParamCount
;
3521 for (IOItemCount i
= 0; i
< count
; i
++, param
++)
3523 informee
= (IOPMinformee
*) param
->Target
;
3524 result
= param
->Result
;
3526 if ((result
== IOPMAckImplied
) || (result
< 0))
3528 // Interested driver return IOPMAckImplied.
3529 // If informee timer is zero, it must have de-registered
3530 // interest during the thread callout. That also drops
3531 // the pending ack count.
3533 if (fHeadNotePendingAcks
&& informee
->timer
)
3534 fHeadNotePendingAcks
--;
3536 informee
->timer
= 0;
3538 else if (informee
->timer
)
3540 assert(informee
->timer
== -1);
3542 // Driver has not acked, and has returned a positive result.
3543 // Enforce a minimum permissible timeout value.
3544 // Make the min value large enough so timeout is less likely
3545 // to occur if a driver misinterpreted that the return value
3546 // should be in microsecond units. And make it large enough
3547 // to be noticeable if a driver neglects to ack.
3549 if (result
< kMinAckTimeoutTicks
)
3550 result
= kMinAckTimeoutTicks
;
3552 informee
->timer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
3554 // else, child has already acked or driver has removed interest,
3555 // and head_note_pendingAcks decremented.
3556 // informee may have been removed from the interested drivers list,
3557 // thus the informee must be retained across the callout.
3559 informee
->release();
3562 fDriverCallParamCount
= 0;
3564 if ( fHeadNotePendingAcks
)
3566 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
3571 MS_POP(); // pushed by notifyAll()
3573 // If interest acks are outstanding, wait for fHeadNotePendingAcks to become
3574 // zero before notifying children. This enforces the children after interest
3575 // ordering even for async interest clients.
3577 if (!fHeadNotePendingAcks
)
3583 MS_PUSH(fMachineState
);
3584 fMachineState
= kIOPM_NotifyChildrenStart
;
3585 PM_LOG2("%s: %u outstanding async interest\n",
3586 getName(), fHeadNotePendingAcks
);
3590 //*********************************************************************************
3591 // [private] notifyChildren
3592 //*********************************************************************************
3594 void IOService::notifyChildren ( void )
3598 IOPowerConnection
* connection
;
3599 OSArray
* children
= 0;
3600 IOPMrootDomain
* rootDomain
;
3601 bool delayNotify
= false;
3603 if ((fHeadNotePowerState
!= fCurrentPowerState
) &&
3604 (IS_POWER_DROP
== fIsPreChange
) &&
3605 ((rootDomain
= getPMRootDomain()) == this))
3607 rootDomain
->tracePoint( IS_POWER_DROP
?
3608 kIOPMTracePointSleepPowerPlaneDrivers
:
3609 kIOPMTracePointWakePowerPlaneDrivers
);
3612 if (fStrictTreeOrder
)
3613 children
= OSArray::withCapacity(8);
3615 // Sum child power consumption in notifyChild()
3616 fHeadNotePowerArrayEntry
->staticPower
= 0;
3618 iter
= getChildIterator(gIOPowerPlane
);
3621 while ((next
= iter
->getNextObject()))
3623 if ((connection
= OSDynamicCast(IOPowerConnection
, next
)))
3625 if (connection
->getReadyFlag() == false)
3627 PM_LOG3("[%s] %s: connection not ready\n",
3628 getName(), __FUNCTION__
);
3632 // Mechanism to postpone the did-change notification to
3633 // certain power children to order those children last.
3634 // Cannot be used together with strict tree ordering.
3636 if (!fIsPreChange
&&
3637 (connection
->delayChildNotification
) &&
3638 getPMRootDomain()->shouldDelayChildNotification(this))
3642 children
= OSArray::withCapacity(8);
3648 children
->setObject( connection
);
3653 if (!delayNotify
&& children
)
3654 children
->setObject( connection
);
3656 notifyChild( connection
);
3662 if (children
&& (children
->getCount() == 0))
3664 children
->release();
3669 assert(fNotifyChildArray
== 0);
3670 fNotifyChildArray
= children
;
3671 MS_PUSH(fMachineState
);
3675 // Wait for exiting child notifications to complete,
3676 // before notifying the children in the array.
3677 fMachineState
= kIOPM_NotifyChildrenDelayed
;
3678 PM_LOG2("%s: %d children in delayed array\n",
3679 getName(), children
->getCount());
3683 // Notify children in the array one at a time.
3684 fMachineState
= kIOPM_NotifyChildrenOrdered
;
3689 //*********************************************************************************
3690 // [private] notifyChildrenOrdered
3691 //*********************************************************************************
3693 void IOService::notifyChildrenOrdered ( void )
3695 PM_ASSERT_IN_GATE();
3696 assert(fNotifyChildArray
);
3697 assert(fMachineState
== kIOPM_NotifyChildrenOrdered
);
3699 // Notify one child, wait for it to ack, then repeat for next child.
3700 // This is a workaround for some drivers with multiple instances at
3701 // the same branch in the power tree, but the driver is slow to power
3702 // up unless the tree ordering is observed. Problem observed only on
3703 // system wake, not on system sleep.
3705 // We have the ability to power off in reverse child index order.
3706 // That works nicely on some machines, but not on all HW configs.
3708 if (fNotifyChildArray
->getCount())
3710 IOPowerConnection
* connection
;
3711 connection
= (IOPowerConnection
*) fNotifyChildArray
->getObject(0);
3712 notifyChild( connection
);
3713 fNotifyChildArray
->removeObject(0);
3717 fNotifyChildArray
->release();
3718 fNotifyChildArray
= 0;
3720 MS_POP(); // pushed by notifyChildren()
3724 //*********************************************************************************
3725 // [private] notifyChildrenDelayed
3726 //*********************************************************************************
3728 void IOService::notifyChildrenDelayed ( void )
3730 IOPowerConnection
* connection
;
3732 PM_ASSERT_IN_GATE();
3733 assert(fNotifyChildArray
);
3734 assert(fMachineState
== kIOPM_NotifyChildrenDelayed
);
3736 // Wait after all non-delayed children and interested drivers have ack'ed,
3737 // then notify all delayed children. When explicitly cancelled, interest
3738 // acks (and ack timer) may still be outstanding.
3740 for (int i
= 0; ; i
++)
3742 connection
= (IOPowerConnection
*) fNotifyChildArray
->getObject(i
);
3746 notifyChild( connection
);
3749 PM_LOG2("%s: notified delayed children\n", getName());
3750 fNotifyChildArray
->release();
3751 fNotifyChildArray
= 0;
3753 MS_POP(); // pushed by notifyChildren()
3756 //*********************************************************************************
3757 // [private] notifyAll
3758 //*********************************************************************************
3760 IOReturn
IOService::notifyAll ( uint32_t nextMS
)
3762 // Save the next machine_state to be restored by notifyInterestedDriversDone()
3764 PM_ASSERT_IN_GATE();
3766 fMachineState
= kIOPM_DriverThreadCallDone
;
3767 fDriverCallReason
= fIsPreChange
?
3768 kDriverCallInformPreChange
: kDriverCallInformPostChange
;
3770 if (!notifyInterestedDrivers())
3771 notifyInterestedDriversDone();
3773 return IOPMWillAckLater
;
3776 //*********************************************************************************
3777 // [private, static] pmDriverCallout
3779 // Thread call context
3780 //*********************************************************************************
3782 IOReturn
IOService::actionDriverCalloutDone (
3784 void * arg0
, void * arg1
,
3785 void * arg2
, void * arg3
)
3787 IOServicePM
* pwrMgt
= (IOServicePM
*) arg0
;
3789 assert( fDriverCallBusy
);
3790 fDriverCallBusy
= false;
3792 assert(gIOPMWorkQueue
);
3793 gIOPMWorkQueue
->signalWorkAvailable();
3795 return kIOReturnSuccess
;
3798 void IOService::pmDriverCallout ( IOService
* from
)
3801 switch (from
->fDriverCallReason
)
3803 case kDriverCallSetPowerState
:
3804 from
->driverSetPowerState();
3807 case kDriverCallInformPreChange
:
3808 case kDriverCallInformPostChange
:
3809 from
->driverInformPowerChange();
3813 panic("IOService::pmDriverCallout bad machine state %x",
3814 from
->fDriverCallReason
);
3817 gIOPMWorkLoop
->runAction(actionDriverCalloutDone
,
3819 /* arg0 */ (void *) from
->pwrMgt
);
3822 //*********************************************************************************
3823 // [private] driverSetPowerState
3825 // Thread call context
3826 //*********************************************************************************
3828 void IOService::driverSetPowerState ( void )
3830 IOPMPowerStateIndex powerState
;
3831 DriverCallParam
* param
;
3832 IOPMDriverCallEntry callEntry
;
3835 uint32_t oldPowerState
= getPowerState();
3837 assert( fDriverCallBusy
);
3838 assert( fDriverCallParamPtr
);
3839 assert( fDriverCallParamCount
== 1 );
3841 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3842 powerState
= fHeadNotePowerState
;
3844 if (assertPMDriverCall(&callEntry
))
3846 OUR_PMLog( kPMLogProgramHardware
, (uintptr_t) this, powerState
);
3847 clock_get_uptime(&fDriverCallStartTime
);
3848 result
= fControllingDriver
->setPowerState( powerState
, this );
3849 clock_get_uptime(&end
);
3850 OUR_PMLog((UInt32
) -kPMLogProgramHardware
, (uintptr_t) this, (UInt32
) result
);
3852 deassertPMDriverCall(&callEntry
);
3856 PM_LOG("%s::setPowerState(%p, %lu -> %lu) returned 0x%x\n",
3857 fName
, this, fCurrentPowerState
, powerState
, result
);
3860 #if LOG_SETPOWER_TIMES
3861 if ((result
== IOPMAckImplied
) || (result
< 0))
3865 SUB_ABSOLUTETIME(&end
, &fDriverCallStartTime
);
3866 absolutetime_to_nanoseconds(end
, &nsec
);
3867 if (nsec
> LOG_SETPOWER_TIMES
)
3868 PM_LOG("%s::setPowerState(%p, %lu -> %lu) took %d ms\n",
3869 fName
, this, fCurrentPowerState
, powerState
, NS_TO_MS(nsec
));
3871 PMEventDetails
*details
= PMEventDetails::eventDetails(
3872 kIOPMEventTypeSetPowerStateImmediate
, // type
3874 (uintptr_t)this, // owner unique
3875 NULL
, // interest name
3876 (uint8_t)oldPowerState
, // old
3877 (uint8_t)powerState
, // new
3879 NS_TO_US(nsec
)); // usec completion time
3881 getPMRootDomain()->recordAndReleasePMEventGated( details
);
3886 result
= kIOPMAckImplied
;
3888 param
->Result
= result
;
3891 //*********************************************************************************
3892 // [private] driverInformPowerChange
3894 // Thread call context
3895 //*********************************************************************************
3897 void IOService::driverInformPowerChange ( void )
3899 IOPMinformee
* informee
;
3901 DriverCallParam
* param
;
3902 IOPMDriverCallEntry callEntry
;
3903 IOPMPowerFlags powerFlags
;
3904 IOPMPowerStateIndex powerState
;
3909 assert( fDriverCallBusy
);
3910 assert( fDriverCallParamPtr
);
3911 assert( fDriverCallParamCount
);
3913 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3914 count
= fDriverCallParamCount
;
3916 powerFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
3917 powerState
= fHeadNotePowerState
;
3919 for (IOItemCount i
= 0; i
< count
; i
++)
3921 informee
= (IOPMinformee
*) param
->Target
;
3922 driver
= informee
->whatObject
;
3924 if (assertPMDriverCall(&callEntry
, 0, informee
))
3926 if (fDriverCallReason
== kDriverCallInformPreChange
)
3928 OUR_PMLog(kPMLogInformDriverPreChange
, (uintptr_t) this, powerState
);
3929 clock_get_uptime(&informee
->startTime
);
3930 result
= driver
->powerStateWillChangeTo(powerFlags
, powerState
, this);
3931 clock_get_uptime(&end
);
3932 OUR_PMLog((UInt32
)-kPMLogInformDriverPreChange
, (uintptr_t) this, result
);
3936 OUR_PMLog(kPMLogInformDriverPostChange
, (uintptr_t) this, powerState
);
3937 clock_get_uptime(&informee
->startTime
);
3938 result
= driver
->powerStateDidChangeTo(powerFlags
, powerState
, this);
3939 clock_get_uptime(&end
);
3940 OUR_PMLog((UInt32
)-kPMLogInformDriverPostChange
, (uintptr_t) this, result
);
3943 deassertPMDriverCall(&callEntry
);
3945 #if LOG_SETPOWER_TIMES
3946 if ((result
== IOPMAckImplied
) || (result
< 0))
3950 SUB_ABSOLUTETIME(&end
, &informee
->startTime
);
3951 absolutetime_to_nanoseconds(end
, &nsec
);
3952 if (nsec
> LOG_SETPOWER_TIMES
)
3953 PM_LOG("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) took %d ms\n",
3955 (fDriverCallReason
== kDriverCallInformPreChange
) ? "Will" : "Did",
3956 driver
, fName
, fCurrentPowerState
, powerState
, NS_TO_MS(nsec
));
3958 uint16_t logType
= (fDriverCallReason
== kDriverCallInformPreChange
)
3959 ? kIOPMEventTypePSWillChangeTo
3960 : kIOPMEventTypePSDidChangeTo
;
3962 PMEventDetails
*details
= PMEventDetails::eventDetails(
3965 (uintptr_t)this, // owner unique
3966 driver
->getName(), // interest name
3967 (uint8_t)fCurrentPowerState
, // old
3968 (uint8_t)fHeadNotePowerState
, // new
3970 NS_TO_US(nsec
)); // usec completion time
3972 getPMRootDomain()->recordAndReleasePMEventGated( details
);
3977 result
= kIOPMAckImplied
;
3979 param
->Result
= result
;
3984 //*********************************************************************************
3985 // [private] notifyChild
3987 // Notify a power domain child of an upcoming power change.
3988 // If the object acknowledges the current change, we return TRUE.
3989 //*********************************************************************************
3991 bool IOService::notifyChild ( IOPowerConnection
* theNub
)
3993 IOReturn ret
= IOPMAckImplied
;
3994 unsigned long childPower
;
3995 IOService
* theChild
;
3996 IOPMRequest
* childRequest
;
3997 IOPMPowerChangeFlags requestArg2
;
4000 PM_ASSERT_IN_GATE();
4001 theChild
= (IOService
*)(theNub
->copyChildEntry(gIOPowerPlane
));
4007 // Unless the child handles the notification immediately and returns
4008 // kIOPMAckImplied, we'll be awaiting their acknowledgement later.
4009 fHeadNotePendingAcks
++;
4010 theNub
->setAwaitingAck(true);
4012 requestArg2
= fHeadNoteChangeFlags
;
4013 if (fHeadNotePowerState
< fCurrentPowerState
)
4014 requestArg2
|= kIOPMDomainPowerDrop
;
4016 requestType
= fIsPreChange
?
4017 kIOPMRequestTypePowerDomainWillChange
:
4018 kIOPMRequestTypePowerDomainDidChange
;
4020 childRequest
= acquirePMRequest( theChild
, requestType
);
4024 childRequest
->fArg0
= (void *) fHeadNotePowerArrayEntry
->outputPowerFlags
;
4025 childRequest
->fArg1
= (void *) theNub
;
4026 childRequest
->fArg2
= (void *) requestArg2
;
4027 theChild
->submitPMRequest( childRequest
);
4028 ret
= IOPMWillAckLater
;
4032 ret
= IOPMAckImplied
;
4033 fHeadNotePendingAcks
--;
4034 theNub
->setAwaitingAck(false);
4035 childPower
= theChild
->currentPowerConsumption();
4036 if ( childPower
== kIOPMUnknown
)
4038 fHeadNotePowerArrayEntry
->staticPower
= kIOPMUnknown
;
4040 if (fHeadNotePowerArrayEntry
->staticPower
!= kIOPMUnknown
)
4041 fHeadNotePowerArrayEntry
->staticPower
+= childPower
;
4045 theChild
->release();
4046 return (IOPMAckImplied
== ret
);
4049 //*********************************************************************************
4050 // [private] notifyControllingDriver
4051 //*********************************************************************************
4053 bool IOService::notifyControllingDriver ( void )
4055 DriverCallParam
* param
;
4057 PM_ASSERT_IN_GATE();
4058 assert( fDriverCallParamCount
== 0 );
4059 assert( fControllingDriver
);
4061 if (fInitialSetPowerState
)
4063 fInitialSetPowerState
= false;
4064 fHeadNoteChangeFlags
|= kIOPMInitialPowerChange
;
4066 // Driver specified flag to skip the inital setPowerState()
4067 if (fHeadNotePowerArrayEntry
->capabilityFlags
& kIOPMInitialDeviceState
)
4073 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4076 param
= IONew(DriverCallParam
, 1);
4078 return false; // no memory
4080 fDriverCallParamPtr
= (void *) param
;
4081 fDriverCallParamSlots
= 1;
4084 param
->Target
= fControllingDriver
;
4085 fDriverCallParamCount
= 1;
4088 // Block state machine and wait for callout completion.
4089 assert(!fDriverCallBusy
);
4090 fDriverCallBusy
= true;
4091 thread_call_enter( fDriverCallEntry
);
4096 //*********************************************************************************
4097 // [private] notifyControllingDriverDone
4098 //*********************************************************************************
4100 void IOService::notifyControllingDriverDone( void )
4102 DriverCallParam
* param
;
4105 PM_ASSERT_IN_GATE();
4106 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4108 assert( fDriverCallBusy
== false );
4109 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
4111 if (param
&& fDriverCallParamCount
)
4113 assert(fDriverCallParamCount
== 1);
4115 // the return value from setPowerState()
4116 result
= param
->Result
;
4118 if ((result
== IOPMAckImplied
) || (result
< 0))
4122 else if (fDriverTimer
)
4124 assert(fDriverTimer
== -1);
4126 // Driver has not acked, and has returned a positive result.
4127 // Enforce a minimum permissible timeout value.
4128 // Make the min value large enough so timeout is less likely
4129 // to occur if a driver misinterpreted that the return value
4130 // should be in microsecond units. And make it large enough
4131 // to be noticeable if a driver neglects to ack.
4133 if (result
< kMinAckTimeoutTicks
)
4134 result
= kMinAckTimeoutTicks
;
4136 fDriverTimer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
4138 // else, child has already acked and driver_timer reset to 0.
4140 fDriverCallParamCount
= 0;
4144 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
4149 MS_POP(); // pushed by OurChangeSetPowerState()
4150 fIsPreChange
= false;
4153 //*********************************************************************************
4154 // [private] all_done
4156 // A power change is done.
4157 //*********************************************************************************
4159 void IOService::all_done ( void )
4161 IOPMPowerStateIndex prevPowerState
;
4162 const IOPMPSEntry
* powerStatePtr
;
4163 IOPMDriverCallEntry callEntry
;
4164 uint32_t prevMachineState
= fMachineState
;
4165 bool callAction
= false;
4167 fMachineState
= kIOPM_Finished
;
4169 if ((fHeadNoteChangeFlags
& kIOPMSynchronize
) &&
4170 ((prevMachineState
== kIOPM_Finished
) ||
4171 (prevMachineState
== kIOPM_SyncFinish
)))
4173 // Sync operation and no power change occurred.
4174 // Do not inform driver and clients about this request completion,
4175 // except for the originator (root domain).
4177 PM_ACTION_2(actionPowerChangeDone
,
4178 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4180 if (getPMRequestType() == kIOPMRequestTypeSynchronizePowerTree
)
4182 powerChangeDone(fCurrentPowerState
);
4184 else if (fAdvisoryTickleUsed
)
4186 // Not root domain and advisory tickle target.
4187 // Re-adjust power after power tree sync at the 'did' pass
4188 // to recompute desire and adjust power state between dark
4189 // and full wake transitions. Root domain is responsible
4190 // for calling setAdvisoryTickleEnable() before starting
4191 // the kIOPMSynchronize power change.
4193 if (!fAdjustPowerScheduled
&&
4194 (fHeadNoteChangeFlags
& kIOPMDomainDidChange
))
4196 IOPMRequest
* request
;
4197 request
= acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState
);
4200 submitPMRequest( request
);
4201 fAdjustPowerScheduled
= true;
4210 if ( fHeadNoteChangeFlags
& kIOPMSelfInitiated
)
4212 // could our driver switch to the new state?
4213 if ( !( fHeadNoteChangeFlags
& kIOPMNotDone
) )
4215 trackSystemSleepPreventers(
4216 fCurrentPowerState
, fHeadNotePowerState
, fHeadNoteChangeFlags
);
4218 // we changed, tell our parent
4219 requestDomainPower(fHeadNotePowerState
);
4221 // yes, did power raise?
4222 if ( fCurrentPowerState
< fHeadNotePowerState
)
4224 // yes, inform clients and apps
4225 tellChangeUp (fHeadNotePowerState
);
4227 prevPowerState
= fCurrentPowerState
;
4229 fCurrentPowerState
= fHeadNotePowerState
;
4231 fPMVars
->myCurrentState
= fCurrentPowerState
;
4233 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, prevPowerState
);
4234 PM_ACTION_2(actionPowerChangeDone
,
4235 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4238 powerStatePtr
= &fPowerStates
[fCurrentPowerState
];
4239 fCurrentCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4240 if (fCurrentCapabilityFlags
& kIOPMStaticPowerValid
)
4241 fCurrentPowerConsumption
= powerStatePtr
->staticPower
;
4243 if (fHeadNoteChangeFlags
& kIOPMRootChangeDown
)
4245 // Bump tickle generation count once the entire tree is down
4246 gIOPMTickleGeneration
++;
4249 // inform subclass policy-maker
4250 if (fPCDFunctionOverride
&& fParentsKnowState
&&
4251 assertPMDriverCall(&callEntry
, kIOPMADC_NoInactiveCheck
))
4253 powerChangeDone(prevPowerState
);
4254 deassertPMDriverCall(&callEntry
);
4257 else if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)
4259 // changePowerStateWithOverrideTo() was cancelled
4260 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
4264 // parent's power change
4265 if ( fHeadNoteChangeFlags
& kIOPMParentInitiated
)
4267 if (fHeadNoteChangeFlags
& kIOPMRootChangeDown
)
4268 ParentChangeRootChangeDown();
4270 if (((fHeadNoteChangeFlags
& kIOPMDomainWillChange
) &&
4271 (fCurrentPowerState
>= fHeadNotePowerState
)) ||
4272 ((fHeadNoteChangeFlags
& kIOPMDomainDidChange
) &&
4273 (fCurrentPowerState
< fHeadNotePowerState
)))
4275 trackSystemSleepPreventers(
4276 fCurrentPowerState
, fHeadNotePowerState
, fHeadNoteChangeFlags
);
4279 if ( fCurrentPowerState
< fHeadNotePowerState
)
4281 // yes, inform clients and apps
4282 tellChangeUp (fHeadNotePowerState
);
4285 prevPowerState
= fCurrentPowerState
;
4286 fCurrentPowerState
= fHeadNotePowerState
;
4288 fPMVars
->myCurrentState
= fCurrentPowerState
;
4290 fMaxPowerState
= fControllingDriver
->maxCapabilityForDomainState(fHeadNoteDomainFlags
);
4292 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, prevPowerState
);
4293 PM_ACTION_2(actionPowerChangeDone
,
4294 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4297 powerStatePtr
= &fPowerStates
[fCurrentPowerState
];
4298 fCurrentCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4299 if (fCurrentCapabilityFlags
& kIOPMStaticPowerValid
)
4300 fCurrentPowerConsumption
= powerStatePtr
->staticPower
;
4302 // inform subclass policy-maker
4303 if (fPCDFunctionOverride
&& fParentsKnowState
&&
4304 assertPMDriverCall(&callEntry
, kIOPMADC_NoInactiveCheck
))
4306 powerChangeDone(prevPowerState
);
4307 deassertPMDriverCall(&callEntry
);
4312 // When power rises enough to satisfy the tickle's desire for more power,
4313 // the condition preventing idle-timer from dropping power is removed.
4315 if (fCurrentPowerState
>= fIdleTimerMinPowerState
)
4317 fIdleTimerMinPowerState
= 0;
4322 PM_ACTION_2(actionPowerChangeDone
,
4323 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4328 // MARK: Power Change Initiated by Driver
4330 //*********************************************************************************
4331 // [private] OurChangeStart
4333 // Begin the processing of a power change initiated by us.
4334 //*********************************************************************************
4336 void IOService::OurChangeStart ( void )
4338 PM_ASSERT_IN_GATE();
4339 OUR_PMLog( kPMLogStartDeviceChange
, fHeadNotePowerState
, fCurrentPowerState
);
4341 // fMaxPowerState is our maximum possible power state based on the current
4342 // power state of our parents. If we are trying to raise power beyond the
4343 // maximum, send an async request for more power to all parents.
4345 if (!IS_PM_ROOT
&& (fMaxPowerState
< fHeadNotePowerState
))
4347 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4348 requestDomainPower(fHeadNotePowerState
);
4353 // Redundant power changes skips to the end of the state machine.
4355 if (!fInitialPowerChange
&& (fHeadNotePowerState
== fCurrentPowerState
))
4360 fInitialPowerChange
= false;
4362 // Change started, but may not complete...
4363 // Can be canceled (power drop) or deferred (power rise).
4365 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4367 // Two separate paths, depending if power is being raised or lowered.
4368 // Lowering power is subject to approval by clients of this service.
4372 fDoNotPowerDown
= false;
4374 // Ask for persmission to drop power state
4375 fMachineState
= kIOPM_OurChangeTellClientsPowerDown
;
4376 fOutOfBandParameter
= kNotifyApps
;
4377 askChangeDown(fHeadNotePowerState
);
4381 // This service is raising power and parents are able to support the
4382 // new power state. However a parent may have already committed to
4383 // drop power, which might force this object to temporarily drop power.
4384 // This results in "oscillations" before the state machines converge
4385 // to a steady state.
4387 // To prevent this, a child must make a power reservation against all
4388 // parents before raising power. If the reservation fails, indicating
4389 // that the child will be unable to sustain the higher power state,
4390 // then the child will signal the parent to adjust power, and the child
4391 // will defer its power change.
4395 // Reserve parent power necessary to achieve fHeadNotePowerState.
4396 ret
= requestDomainPower( fHeadNotePowerState
, kReserveDomainPower
);
4397 if (ret
!= kIOReturnSuccess
)
4399 // Reservation failed, defer power rise.
4400 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4405 OurChangeTellCapabilityWillChange();
4409 //*********************************************************************************
4410 // [private] requestDomainPowerApplier
4412 // Call requestPowerDomainState() on all power parents.
4413 //*********************************************************************************
4415 struct IOPMRequestDomainPowerContext
{
4416 IOService
* child
; // the requesting child
4417 IOPMPowerFlags requestPowerFlags
; // power flags requested by child
4421 requestDomainPowerApplier(
4422 IORegistryEntry
* entry
,
4425 IOPowerConnection
* connection
;
4427 IOPMRequestDomainPowerContext
* context
;
4429 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)) == 0)
4431 parent
= (IOService
*) connection
->copyParentEntry(gIOPowerPlane
);
4436 context
= (IOPMRequestDomainPowerContext
*) inContext
;
4438 if (connection
->parentKnowsState() && connection
->getReadyFlag())
4440 parent
->requestPowerDomainState(
4441 context
->requestPowerFlags
,
4449 //*********************************************************************************
4450 // [private] requestDomainPower
4452 // Called by a power child to broadcast its desired power state to all parents.
4453 // If the child self-initiates a power change, it must call this function to
4454 // allow its parents to adjust power state.
4455 //*********************************************************************************
4457 IOReturn
IOService::requestDomainPower(
4458 IOPMPowerStateIndex ourPowerState
,
4459 IOOptionBits options
)
4461 IOPMPowerFlags requestPowerFlags
;
4462 IOPMPowerStateIndex maxPowerState
;
4463 IOPMRequestDomainPowerContext context
;
4465 PM_ASSERT_IN_GATE();
4466 assert(ourPowerState
< fNumberOfPowerStates
);
4467 if (ourPowerState
>= fNumberOfPowerStates
)
4468 return kIOReturnBadArgument
;
4470 return kIOReturnSuccess
;
4472 // Fetch our input power flags for the requested power state.
4473 // Parent request is stated in terms of required power flags.
4475 requestPowerFlags
= fPowerStates
[ourPowerState
].inputPowerFlags
;
4477 // Disregard the "previous request" for power reservation.
4479 if (((options
& kReserveDomainPower
) == 0) &&
4480 (fPreviousRequestPowerFlags
== requestPowerFlags
))
4482 // skip if domain already knows our requirements
4485 fPreviousRequestPowerFlags
= requestPowerFlags
;
4487 // The results will be collected by fHeadNoteDomainTargetFlags
4488 context
.child
= this;
4489 context
.requestPowerFlags
= requestPowerFlags
;
4490 fHeadNoteDomainTargetFlags
= 0;
4491 applyToParents(requestDomainPowerApplier
, &context
, gIOPowerPlane
);
4493 if (options
& kReserveDomainPower
)
4495 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
4496 fHeadNoteDomainTargetFlags
);
4498 if (maxPowerState
< ourPowerState
)
4500 PM_LOG1("%s: power desired %u:0x%x got %u:0x%x\n",
4502 (uint32_t) ourPowerState
, (uint32_t) requestPowerFlags
,
4503 (uint32_t) maxPowerState
, (uint32_t) fHeadNoteDomainTargetFlags
);
4504 return kIOReturnNoPower
;
4509 return kIOReturnSuccess
;
4512 //*********************************************************************************
4513 // [private] OurSyncStart
4514 //*********************************************************************************
4516 void IOService::OurSyncStart ( void )
4518 PM_ASSERT_IN_GATE();
4520 if (fInitialPowerChange
)
4523 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4525 if (fHeadNoteChangeFlags
& kIOPMNotDone
)
4531 if (fHeadNoteChangeFlags
& kIOPMSyncTellPowerDown
)
4533 fDoNotPowerDown
= false;
4535 // Ask for permission to drop power state
4536 fMachineState
= kIOPM_SyncTellClientsPowerDown
;
4537 fOutOfBandParameter
= kNotifyApps
;
4538 askChangeDown(fHeadNotePowerState
);
4542 // Only inform capability app and clients.
4543 tellSystemCapabilityChange( kIOPM_SyncNotifyWillChange
);
4547 //*********************************************************************************
4548 // [private] OurChangeTellClientsPowerDown
4550 // All applications and kernel clients have acknowledged our permission to drop
4551 // power. Here we notify them that we will lower the power and wait for acks.
4552 //*********************************************************************************
4554 void IOService::OurChangeTellClientsPowerDown ( void )
4556 fMachineState
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
4557 tellChangeDown1(fHeadNotePowerState
);
4560 //*********************************************************************************
4561 // [private] OurChangeTellPriorityClientsPowerDown
4563 // All applications and kernel clients have acknowledged our intention to drop
4564 // power. Here we notify "priority" clients that we are lowering power.
4565 //*********************************************************************************
4567 void IOService::OurChangeTellPriorityClientsPowerDown ( void )
4569 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversWillChange
;
4570 tellChangeDown2(fHeadNotePowerState
);
4573 //*********************************************************************************
4574 // [private] OurChangeTellCapabilityWillChange
4576 // Extra stage for root domain to notify apps and drivers about the
4577 // system capability change when raising power state.
4578 //*********************************************************************************
4580 void IOService::OurChangeTellCapabilityWillChange ( void )
4582 if (!IS_ROOT_DOMAIN
)
4583 return OurChangeNotifyInterestedDriversWillChange();
4585 tellSystemCapabilityChange( kIOPM_OurChangeNotifyInterestedDriversWillChange
);
4588 //*********************************************************************************
4589 // [private] OurChangeNotifyInterestedDriversWillChange
4591 // All applications and kernel clients have acknowledged our power state change.
4592 // Here we notify interested drivers pre-change.
4593 //*********************************************************************************
4595 void IOService::OurChangeNotifyInterestedDriversWillChange ( void )
4597 IOPMrootDomain
* rootDomain
;
4598 if ((rootDomain
= getPMRootDomain()) == this)
4602 rootDomain
->tracePoint( kIOPMTracePointSleepWillChangeInterests
);
4604 PMEventDetails
*details
= PMEventDetails::eventDetails(
4605 kIOPMEventTypeAppNotificationsFinished
,
4609 rootDomain
->recordAndReleasePMEventGated( details
);
4612 rootDomain
->tracePoint( kIOPMTracePointWakeWillChangeInterests
);
4615 notifyAll( kIOPM_OurChangeSetPowerState
);
4618 //*********************************************************************************
4619 // [private] OurChangeSetPowerState
4621 // Instruct our controlling driver to program the hardware for the power state
4622 // change. Wait for async completions.
4623 //*********************************************************************************
4625 void IOService::OurChangeSetPowerState ( void )
4627 MS_PUSH( kIOPM_OurChangeWaitForPowerSettle
);
4628 fMachineState
= kIOPM_DriverThreadCallDone
;
4629 fDriverCallReason
= kDriverCallSetPowerState
;
4631 if (notifyControllingDriver() == false)
4632 notifyControllingDriverDone();
4635 //*********************************************************************************
4636 // [private] OurChangeWaitForPowerSettle
4638 // Our controlling driver has completed the power state change we initiated.
4639 // Wait for the driver specified settle time to expire.
4640 //*********************************************************************************
4642 void IOService::OurChangeWaitForPowerSettle ( void )
4644 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversDidChange
;
4648 //*********************************************************************************
4649 // [private] OurChangeNotifyInterestedDriversDidChange
4651 // Power has settled on a power change we initiated. Here we notify
4652 // all our interested drivers post-change.
4653 //*********************************************************************************
4655 void IOService::OurChangeNotifyInterestedDriversDidChange ( void )
4657 IOPMrootDomain
* rootDomain
;
4658 if ((rootDomain
= getPMRootDomain()) == this)
4660 rootDomain
->tracePoint( IS_POWER_DROP
?
4661 kIOPMTracePointSleepDidChangeInterests
:
4662 kIOPMTracePointWakeDidChangeInterests
);
4665 notifyAll( kIOPM_OurChangeTellCapabilityDidChange
);
4668 //*********************************************************************************
4669 // [private] OurChangeTellCapabilityDidChange
4671 // For root domain to notify capability power-change.
4672 //*********************************************************************************
4674 void IOService::OurChangeTellCapabilityDidChange ( void )
4676 if (!IS_ROOT_DOMAIN
)
4677 return OurChangeFinish();
4679 getPMRootDomain()->tracePoint( IS_POWER_DROP
?
4680 kIOPMTracePointSleepCapabilityClients
:
4681 kIOPMTracePointWakeCapabilityClients
);
4683 tellSystemCapabilityChange( kIOPM_OurChangeFinish
);
4686 //*********************************************************************************
4687 // [private] OurChangeFinish
4689 // Done with this self-induced power state change.
4690 //*********************************************************************************
4692 void IOService::OurChangeFinish ( void )
4698 // MARK: Power Change Initiated by Parent
4700 //*********************************************************************************
4701 // [private] ParentChangeStart
4703 // Here we begin the processing of a power change initiated by our parent.
4704 //*********************************************************************************
4706 IOReturn
IOService::ParentChangeStart ( void )
4708 PM_ASSERT_IN_GATE();
4709 OUR_PMLog( kPMLogStartParentChange
, fHeadNotePowerState
, fCurrentPowerState
);
4711 // Root power domain has transitioned to its max power state
4712 if ((fHeadNoteChangeFlags
& (kIOPMDomainDidChange
| kIOPMRootChangeUp
)) ==
4713 (kIOPMDomainDidChange
| kIOPMRootChangeUp
))
4715 // Restart the idle timer stopped by ParentChangeRootChangeDown()
4716 if (fIdleTimerPeriod
&& fIdleTimerStopped
)
4722 // Power domain is forcing us to lower power
4723 if ( fHeadNotePowerState
< fCurrentPowerState
)
4725 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4727 // Tell apps and kernel clients
4728 fInitialPowerChange
= false;
4729 fMachineState
= kIOPM_ParentChangeTellPriorityClientsPowerDown
;
4730 tellChangeDown1(fHeadNotePowerState
);
4731 return IOPMWillAckLater
;
4734 // Power domain is raising power
4735 if ( fHeadNotePowerState
> fCurrentPowerState
)
4737 if ( fDesiredPowerState
> fCurrentPowerState
)
4739 if ( fDesiredPowerState
< fHeadNotePowerState
)
4741 // We power up, but not all the way
4742 fHeadNotePowerState
= fDesiredPowerState
;
4743 fHeadNotePowerArrayEntry
= &fPowerStates
[fDesiredPowerState
];
4744 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
4747 // We don't need to change
4748 fHeadNotePowerState
= fCurrentPowerState
;
4749 fHeadNotePowerArrayEntry
= &fPowerStates
[fCurrentPowerState
];
4750 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
4754 if ( fHeadNoteChangeFlags
& kIOPMDomainDidChange
)
4756 if ( fHeadNotePowerState
> fCurrentPowerState
)
4758 PM_ACTION_2(actionPowerChangeStart
,
4759 fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4761 // Parent did change up - start our change up
4762 fInitialPowerChange
= false;
4763 ParentChangeTellCapabilityWillChange();
4764 return IOPMWillAckLater
;
4766 else if (fHeadNoteChangeFlags
& kIOPMRootBroadcastFlags
)
4768 // No need to change power state, but broadcast change
4770 fMachineState
= kIOPM_SyncNotifyDidChange
;
4771 fDriverCallReason
= kDriverCallInformPreChange
;
4773 return IOPMWillAckLater
;
4778 return IOPMAckImplied
;
4781 //******************************************************************************
4782 // [private] ParentChangeRootChangeDown
4784 // Root domain has finished the transition to the system sleep state. And all
4785 // drivers in the power plane should have powered down. Cancel the idle timer,
4786 // and also reset the device desire for those drivers that don't want power
4787 // automatically restored on wake.
4788 //******************************************************************************
4790 void IOService::ParentChangeRootChangeDown( void )
4792 // Always stop the idle timer before root power down
4793 if (fIdleTimerPeriod
&& !fIdleTimerStopped
)
4795 fIdleTimerStopped
= true;
4796 if (fIdleTimer
&& thread_call_cancel(fIdleTimer
))
4800 if (fResetPowerStateOnWake
)
4802 // Reset device desire down to the lowest power state.
4803 // Advisory tickle desire is intentionally untouched since
4804 // it has no effect until system is promoted to full wake.
4806 if (fDeviceDesire
!= 0)
4808 updatePowerClient(gIOPMPowerClientDevice
, 0);
4809 computeDesiredState(0, true);
4810 PM_LOG1("%s: tickle desire removed\n", fName
);
4813 // Invalidate tickle cache so the next tickle will issue a request
4814 IOLockLock(fActivityLock
);
4815 fDeviceWasActive
= false;
4816 fActivityTicklePowerState
= kInvalidTicklePowerState
;
4817 IOLockUnlock(fActivityLock
);
4819 fIdleTimerMinPowerState
= 0;
4821 else if (fAdvisoryTickleUsed
)
4823 // Less aggressive mechanism to accelerate idle timer expiration
4824 // before system sleep. May not always allow the driver to wake
4825 // up from system sleep in the min power state.
4829 bool dropTickleDesire
= false;
4831 if (fIdleTimerPeriod
&& !fIdleTimerIgnored
&&
4832 (fIdleTimerMinPowerState
== 0) &&
4833 (fDeviceDesire
!= 0))
4835 IOLockLock(fActivityLock
);
4837 if (!fDeviceWasActive
)
4839 // No tickles since the last idle timer expiration.
4840 // Safe to drop the device desire to zero.
4841 dropTickleDesire
= true;
4845 // Was tickled since the last idle timer expiration,
4846 // but not in the last minute.
4847 clock_get_uptime(&now
);
4848 SUB_ABSOLUTETIME(&now
, &fDeviceActiveTimestamp
);
4849 absolutetime_to_nanoseconds(now
, &nsec
);
4850 if (nsec
>= kNoTickleCancelWindow
)
4852 dropTickleDesire
= true;
4856 if (dropTickleDesire
)
4858 // Force the next tickle to raise power state
4859 fDeviceWasActive
= false;
4860 fActivityTicklePowerState
= kInvalidTicklePowerState
;
4863 IOLockUnlock(fActivityLock
);
4866 if (dropTickleDesire
)
4868 // Advisory tickle desire is intentionally untouched since
4869 // it has no effect until system is promoted to full wake.
4871 updatePowerClient(gIOPMPowerClientDevice
, 0);
4872 computeDesiredState(0, true);
4873 PM_LOG1("%s: tickle desire dropped\n", fName
);
4878 //*********************************************************************************
4879 // [private] ParentChangeTellPriorityClientsPowerDown
4881 // All applications and kernel clients have acknowledged our intention to drop
4882 // power. Here we notify "priority" clients that we are lowering power.
4883 //*********************************************************************************
4885 void IOService::ParentChangeTellPriorityClientsPowerDown ( void )
4887 fMachineState
= kIOPM_ParentChangeNotifyInterestedDriversWillChange
;
4888 tellChangeDown2(fHeadNotePowerState
);
4891 //*********************************************************************************
4892 // [private] ParentChangeTellCapabilityWillChange
4894 // All (legacy) applications and kernel clients have acknowledged, extra stage for
4895 // root domain to notify apps and drivers about the system capability change.
4896 //*********************************************************************************
4898 void IOService::ParentChangeTellCapabilityWillChange ( void )
4900 if (!IS_ROOT_DOMAIN
)
4901 return ParentChangeNotifyInterestedDriversWillChange();
4903 tellSystemCapabilityChange( kIOPM_ParentChangeNotifyInterestedDriversWillChange
);
4906 //*********************************************************************************
4907 // [private] ParentChangeNotifyInterestedDriversWillChange
4909 // All applications and kernel clients have acknowledged our power state change.
4910 // Here we notify interested drivers pre-change.
4911 //*********************************************************************************
4913 void IOService::ParentChangeNotifyInterestedDriversWillChange ( void )
4915 notifyAll( kIOPM_ParentChangeSetPowerState
);
4918 //*********************************************************************************
4919 // [private] ParentChangeSetPowerState
4921 // Instruct our controlling driver to program the hardware for the power state
4922 // change. Wait for async completions.
4923 //*********************************************************************************
4925 void IOService::ParentChangeSetPowerState ( void )
4927 MS_PUSH( kIOPM_ParentChangeWaitForPowerSettle
);
4928 fMachineState
= kIOPM_DriverThreadCallDone
;
4929 fDriverCallReason
= kDriverCallSetPowerState
;
4931 if (notifyControllingDriver() == false)
4932 notifyControllingDriverDone();
4935 //*********************************************************************************
4936 // [private] ParentChangeWaitForPowerSettle
4938 // Our controlling driver has completed the power state change initiated by our
4939 // parent. Wait for the driver specified settle time to expire.
4940 //*********************************************************************************
4942 void IOService::ParentChangeWaitForPowerSettle ( void )
4944 fMachineState
= kIOPM_ParentChangeNotifyInterestedDriversDidChange
;
4948 //*********************************************************************************
4949 // [private] ParentChangeNotifyInterestedDriversDidChange
4951 // Power has settled on a power change initiated by our parent. Here we notify
4952 // all our interested drivers post-change.
4953 //*********************************************************************************
4955 void IOService::ParentChangeNotifyInterestedDriversDidChange ( void )
4957 notifyAll( kIOPM_ParentChangeTellCapabilityDidChange
);
4960 //*********************************************************************************
4961 // [private] ParentChangeTellCapabilityDidChange
4963 // For root domain to notify capability power-change.
4964 //*********************************************************************************
4966 void IOService::ParentChangeTellCapabilityDidChange ( void )
4968 if (!IS_ROOT_DOMAIN
)
4969 return ParentChangeAcknowledgePowerChange();
4971 tellSystemCapabilityChange( kIOPM_ParentChangeAcknowledgePowerChange
);
4974 //*********************************************************************************
4975 // [private] ParentAcknowledgePowerChange
4977 // Acknowledge our power parent that our power change is done.
4978 //*********************************************************************************
4980 void IOService::ParentChangeAcknowledgePowerChange ( void )
4982 IORegistryEntry
* nub
;
4985 nub
= fHeadNoteParentConnection
;
4988 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
4991 parent
->acknowledgePowerChange((IOService
*)nub
);
4998 // MARK: Ack and Settle timers
5000 //*********************************************************************************
5001 // [private] settleTimerExpired
5003 // Power has settled after our last change. Notify interested parties that
5004 // there is a new power state.
5005 //*********************************************************************************
5007 void IOService::settleTimerExpired( void )
5010 gIOPMWorkQueue
->signalWorkAvailable();
5013 //*********************************************************************************
5014 // settle_timer_expired
5016 // Holds a retain while the settle timer callout is in flight.
5017 //*********************************************************************************
5020 settle_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5022 IOService
* me
= (IOService
*) arg0
;
5024 if (gIOPMWorkLoop
&& gIOPMWorkQueue
)
5026 gIOPMWorkLoop
->runAction(
5027 OSMemberFunctionCast(IOWorkLoop::Action
, me
, &IOService::settleTimerExpired
),
5033 //*********************************************************************************
5034 // [private] startSettleTimer
5036 // Calculate a power-settling delay in microseconds and start a timer.
5037 //*********************************************************************************
5039 void IOService::startSettleTimer( void )
5042 // This function is broken and serves no useful purpose since it never
5043 // updates fSettleTimeUS to a non-zero value to stall the state machine,
5044 // yet it starts a delay timer. It appears no driver relies on a delay
5045 // from settleUpTime and settleDownTime in the power state table.
5047 AbsoluteTime deadline
;
5048 IOPMPowerStateIndex i
;
5049 uint32_t settleTime
= 0;
5052 PM_ASSERT_IN_GATE();
5054 i
= fCurrentPowerState
;
5057 if ( fHeadNotePowerState
< fCurrentPowerState
)
5059 while ( i
> fHeadNotePowerState
)
5061 settleTime
+= (uint32_t) fPowerStates
[i
].settleDownTime
;
5067 if ( fHeadNotePowerState
> fCurrentPowerState
)
5069 while ( i
< fHeadNotePowerState
)
5071 settleTime
+= (uint32_t) fPowerStates
[i
+1].settleUpTime
;
5079 clock_interval_to_deadline(settleTime
, kMicrosecondScale
, &deadline
);
5080 pending
= thread_call_enter_delayed(fSettleTimer
, deadline
);
5081 if (pending
) release();
5086 //*********************************************************************************
5087 // [private] ackTimerTick
5089 // The acknowledgement timeout periodic timer has ticked.
5090 // If we are awaiting acks for a power change notification,
5091 // we decrement the timer word of each interested driver which hasn't acked.
5092 // If a timer word becomes zero, we pretend the driver aknowledged.
5093 // If we are waiting for the controlling driver to change the power
5094 // state of the hardware, we decrement its timer word, and if it becomes
5095 // zero, we pretend the driver acknowledged.
5097 // Returns true if the timer tick made it possible to advance to the next
5098 // machine state, false otherwise.
5099 //*********************************************************************************
5102 void IOService::ack_timer_ticked ( void )
5106 #endif /* !__LP64__ */
5108 bool IOService::ackTimerTick( void )
5110 IOPMinformee
* nextObject
;
5113 PM_ASSERT_IN_GATE();
5114 switch (fMachineState
) {
5115 case kIOPM_OurChangeWaitForPowerSettle
:
5116 case kIOPM_ParentChangeWaitForPowerSettle
:
5117 // are we waiting for controlling driver to acknowledge?
5118 if ( fDriverTimer
> 0 )
5120 // yes, decrement timer tick
5122 if ( fDriverTimer
== 0 )
5124 // controlling driver is tardy
5125 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
5126 OUR_PMLog(kPMLogCtrlDriverTardy
, 0, 0);
5127 setProperty(kIOPMTardyAckSPSKey
, kOSBooleanTrue
);
5128 PM_ERROR("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms\n",
5129 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5131 #if LOG_SETPOWER_TIMES
5132 PMEventDetails
*details
= PMEventDetails::eventDetails(
5133 kIOPMEventTypeSetPowerStateDelayed
, // type
5135 (uintptr_t)this, // owner unique
5136 NULL
, // interest name
5137 (uint8_t)getPowerState(), // old
5139 kIOReturnTimeout
, // result
5140 NS_TO_US(nsec
)); // usec completion time
5142 getPMRootDomain()->recordAndReleasePMEventGated( details
);
5145 if (gIOKitDebug
& kIOLogDebugPower
)
5147 panic("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms",
5148 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5152 // Unblock state machine and pretend driver has acked.
5156 // still waiting, set timer again
5162 case kIOPM_NotifyChildrenStart
:
5163 // are we waiting for interested parties to acknowledge?
5164 if ( fHeadNotePendingAcks
!= 0 )
5166 // yes, go through the list of interested drivers
5167 nextObject
= fInterestedDrivers
->firstInList();
5168 // and check each one
5169 while ( nextObject
!= NULL
)
5171 if ( nextObject
->timer
> 0 )
5173 nextObject
->timer
--;
5174 // this one should have acked by now
5175 if ( nextObject
->timer
== 0 )
5177 uint64_t nsec
= computeTimeDeltaNS(&nextObject
->startTime
);
5178 OUR_PMLog(kPMLogIntDriverTardy
, 0, 0);
5179 nextObject
->whatObject
->setProperty(kIOPMTardyAckPSCKey
, kOSBooleanTrue
);
5180 PM_ERROR("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) timed out after %d ms\n",
5181 nextObject
->whatObject
->getName(),
5182 (fDriverCallReason
== kDriverCallInformPreChange
) ? "Will" : "Did",
5183 nextObject
->whatObject
, fName
, fCurrentPowerState
, fHeadNotePowerState
,
5186 #if LOG_SETPOWER_TIMES
5187 uint16_t logType
= (fDriverCallReason
== kDriverCallInformPreChange
)
5188 ? kIOPMEventTypePSWillChangeTo
5189 : kIOPMEventTypePSDidChangeTo
;
5191 PMEventDetails
*details
= PMEventDetails::eventDetails(
5194 (uintptr_t)this, // owner unique
5195 nextObject
->whatObject
->getName(), // interest name
5196 (uint8_t)fCurrentPowerState
, // old
5197 (uint8_t)fHeadNotePowerState
, // new
5198 kIOReturnTimeout
, // result
5199 NS_TO_US(nsec
)); // usec completion time
5201 getPMRootDomain()->recordAndReleasePMEventGated( details
);
5204 // Pretend driver has acked.
5205 fHeadNotePendingAcks
--;
5208 nextObject
= fInterestedDrivers
->nextInList(nextObject
);
5211 // is that the last?
5212 if ( fHeadNotePendingAcks
== 0 )
5214 // yes, we can continue
5217 // no, set timer again
5223 // TODO: aggreggate this
5224 case kIOPM_OurChangeTellClientsPowerDown
:
5225 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
5226 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
5227 case kIOPM_ParentChangeTellPriorityClientsPowerDown
:
5228 case kIOPM_ParentChangeNotifyInterestedDriversWillChange
:
5229 case kIOPM_SyncTellClientsPowerDown
:
5230 case kIOPM_SyncTellPriorityClientsPowerDown
:
5231 case kIOPM_SyncNotifyWillChange
:
5232 case kIOPM_TellCapabilityChangeDone
:
5233 // apps didn't respond in time
5234 cleanClientResponses(true);
5235 OUR_PMLog(kPMLogClientTardy
, 0, 1);
5236 // tardy equates to approval
5241 PM_LOG1("%s: unexpected ack timer tick (state = %d)\n",
5242 getName(), fMachineState
);
5248 //*********************************************************************************
5249 // [private] start_ack_timer
5250 //*********************************************************************************
5252 void IOService::start_ack_timer ( void )
5254 start_ack_timer( ACK_TIMER_PERIOD
, kNanosecondScale
);
5257 void IOService::start_ack_timer ( UInt32 interval
, UInt32 scale
)
5259 AbsoluteTime deadline
;
5262 clock_interval_to_deadline(interval
, scale
, &deadline
);
5265 pending
= thread_call_enter_delayed(fAckTimer
, deadline
);
5266 if (pending
) release();
5269 //*********************************************************************************
5270 // [private] stop_ack_timer
5271 //*********************************************************************************
5273 void IOService::stop_ack_timer ( void )
5277 pending
= thread_call_cancel(fAckTimer
);
5278 if (pending
) release();
5281 //*********************************************************************************
5282 // [static] actionAckTimerExpired
5284 // Inside PM work loop's gate.
5285 //*********************************************************************************
5288 IOService::actionAckTimerExpired (
5290 void * arg0
, void * arg1
,
5291 void * arg2
, void * arg3
)
5293 IOService
* me
= (IOService
*) target
;
5296 // done will be true if the timer tick unblocks the machine state,
5297 // otherwise no need to signal the work loop.
5299 done
= me
->ackTimerTick();
5300 if (done
&& gIOPMWorkQueue
)
5301 gIOPMWorkQueue
->signalWorkAvailable();
5303 return kIOReturnSuccess
;
5306 //*********************************************************************************
5307 // ack_timer_expired
5309 // Thread call function. Holds a retain while the callout is in flight.
5310 //*********************************************************************************
5313 IOService::ack_timer_expired ( thread_call_param_t arg0
, thread_call_param_t arg1
)
5315 IOService
* me
= (IOService
*) arg0
;
5319 gIOPMWorkLoop
->runAction(&actionAckTimerExpired
, me
);
5325 // MARK: Client Messaging
5327 //*********************************************************************************
5328 // [private] tellSystemCapabilityChange
5329 //*********************************************************************************
5331 void IOService::tellSystemCapabilityChange( uint32_t nextMS
)
5334 fMachineState
= kIOPM_TellCapabilityChangeDone
;
5335 fOutOfBandMessage
= kIOMessageSystemCapabilityChange
;
5339 // Notify app first on pre-change.
5340 fOutOfBandParameter
= kNotifyCapabilityChangeApps
;
5344 // Notify kernel clients first on post-change.
5345 fOutOfBandParameter
= kNotifyCapabilityChangePriority
;
5348 tellClientsWithResponse( fOutOfBandMessage
);
5351 //*********************************************************************************
5352 // [public] askChangeDown
5354 // Ask registered applications and kernel clients if we can change to a lower
5357 // Subclass can override this to send a different message type. Parameter is
5358 // the destination state number.
5360 // Return true if we don't have to wait for acknowledgements
5361 //*********************************************************************************
5363 bool IOService::askChangeDown ( unsigned long stateNum
)
5365 return tellClientsWithResponse( kIOMessageCanDevicePowerOff
);
5368 //*********************************************************************************
5369 // [private] tellChangeDown1
5371 // Notify registered applications and kernel clients that we are definitely
5374 // Return true if we don't have to wait for acknowledgements
5375 //*********************************************************************************
5377 bool IOService::tellChangeDown1 ( unsigned long stateNum
)
5379 fOutOfBandParameter
= kNotifyApps
;
5380 return tellChangeDown(stateNum
);
5383 //*********************************************************************************
5384 // [private] tellChangeDown2
5386 // Notify priority clients that we are definitely dropping power.
5388 // Return true if we don't have to wait for acknowledgements
5389 //*********************************************************************************
5391 bool IOService::tellChangeDown2 ( unsigned long stateNum
)
5393 fOutOfBandParameter
= kNotifyPriority
;
5394 return tellChangeDown(stateNum
);
5397 //*********************************************************************************
5398 // [public] tellChangeDown
5400 // Notify registered applications and kernel clients that we are definitely
5403 // Subclass can override this to send a different message type. Parameter is
5404 // the destination state number.
5406 // Return true if we don't have to wait for acknowledgements
5407 //*********************************************************************************
5409 bool IOService::tellChangeDown ( unsigned long stateNum
)
5411 return tellClientsWithResponse( kIOMessageDeviceWillPowerOff
);
5414 //*********************************************************************************
5415 // cleanClientResponses
5417 //*********************************************************************************
5419 static void logAppTimeouts ( OSObject
* object
, void * arg
)
5421 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5423 unsigned int clientIndex
;
5425 if (OSDynamicCast(_IOServiceInterestNotifier
, object
))
5427 // Discover the 'counter' value or index assigned to this client
5428 // when it was notified, by searching for the array index of the
5429 // client in an array holding the cached interested clients.
5431 clientIndex
= context
->notifyClients
->getNextIndexOfObject(object
, 0);
5433 if ((clientIndex
!= (unsigned int) -1) &&
5434 (flag
= context
->responseArray
->getObject(clientIndex
)) &&
5435 (flag
!= kOSBooleanTrue
))
5437 OSString
*logClientID
= NULL
;
5438 OSNumber
*clientID
= copyClientIDForNotification(object
, context
);
5441 logClientID
= IOCopyLogNameForPID(clientID
->unsigned32BitValue());
5442 clientID
->release();
5445 PM_ERROR(context
->errorLog
, logClientID
? logClientID
->getCStringNoCopy() : "");
5447 // TODO: record message type if possible
5448 IOService::getPMRootDomain()->pmStatsRecordApplicationResponse(
5449 gIOPMStatsApplicationResponseTimedOut
,
5450 logClientID
? logClientID
->getCStringNoCopy() : "",
5454 logClientID
->release();
5459 void IOService::cleanClientResponses ( bool logErrors
)
5461 if (logErrors
&& fResponseArray
)
5463 switch ( fOutOfBandParameter
) {
5465 case kNotifyCapabilityChangeApps
:
5466 if (fNotifyClientArray
)
5468 IOPMInterestContext context
;
5470 context
.responseArray
= fResponseArray
;
5471 context
.notifyClients
= fNotifyClientArray
;
5472 context
.serialNumber
= fSerialNumber
;
5473 context
.messageType
= kIOMessageCopyClientID
;
5474 context
.notifyType
= kNotifyApps
;
5475 context
.isPreChange
= fIsPreChange
;
5476 context
.enableTracing
= false;
5478 context
.maxTimeRequested
= 0;
5479 context
.stateNumber
= fHeadNotePowerState
;
5480 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
5481 context
.changeFlags
= fHeadNoteChangeFlags
;
5482 context
.errorLog
= "PM notification timeout (%s)\n";
5484 applyToInterested(gIOAppPowerStateInterest
, logAppTimeouts
, (void *) &context
);
5489 // kNotifyPriority, kNotifyCapabilityChangePriority
5490 // TODO: identify the priority client that has not acked
5491 PM_ERROR("PM priority notification timeout\n");
5492 if (gIOKitDebug
& kIOLogDebugPower
)
5494 panic("PM priority notification timeout");
5502 fResponseArray
->release();
5503 fResponseArray
= NULL
;
5505 if (fNotifyClientArray
)
5507 fNotifyClientArray
->release();
5508 fNotifyClientArray
= NULL
;
5512 //*********************************************************************************
5513 // [protected] tellClientsWithResponse
5515 // Notify registered applications and kernel clients that we are definitely
5518 // Return true if we don't have to wait for acknowledgements
5519 //*********************************************************************************
5521 bool IOService::tellClientsWithResponse ( int messageType
)
5523 IOPMInterestContext context
;
5524 bool isRootDomain
= IS_ROOT_DOMAIN
;
5526 PM_ASSERT_IN_GATE();
5527 assert( fResponseArray
== NULL
);
5528 assert( fNotifyClientArray
== NULL
);
5530 RD_LOG("tellClientsWithResponse( %s, %d )\n",
5531 getIOMessageString(messageType
), fOutOfBandParameter
);
5533 fResponseArray
= OSArray::withCapacity( 1 );
5534 if (!fResponseArray
)
5537 fResponseArray
->setCapacityIncrement(8);
5538 if (++fSerialNumber
== 0)
5541 context
.responseArray
= fResponseArray
;
5542 context
.notifyClients
= 0;
5543 context
.serialNumber
= fSerialNumber
;
5544 context
.messageType
= messageType
;
5545 context
.notifyType
= fOutOfBandParameter
;
5546 context
.isPreChange
= fIsPreChange
;
5547 context
.enableTracing
= false;
5549 context
.maxTimeRequested
= 0;
5550 context
.stateNumber
= fHeadNotePowerState
;
5551 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
5552 context
.changeFlags
= fHeadNoteChangeFlags
;
5553 context
.messageFilter
= (isRootDomain
) ?
5554 OSMemberFunctionCast(
5557 &IOPMrootDomain::systemMessageFilter
) : 0;
5559 switch ( fOutOfBandParameter
) {
5561 applyToInterested( gIOAppPowerStateInterest
,
5562 pmTellAppWithResponse
, (void *) &context
);
5565 (fMachineState
!= kIOPM_OurChangeTellClientsPowerDown
) &&
5566 (fMachineState
!= kIOPM_SyncTellClientsPowerDown
))
5568 // Notify capability app for tellChangeDown1()
5569 // but not for askChangeDown().
5570 context
.notifyType
= kNotifyCapabilityChangeApps
;
5571 context
.messageType
= kIOMessageSystemCapabilityChange
;
5572 applyToInterested( gIOAppPowerStateInterest
,
5573 pmTellCapabilityAppWithResponse
, (void *) &context
);
5574 context
.notifyType
= fOutOfBandParameter
;
5575 context
.messageType
= messageType
;
5577 context
.maxTimeRequested
= k30Seconds
;
5579 applyToInterested( gIOGeneralInterest
,
5580 pmTellClientWithResponse
, (void *) &context
);
5582 fNotifyClientArray
= context
.notifyClients
;
5585 case kNotifyPriority
:
5586 context
.enableTracing
= isRootDomain
;
5587 applyToInterested( gIOPriorityPowerStateInterest
,
5588 pmTellClientWithResponse
, (void *) &context
);
5592 // Notify capability clients for tellChangeDown2().
5593 context
.notifyType
= kNotifyCapabilityChangePriority
;
5594 context
.messageType
= kIOMessageSystemCapabilityChange
;
5595 applyToInterested( gIOPriorityPowerStateInterest
,
5596 pmTellCapabilityClientWithResponse
, (void *) &context
);
5600 case kNotifyCapabilityChangeApps
:
5601 applyToInterested( gIOAppPowerStateInterest
,
5602 pmTellCapabilityAppWithResponse
, (void *) &context
);
5603 fNotifyClientArray
= context
.notifyClients
;
5604 context
.maxTimeRequested
= k30Seconds
;
5607 case kNotifyCapabilityChangePriority
:
5608 applyToInterested( gIOPriorityPowerStateInterest
,
5609 pmTellCapabilityClientWithResponse
, (void *) &context
);
5613 // do we have to wait for somebody?
5614 if ( !checkForDone() )
5616 OUR_PMLog(kPMLogStartAckTimer
, context
.maxTimeRequested
, 0);
5617 if (context
.enableTracing
)
5618 getPMRootDomain()->traceDetail( context
.maxTimeRequested
/ 1000 );
5619 start_ack_timer( context
.maxTimeRequested
/ 1000, kMillisecondScale
);
5624 // everybody responded
5627 fResponseArray
->release();
5628 fResponseArray
= NULL
;
5630 if (fNotifyClientArray
)
5632 fNotifyClientArray
->release();
5633 fNotifyClientArray
= NULL
;
5639 //*********************************************************************************
5640 // [static private] pmTellAppWithResponse
5642 // We send a message to an application, and we expect a response, so we compute a
5643 // cookie we can identify the response with.
5644 //*********************************************************************************
5646 void IOService::pmTellAppWithResponse ( OSObject
* object
, void * arg
)
5648 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5649 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
5650 uint32_t msgIndex
, msgRef
, msgType
;
5651 OSNumber
*clientID
= NULL
;
5653 boolean_t proc_suspended
= FALSE
;
5654 #if LOG_APP_RESPONSE_TIMES
5658 if (!OSDynamicCast(_IOServiceInterestNotifier
, object
))
5661 if (context
->us
== getPMRootDomain())
5663 if ((clientID
= copyClientIDForNotification(object
, context
)))
5665 uint32_t clientPID
= clientID
->unsigned32BitValue();
5666 clientID
->release();
5667 proc
= proc_find(clientPID
);
5671 proc_suspended
= get_task_pidsuspended((task_t
) proc
->task
);
5676 logClientIDForNotification(object
, context
, "PMTellAppWithResponse - Suspended");
5683 if (context
->messageFilter
&&
5684 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
5686 if (kIOLogDebugPower
& gIOKitDebug
)
5688 logClientIDForNotification(object
, context
, "DROP App");
5693 // Create client array (for tracking purposes) only if the service
5694 // has app clients. Usually only root domain does.
5695 if (0 == context
->notifyClients
)
5696 context
->notifyClients
= OSArray::withCapacity( 32 );
5698 msgType
= context
->messageType
;
5699 msgIndex
= context
->responseArray
->getCount();
5700 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
5702 OUR_PMLog(kPMLogAppNotify
, msgType
, msgRef
);
5703 if (kIOLogDebugPower
& gIOKitDebug
)
5705 logClientIDForNotification(object
, context
, "MESG App");
5708 #if LOG_APP_RESPONSE_TIMES
5710 clock_get_uptime(&now
);
5711 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&now
), sizeof(uint64_t) * 8);
5714 context
->responseArray
->setObject(msgIndex
, num
);
5719 context
->responseArray
->setObject(msgIndex
, kOSBooleanFalse
);
5721 if (context
->notifyClients
)
5722 context
->notifyClients
->setObject(msgIndex
, object
);
5724 context
->us
->messageClient(msgType
, object
, (void *) msgRef
);
5727 //*********************************************************************************
5728 // [static private] pmTellClientWithResponse
5730 // We send a message to an in-kernel client, and we expect a response,
5731 // so we compute a cookie we can identify the response with.
5732 //*********************************************************************************
5734 void IOService::pmTellClientWithResponse ( OSObject
* object
, void * arg
)
5736 IOPowerStateChangeNotification notify
;
5737 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5738 OSObject
* replied
= kOSBooleanTrue
;
5739 _IOServiceInterestNotifier
* notifier
;
5740 uint32_t msgIndex
, msgRef
, msgType
;
5743 if (context
->messageFilter
&&
5744 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
5746 if ((kIOLogDebugPower
& gIOKitDebug
) &&
5747 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
5749 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
5750 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
5751 context
->us
->getName(),
5752 getIOMessageString(context
->messageType
),
5753 object
, n
->handler
);
5758 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
5759 msgType
= context
->messageType
;
5760 msgIndex
= context
->responseArray
->getCount();
5761 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
5763 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
5764 if (gIOKitDebug
& kIOLogPower
) {
5765 OUR_PMLog(kPMLogClientNotify
, msgRef
, msgType
);
5766 if (OSDynamicCast(IOService
, object
)) {
5767 const char *who
= ((IOService
*) object
)->getName();
5768 gPlatform
->PMLog(who
, kPMLogClientNotify
, (uintptr_t) object
, 0);
5770 else if (notifier
) {
5771 OUR_PMLog(kPMLogClientNotify
, (uintptr_t) notifier
->handler
, 0);
5774 if ((kIOLogDebugPower
& gIOKitDebug
) && notifier
)
5776 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
5777 context
->us
->getName(),
5778 getIOMessageString(msgType
),
5779 object
, notifier
->handler
);
5782 notify
.powerRef
= (void *)(uintptr_t) msgRef
;
5783 notify
.returnValue
= 0;
5784 notify
.stateNumber
= context
->stateNumber
;
5785 notify
.stateFlags
= context
->stateFlags
;
5787 if (context
->enableTracing
&& (notifier
!= 0))
5789 uint32_t detail
= ((msgIndex
& 0xff) << 24) |
5790 ((msgType
& 0xfff) << 12) |
5791 (((uintptr_t) notifier
->handler
) & 0xfff);
5792 getPMRootDomain()->traceDetail( detail
);
5795 retCode
= context
->us
->messageClient(msgType
, object
, (void *) ¬ify
, sizeof(notify
));
5797 if (kIOReturnSuccess
== retCode
)
5799 if (0 == notify
.returnValue
) {
5800 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, (uintptr_t) object
);
5802 replied
= kOSBooleanFalse
;
5803 if ( notify
.returnValue
> context
->maxTimeRequested
)
5805 if (notify
.returnValue
> kPriorityClientMaxWait
)
5807 context
->maxTimeRequested
= kPriorityClientMaxWait
;
5808 PM_ERROR("%s: client %p returned %llu for %s\n",
5809 context
->us
->getName(),
5810 notifier
? (void *) notifier
->handler
: object
,
5811 (uint64_t) notify
.returnValue
,
5812 getIOMessageString(msgType
));
5815 context
->maxTimeRequested
= notify
.returnValue
;
5819 // not a client of ours
5820 // so we won't be waiting for response
5821 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, 0);
5824 context
->responseArray
->setObject(msgIndex
, replied
);
5827 //*********************************************************************************
5828 // [static private] pmTellCapabilityAppWithResponse
5829 //*********************************************************************************
5831 void IOService::pmTellCapabilityAppWithResponse ( OSObject
* object
, void * arg
)
5833 IOPMSystemCapabilityChangeParameters msgArg
;
5834 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5835 OSObject
* replied
= kOSBooleanTrue
;
5836 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
5837 uint32_t msgIndex
, msgRef
, msgType
;
5838 #if LOG_APP_RESPONSE_TIMES
5842 if (!OSDynamicCast(_IOServiceInterestNotifier
, object
))
5845 memset(&msgArg
, 0, sizeof(msgArg
));
5846 if (context
->messageFilter
&&
5847 !context
->messageFilter(context
->us
, object
, context
, &msgArg
, &replied
))
5852 // Create client array (for tracking purposes) only if the service
5853 // has app clients. Usually only root domain does.
5854 if (0 == context
->notifyClients
)
5855 context
->notifyClients
= OSArray::withCapacity( 32 );
5857 msgType
= context
->messageType
;
5858 msgIndex
= context
->responseArray
->getCount();
5859 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
5861 OUR_PMLog(kPMLogAppNotify
, msgType
, msgRef
);
5862 if (kIOLogDebugPower
& gIOKitDebug
)
5864 // Log client pid/name and client array index.
5865 OSNumber
* clientID
= NULL
;
5866 OSString
* clientIDString
= NULL
;;
5867 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
5869 clientIDString
= IOCopyLogNameForPID(clientID
->unsigned32BitValue());
5872 PM_LOG("%s MESG App(%u) %s, wait %u, %s\n",
5873 context
->us
->getName(),
5874 msgIndex
, getIOMessageString(msgType
),
5875 (replied
!= kOSBooleanTrue
),
5876 clientIDString
? clientIDString
->getCStringNoCopy() : "");
5877 if (clientID
) clientID
->release();
5878 if (clientIDString
) clientIDString
->release();
5881 msgArg
.notifyRef
= msgRef
;
5882 msgArg
.maxWaitForReply
= 0;
5884 if (replied
== kOSBooleanTrue
)
5886 msgArg
.notifyRef
= 0;
5887 context
->responseArray
->setObject(msgIndex
, kOSBooleanTrue
);
5888 if (context
->notifyClients
)
5889 context
->notifyClients
->setObject(msgIndex
, kOSBooleanTrue
);
5893 #if LOG_APP_RESPONSE_TIMES
5895 clock_get_uptime(&now
);
5896 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&now
), sizeof(uint64_t) * 8);
5899 context
->responseArray
->setObject(msgIndex
, num
);
5904 context
->responseArray
->setObject(msgIndex
, kOSBooleanFalse
);
5906 if (context
->notifyClients
)
5907 context
->notifyClients
->setObject(msgIndex
, object
);
5910 context
->us
->messageClient(msgType
, object
, (void *) &msgArg
, sizeof(msgArg
));
5913 //*********************************************************************************
5914 // [static private] pmTellCapabilityClientWithResponse
5915 //*********************************************************************************
5917 void IOService::pmTellCapabilityClientWithResponse(
5918 OSObject
* object
, void * arg
)
5920 IOPMSystemCapabilityChangeParameters msgArg
;
5921 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5922 OSObject
* replied
= kOSBooleanTrue
;
5923 _IOServiceInterestNotifier
* notifier
;
5924 uint32_t msgIndex
, msgRef
, msgType
;
5927 memset(&msgArg
, 0, sizeof(msgArg
));
5928 if (context
->messageFilter
&&
5929 !context
->messageFilter(context
->us
, object
, context
, &msgArg
, 0))
5931 if ((kIOLogDebugPower
& gIOKitDebug
) &&
5932 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
5934 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
5935 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
5936 context
->us
->getName(),
5937 getIOMessageString(context
->messageType
),
5938 object
, n
->handler
);
5943 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
5944 msgType
= context
->messageType
;
5945 msgIndex
= context
->responseArray
->getCount();
5946 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
5948 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
5949 if (gIOKitDebug
& kIOLogPower
) {
5950 OUR_PMLog(kPMLogClientNotify
, msgRef
, msgType
);
5951 if (OSDynamicCast(IOService
, object
)) {
5952 const char *who
= ((IOService
*) object
)->getName();
5953 gPlatform
->PMLog(who
, kPMLogClientNotify
, (uintptr_t) object
, 0);
5955 else if (notifier
) {
5956 OUR_PMLog(kPMLogClientNotify
, (uintptr_t) notifier
->handler
, 0);
5959 if ((kIOLogDebugPower
& gIOKitDebug
) && notifier
)
5961 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
5962 context
->us
->getName(),
5963 getIOMessageString(msgType
),
5964 object
, notifier
->handler
);
5967 msgArg
.notifyRef
= msgRef
;
5968 msgArg
.maxWaitForReply
= 0;
5970 if (context
->enableTracing
&& (notifier
!= 0))
5972 uint32_t detail
= ((msgIndex
& 0xff) << 24) |
5973 ((msgType
& 0xfff) << 12) |
5974 (((uintptr_t) notifier
->handler
) & 0xfff);
5975 getPMRootDomain()->traceDetail( detail
);
5978 retCode
= context
->us
->messageClient(
5979 msgType
, object
, (void *) &msgArg
, sizeof(msgArg
));
5981 if ( kIOReturnSuccess
== retCode
)
5983 if ( 0 == msgArg
.maxWaitForReply
)
5985 // client doesn't want time to respond
5986 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, (uintptr_t) object
);
5990 replied
= kOSBooleanFalse
;
5991 if ( msgArg
.maxWaitForReply
> context
->maxTimeRequested
)
5993 if (msgArg
.maxWaitForReply
> kCapabilityClientMaxWait
)
5995 context
->maxTimeRequested
= kCapabilityClientMaxWait
;
5996 PM_ERROR("%s: client %p returned %u for %s\n",
5997 context
->us
->getName(),
5998 notifier
? (void *) notifier
->handler
: object
,
5999 msgArg
.maxWaitForReply
,
6000 getIOMessageString(msgType
));
6003 context
->maxTimeRequested
= msgArg
.maxWaitForReply
;
6009 // not a client of ours
6010 // so we won't be waiting for response
6011 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, 0);
6014 context
->responseArray
->setObject(msgIndex
, replied
);
6017 //*********************************************************************************
6018 // [public] tellNoChangeDown
6020 // Notify registered applications and kernel clients that we are not
6023 // Subclass can override this to send a different message type. Parameter is
6024 // the aborted destination state number.
6025 //*********************************************************************************
6027 void IOService::tellNoChangeDown ( unsigned long )
6029 return tellClients( kIOMessageDeviceWillNotPowerOff
);
6032 //*********************************************************************************
6033 // [public] tellChangeUp
6035 // Notify registered applications and kernel clients that we are raising power.
6037 // Subclass can override this to send a different message type. Parameter is
6038 // the aborted destination state number.
6039 //*********************************************************************************
6041 void IOService::tellChangeUp ( unsigned long )
6043 return tellClients( kIOMessageDeviceHasPoweredOn
);
6046 //*********************************************************************************
6047 // [protected] tellClients
6049 // Notify registered applications and kernel clients of something.
6050 //*********************************************************************************
6052 void IOService::tellClients ( int messageType
)
6054 IOPMInterestContext context
;
6056 RD_LOG("tellClients( %s )\n", getIOMessageString(messageType
));
6058 memset(&context
, 0, sizeof(context
));
6059 context
.messageType
= messageType
;
6060 context
.isPreChange
= fIsPreChange
;
6062 context
.stateNumber
= fHeadNotePowerState
;
6063 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
6064 context
.changeFlags
= fHeadNoteChangeFlags
;
6065 context
.messageFilter
= (IS_ROOT_DOMAIN
) ?
6066 OSMemberFunctionCast(
6069 &IOPMrootDomain::systemMessageFilter
) : 0;
6071 context
.notifyType
= kNotifyPriority
;
6072 applyToInterested( gIOPriorityPowerStateInterest
,
6073 tellKernelClientApplier
, (void *) &context
);
6075 context
.notifyType
= kNotifyApps
;
6076 applyToInterested( gIOAppPowerStateInterest
,
6077 tellAppClientApplier
, (void *) &context
);
6079 applyToInterested( gIOGeneralInterest
,
6080 tellKernelClientApplier
, (void *) &context
);
6083 //*********************************************************************************
6084 // [private] tellKernelClientApplier
6086 // Message a kernel client.
6087 //*********************************************************************************
6089 static void tellKernelClientApplier ( OSObject
* object
, void * arg
)
6091 IOPowerStateChangeNotification notify
;
6092 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6094 if (context
->messageFilter
&&
6095 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
6097 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6098 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
6100 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6101 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
6102 context
->us
->getName(),
6103 IOService::getIOMessageString(context
->messageType
),
6104 object
, n
->handler
);
6109 notify
.powerRef
= (void *) 0;
6110 notify
.returnValue
= 0;
6111 notify
.stateNumber
= context
->stateNumber
;
6112 notify
.stateFlags
= context
->stateFlags
;
6114 context
->us
->messageClient(context
->messageType
, object
, ¬ify
, sizeof(notify
));
6116 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6117 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
6119 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6120 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
6121 context
->us
->getName(),
6122 IOService::getIOMessageString(context
->messageType
),
6123 object
, n
->handler
);
6127 static OSNumber
* copyClientIDForNotification(
6129 IOPMInterestContext
*context
)
6131 OSNumber
*clientID
= NULL
;
6132 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
6136 static void logClientIDForNotification(
6138 IOPMInterestContext
*context
,
6139 const char *logString
)
6141 OSString
*logClientID
= NULL
;
6142 OSNumber
*clientID
= copyClientIDForNotification(object
, context
);
6147 logClientID
= IOCopyLogNameForPID(clientID
->unsigned32BitValue());
6149 PM_LOG("%s %s %s, %s\n",
6150 context
->us
->getName(), logString
,
6151 IOService::getIOMessageString(context
->messageType
),
6152 logClientID
? logClientID
->getCStringNoCopy() : "");
6155 logClientID
->release();
6159 clientID
->release();
6165 static void tellAppClientApplier ( OSObject
* object
, void * arg
)
6167 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6168 OSNumber
* clientID
= NULL
;
6170 boolean_t proc_suspended
= FALSE
;
6172 if (context
->us
== IOService::getPMRootDomain())
6174 if ((clientID
= copyClientIDForNotification(object
, context
)))
6176 uint32_t clientPID
= clientID
->unsigned32BitValue();
6177 clientID
->release();
6178 proc
= proc_find(clientPID
);
6182 proc_suspended
= get_task_pidsuspended((task_t
) proc
->task
);
6187 logClientIDForNotification(object
, context
, "tellAppClientApplier - Suspended");
6194 if (context
->messageFilter
&&
6195 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
6197 if (kIOLogDebugPower
& gIOKitDebug
)
6199 logClientIDForNotification(object
, context
, "DROP App");
6204 if (kIOLogDebugPower
& gIOKitDebug
)
6206 logClientIDForNotification(object
, context
, "MESG App");
6209 context
->us
->messageClient(context
->messageType
, object
, 0);
6212 //*********************************************************************************
6213 // [private] checkForDone
6214 //*********************************************************************************
6216 bool IOService::checkForDone ( void )
6221 if (fResponseArray
== NULL
) {
6225 for (i
= 0; ; i
++) {
6226 theFlag
= fResponseArray
->getObject(i
);
6228 if (NULL
== theFlag
) {
6232 if (kOSBooleanTrue
!= theFlag
) {
6239 //*********************************************************************************
6240 // [public] responseValid
6241 //*********************************************************************************
6243 bool IOService::responseValid ( uint32_t refcon
, int pid
)
6245 UInt16 serialComponent
;
6246 UInt16 ordinalComponent
;
6249 serialComponent
= (refcon
>> 16) & 0xFFFF;
6250 ordinalComponent
= (refcon
& 0xFFFF);
6252 if ( serialComponent
!= fSerialNumber
)
6257 if ( fResponseArray
== NULL
)
6262 theFlag
= fResponseArray
->getObject(ordinalComponent
);
6270 if ((num
= OSDynamicCast(OSNumber
, theFlag
)))
6272 #if LOG_APP_RESPONSE_TIMES
6276 OSString
*name
= IOCopyLogNameForPID(pid
);
6278 clock_get_uptime(&now
);
6279 AbsoluteTime_to_scalar(&start
) = num
->unsigned64BitValue();
6280 SUB_ABSOLUTETIME(&now
, &start
);
6281 absolutetime_to_nanoseconds(now
, &nsec
);
6283 PMEventDetails
*details
= PMEventDetails::eventDetails(
6284 kIOPMEventTypeAppResponse
, // type
6285 name
? name
->getCStringNoCopy() : "", // who
6286 (uintptr_t)pid
, // owner unique
6287 NULL
, // interest name
6291 NS_TO_US(nsec
)); // usec completion time
6293 getPMRootDomain()->recordAndReleasePMEventGated( details
);
6295 if (kIOLogDebugPower
& gIOKitDebug
)
6297 PM_LOG("Ack(%u) %u ms\n",
6298 (uint32_t) ordinalComponent
,
6303 if (nsec
> LOG_APP_RESPONSE_TIMES
)
6305 PM_LOG("PM response took %d ms (%s)\n", NS_TO_MS(nsec
),
6306 name
? name
->getCStringNoCopy() : "");
6308 if (nsec
> LOG_APP_RESPONSE_MSG_TRACER
)
6310 // TODO: populate the messageType argument
6311 getPMRootDomain()->pmStatsRecordApplicationResponse(
6312 gIOPMStatsApplicationResponseSlow
,
6313 name
? name
->getCStringNoCopy() : "", 0,
6314 NS_TO_MS(nsec
), pid
);
6321 theFlag
= kOSBooleanFalse
;
6324 if ( kOSBooleanFalse
== theFlag
)
6326 fResponseArray
->replaceObject(ordinalComponent
, kOSBooleanTrue
);
6332 //*********************************************************************************
6333 // [public] allowPowerChange
6335 // Our power state is about to lower, and we have notified applications
6336 // and kernel clients, and one of them has acknowledged. If this is the last to do
6337 // so, and all acknowledgements are positive, we continue with the power change.
6338 //*********************************************************************************
6340 IOReturn
IOService::allowPowerChange ( unsigned long refcon
)
6342 IOPMRequest
* request
;
6347 return kIOReturnSuccess
;
6350 request
= acquirePMRequest( this, kIOPMRequestTypeAllowPowerChange
);
6352 return kIOReturnNoMemory
;
6354 request
->fArg0
= (void *) refcon
;
6355 request
->fArg1
= (void *) proc_selfpid();
6356 request
->fArg2
= (void *) 0;
6357 submitPMRequest( request
);
6359 return kIOReturnSuccess
;
6363 IOReturn
IOService::serializedAllowPowerChange2 ( unsigned long refcon
)
6365 // [deprecated] public
6366 return kIOReturnUnsupported
;
6368 #endif /* !__LP64__ */
6370 //*********************************************************************************
6371 // [public] cancelPowerChange
6373 // Our power state is about to lower, and we have notified applications
6374 // and kernel clients, and one of them has vetoed the change. If this is the last
6375 // client to respond, we abandon the power change.
6376 //*********************************************************************************
6378 IOReturn
IOService::cancelPowerChange ( unsigned long refcon
)
6380 IOPMRequest
* request
;
6386 return kIOReturnSuccess
;
6389 name
= IOCopyLogNameForPID(proc_selfpid());
6390 PM_ERROR("PM notification cancel (%s)\n", name
? name
->getCStringNoCopy() : "");
6392 request
= acquirePMRequest( this, kIOPMRequestTypeCancelPowerChange
);
6397 return kIOReturnNoMemory
;
6400 request
->fArg0
= (void *) refcon
;
6401 request
->fArg1
= (void *) proc_selfpid();
6402 request
->fArg2
= (void *) name
;
6403 submitPMRequest( request
);
6405 return kIOReturnSuccess
;
6409 IOReturn
IOService::serializedCancelPowerChange2 ( unsigned long refcon
)
6411 // [deprecated] public
6412 return kIOReturnUnsupported
;
6415 //*********************************************************************************
6416 // PM_Clamp_Timer_Expired
6418 // called when clamp timer expires...set power state to 0.
6419 //*********************************************************************************
6421 void IOService::PM_Clamp_Timer_Expired ( void )
6425 //*********************************************************************************
6428 // Set to highest available power state for a minimum of duration milliseconds
6429 //*********************************************************************************
6431 void IOService::clampPowerOn ( unsigned long duration
)
6434 #endif /* !__LP64__ */
6437 // MARK: Driver Overrides
6439 //*********************************************************************************
6440 // [public] setPowerState
6442 // Does nothing here. This should be implemented in a subclass driver.
6443 //*********************************************************************************
6445 IOReturn
IOService::setPowerState (
6446 unsigned long powerStateOrdinal
, IOService
* whatDevice
)
6451 //*********************************************************************************
6452 // [public] maxCapabilityForDomainState
6454 // Finds the highest power state in the array whose input power
6455 // requirement is equal to the input parameter. Where a more intelligent
6456 // decision is possible, override this in the subclassed driver.
6457 //*********************************************************************************
6459 unsigned long IOService::maxCapabilityForDomainState ( IOPMPowerFlags domainState
)
6463 if (fNumberOfPowerStates
== 0 )
6467 for ( i
= fNumberOfPowerStates
- 1; i
>= 0; i
-- )
6469 if ( (domainState
& fPowerStates
[i
].inputPowerFlags
) ==
6470 fPowerStates
[i
].inputPowerFlags
)
6478 //*********************************************************************************
6479 // [public] initialPowerStateForDomainState
6481 // Finds the highest power state in the array whose input power
6482 // requirement is equal to the input parameter. Where a more intelligent
6483 // decision is possible, override this in the subclassed driver.
6484 //*********************************************************************************
6486 unsigned long IOService::initialPowerStateForDomainState ( IOPMPowerFlags domainState
)
6490 if (fResetPowerStateOnWake
&& (domainState
& kIOPMRootDomainState
))
6492 // Return lowest power state for any root power domain changes
6496 if (fNumberOfPowerStates
== 0 )
6500 for ( i
= fNumberOfPowerStates
- 1; i
>= 0; i
-- )
6502 if ( (domainState
& fPowerStates
[i
].inputPowerFlags
) ==
6503 fPowerStates
[i
].inputPowerFlags
)
6511 //*********************************************************************************
6512 // [public] powerStateForDomainState
6514 // Finds the highest power state in the array whose input power
6515 // requirement is equal to the input parameter. Where a more intelligent
6516 // decision is possible, override this in the subclassed driver.
6517 //*********************************************************************************
6519 unsigned long IOService::powerStateForDomainState ( IOPMPowerFlags domainState
)
6523 if (fNumberOfPowerStates
== 0 )
6527 for ( i
= fNumberOfPowerStates
- 1; i
>= 0; i
-- )
6529 if ( (domainState
& fPowerStates
[i
].inputPowerFlags
) ==
6530 fPowerStates
[i
].inputPowerFlags
)
6539 //*********************************************************************************
6540 // [deprecated] didYouWakeSystem
6542 // Does nothing here. This should be implemented in a subclass driver.
6543 //*********************************************************************************
6545 bool IOService::didYouWakeSystem ( void )
6549 #endif /* !__LP64__ */
6551 //*********************************************************************************
6552 // [public] powerStateWillChangeTo
6554 // Does nothing here. This should be implemented in a subclass driver.
6555 //*********************************************************************************
6557 IOReturn
IOService::powerStateWillChangeTo ( IOPMPowerFlags
, unsigned long, IOService
* )
6559 return kIOPMAckImplied
;
6562 //*********************************************************************************
6563 // [public] powerStateDidChangeTo
6565 // Does nothing here. This should be implemented in a subclass driver.
6566 //*********************************************************************************
6568 IOReturn
IOService::powerStateDidChangeTo ( IOPMPowerFlags
, unsigned long, IOService
* )
6570 return kIOPMAckImplied
;
6573 //*********************************************************************************
6574 // [protected] powerChangeDone
6576 // Called from PM work loop thread.
6577 // Does nothing here. This should be implemented in a subclass policy-maker.
6578 //*********************************************************************************
6580 void IOService::powerChangeDone ( unsigned long )
6585 //*********************************************************************************
6586 // [deprecated] newTemperature
6588 // Does nothing here. This should be implemented in a subclass driver.
6589 //*********************************************************************************
6591 IOReturn
IOService::newTemperature ( long currentTemp
, IOService
* whichZone
)
6595 #endif /* !__LP64__ */
6597 //*********************************************************************************
6598 // [public] systemWillShutdown
6600 // System shutdown and restart notification.
6601 //*********************************************************************************
6603 void IOService::systemWillShutdown( IOOptionBits specifier
)
6605 IOPMrootDomain
* rootDomain
= IOService::getPMRootDomain();
6607 rootDomain
->acknowledgeSystemWillShutdown( this );
6611 // MARK: PM State Machine
6613 //*********************************************************************************
6614 // [private static] acquirePMRequest
6615 //*********************************************************************************
6618 IOService::acquirePMRequest( IOService
* target
, IOOptionBits requestType
,
6619 IOPMRequest
* active
)
6621 IOPMRequest
* request
;
6625 request
= IOPMRequest::create();
6628 request
->init( target
, requestType
);
6631 IOPMRequest
* root
= active
->getRootRequest();
6632 if (root
) request
->attachRootRequest(root
);
6637 PM_ERROR("%s: No memory for PM request type 0x%x\n",
6638 target
->getName(), (uint32_t) requestType
);
6643 //*********************************************************************************
6644 // [private static] releasePMRequest
6645 //*********************************************************************************
6647 void IOService::releasePMRequest( IOPMRequest
* request
)
6656 //*********************************************************************************
6657 // [private] submitPMRequest
6658 //*********************************************************************************
6660 void IOService::submitPMRequest( IOPMRequest
* request
)
6663 assert( gIOPMReplyQueue
);
6664 assert( gIOPMRequestQueue
);
6666 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
6667 (long)request
->getType(), request
,
6668 request
->getTarget(), request
->getTarget()->getName(),
6669 request
->fArg0
, request
->fArg1
, request
->fArg2
);
6671 if (request
->isReplyType())
6672 gIOPMReplyQueue
->queuePMRequest( request
);
6674 gIOPMRequestQueue
->queuePMRequest( request
);
6677 void IOService::submitPMRequest( IOPMRequest
** requests
, IOItemCount count
)
6680 assert( count
> 0 );
6681 assert( gIOPMRequestQueue
);
6683 for (IOItemCount i
= 0; i
< count
; i
++)
6685 IOPMRequest
* req
= requests
[i
];
6686 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
6687 (long)req
->getType(), req
,
6688 req
->getTarget(), req
->getTarget()->getName(),
6689 req
->fArg0
, req
->fArg1
, req
->fArg2
);
6692 gIOPMRequestQueue
->queuePMRequestChain( requests
, count
);
6695 //*********************************************************************************
6696 // [private] servicePMRequestQueue
6698 // Called from IOPMRequestQueue::checkForWork().
6699 //*********************************************************************************
6701 bool IOService::servicePMRequestQueue(
6702 IOPMRequest
* request
,
6703 IOPMRequestQueue
* queue
)
6709 // Work queue will immediately execute the queue'd request if possible.
6710 // If execution blocks, the work queue will wait for a producer signal.
6711 // Only need to signal more when completing attached requests.
6713 more
= gIOPMWorkQueue
->queuePMRequest(request
, pwrMgt
);
6717 // Calling PM without PMinit() is not allowed, fail the request.
6719 PM_LOG("%s: PM not initialized\n", getName());
6720 fAdjustPowerScheduled
= false;
6721 more
= gIOPMFreeQueue
->queuePMRequest(request
);
6722 if (more
) gIOPMWorkQueue
->incrementProducerCount();
6726 //*********************************************************************************
6727 // [private] servicePMFreeQueue
6729 // Called from IOPMCompletionQueue::checkForWork().
6730 //*********************************************************************************
6732 bool IOService::servicePMFreeQueue(
6733 IOPMRequest
* request
,
6734 IOPMCompletionQueue
* queue
)
6736 bool more
= request
->getNextRequest();
6737 IOPMRequest
* root
= request
->getRootRequest();
6739 if (root
&& (root
!= request
))
6742 gIOPMWorkQueue
->incrementProducerCount();
6744 releasePMRequest( request
);
6748 //*********************************************************************************
6749 // [private] retirePMRequest
6751 // Called by IOPMWorkQueue to retire a completed request.
6752 //*********************************************************************************
6754 bool IOService::retirePMRequest( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
6756 assert(request
&& queue
);
6758 PM_LOG1("[- %02x] %p [%p %s] state %d, busy %d\n",
6759 request
->getType(), request
, this, getName(),
6760 fMachineState
, gIOPMBusyCount
);
6762 // Catch requests created by idleTimerExpired().
6764 if ((request
->getType() == kIOPMRequestTypeActivityTickle
) &&
6765 (((uintptr_t) request
->fArg1
) & kTickleTypePowerDrop
) &&
6771 // If the request is linked, then Work queue has already incremented its
6774 return (gIOPMFreeQueue
->queuePMRequest( request
));
6777 //*********************************************************************************
6778 // [private] isPMBlocked
6780 // Check if machine state transition is blocked.
6781 //*********************************************************************************
6783 bool IOService::isPMBlocked ( IOPMRequest
* request
, int count
)
6788 if (kIOPM_Finished
== fMachineState
)
6791 if (kIOPM_DriverThreadCallDone
== fMachineState
)
6793 // 5 = kDriverCallInformPreChange
6794 // 6 = kDriverCallInformPostChange
6795 // 7 = kDriverCallSetPowerState
6796 if (fDriverCallBusy
)
6797 reason
= 5 + fDriverCallReason
;
6801 // Waiting on driver's setPowerState() timeout.
6807 // Child or interested driver acks pending.
6808 if (fHeadNotePendingAcks
)
6813 // Waiting on apps or priority power interest clients.
6819 // Waiting on settle timer expiration.
6826 fWaitReason
= reason
;
6832 PM_LOG1("[B %02x] %p [%p %s] state %d, reason %d\n",
6833 request
->getType(), request
, this, getName(),
6834 fMachineState
, reason
);
6843 //*********************************************************************************
6844 // [private] servicePMRequest
6846 // Service a request from our work queue.
6847 //*********************************************************************************
6849 bool IOService::servicePMRequest( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
6854 assert(request
&& queue
);
6856 while (isPMBlocked(request
, loop
++) == false)
6858 PM_LOG1("[W %02x] %p [%p %s] state %d\n",
6859 request
->getType(), request
, this, getName(), fMachineState
);
6861 gIOPMRequest
= request
;
6864 // Every PM machine states must be handled in one of the cases below.
6866 switch ( fMachineState
)
6868 case kIOPM_Finished
:
6869 executePMRequest( request
);
6872 case kIOPM_OurChangeTellClientsPowerDown
:
6873 // Root domain might self cancel due to assertions.
6876 bool cancel
= (bool) fDoNotPowerDown
;
6877 getPMRootDomain()->askChangeDownDone(
6878 &fHeadNoteChangeFlags
, &cancel
);
6879 fDoNotPowerDown
= cancel
;
6882 // askChangeDown() done, was it vetoed?
6883 if (!fDoNotPowerDown
)
6885 if (IS_ROOT_DOMAIN
) {
6886 PMEventDetails
*details
= PMEventDetails::eventDetails(
6887 kIOPMEventTypeAppNotificationsFinished
,
6892 getPMRootDomain()->recordAndReleasePMEventGated( details
);
6895 // no, we can continue
6896 OurChangeTellClientsPowerDown();
6900 if (IS_ROOT_DOMAIN
) {
6901 PMEventDetails
*details
= PMEventDetails::eventDetails(
6902 kIOPMEventTypeSleepDone
,
6904 1, /* reason: 1 == Ask clients succeeded */
6905 kIOReturnAborted
); /* result */
6907 getPMRootDomain()->recordAndReleasePMEventGated( details
);
6910 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
6911 PM_ERROR("%s: idle cancel\n", fName
);
6912 // yes, rescind the warning
6913 tellNoChangeDown(fHeadNotePowerState
);
6914 // mark the change note un-actioned
6915 fHeadNoteChangeFlags
|= kIOPMNotDone
;
6921 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
6922 // tellChangeDown(kNotifyApps) done, was it cancelled?
6923 if (fDoNotPowerDown
)
6925 if (IS_ROOT_DOMAIN
) {
6926 PMEventDetails
*details
= PMEventDetails::eventDetails(
6927 kIOPMEventTypeSleepDone
,
6929 2, /* reason: 2 == Client cancelled wake */
6930 kIOReturnAborted
); /* result */
6932 getPMRootDomain()->recordAndReleasePMEventGated( details
);
6934 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
6935 PM_ERROR("%s: idle revert\n", fName
);
6936 // no, tell clients we're back in the old state
6937 tellChangeUp(fCurrentPowerState
);
6938 // mark the change note un-actioned
6939 fHeadNoteChangeFlags
|= kIOPMNotDone
;
6945 if (IS_ROOT_DOMAIN
) {
6946 PMEventDetails
*details
= PMEventDetails::eventDetails(
6947 kIOPMEventTypeAppNotificationsFinished
,
6949 2, /* reason: 2 == TellPriorityClientsDone */
6950 kIOReturnSuccess
); /* result */
6952 getPMRootDomain()->recordAndReleasePMEventGated( details
);
6954 // yes, we can continue
6955 OurChangeTellPriorityClientsPowerDown();
6959 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
6960 OurChangeNotifyInterestedDriversWillChange();
6963 case kIOPM_OurChangeSetPowerState
:
6964 OurChangeSetPowerState();
6967 case kIOPM_OurChangeWaitForPowerSettle
:
6968 OurChangeWaitForPowerSettle();
6971 case kIOPM_OurChangeNotifyInterestedDriversDidChange
:
6972 OurChangeNotifyInterestedDriversDidChange();
6975 case kIOPM_OurChangeTellCapabilityDidChange
:
6976 OurChangeTellCapabilityDidChange();
6979 case kIOPM_OurChangeFinish
:
6983 case kIOPM_ParentChangeTellPriorityClientsPowerDown
:
6984 ParentChangeTellPriorityClientsPowerDown();
6987 case kIOPM_ParentChangeNotifyInterestedDriversWillChange
:
6988 ParentChangeNotifyInterestedDriversWillChange();
6991 case kIOPM_ParentChangeSetPowerState
:
6992 ParentChangeSetPowerState();
6995 case kIOPM_ParentChangeWaitForPowerSettle
:
6996 ParentChangeWaitForPowerSettle();
6999 case kIOPM_ParentChangeNotifyInterestedDriversDidChange
:
7000 ParentChangeNotifyInterestedDriversDidChange();
7003 case kIOPM_ParentChangeTellCapabilityDidChange
:
7004 ParentChangeTellCapabilityDidChange();
7007 case kIOPM_ParentChangeAcknowledgePowerChange
:
7008 ParentChangeAcknowledgePowerChange();
7011 case kIOPM_DriverThreadCallDone
:
7012 if (fDriverCallReason
== kDriverCallSetPowerState
)
7013 notifyControllingDriverDone();
7015 notifyInterestedDriversDone();
7018 case kIOPM_NotifyChildrenOrdered
:
7019 notifyChildrenOrdered();
7022 case kIOPM_NotifyChildrenDelayed
:
7023 notifyChildrenDelayed();
7026 case kIOPM_NotifyChildrenStart
:
7027 PM_LOG2("%s: kIOPM_NotifyChildrenStart done\n", getName());
7028 MS_POP(); // from notifyInterestedDriversDone()
7032 case kIOPM_SyncTellClientsPowerDown
:
7033 // Root domain might self cancel due to assertions.
7036 bool cancel
= (bool) fDoNotPowerDown
;
7037 getPMRootDomain()->askChangeDownDone(
7038 &fHeadNoteChangeFlags
, &cancel
);
7039 fDoNotPowerDown
= cancel
;
7041 if (!fDoNotPowerDown
)
7043 fMachineState
= kIOPM_SyncTellPriorityClientsPowerDown
;
7044 fOutOfBandParameter
= kNotifyApps
;
7045 tellChangeDown(fHeadNotePowerState
);
7049 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7050 PM_ERROR("%s: idle cancel\n", fName
);
7051 tellNoChangeDown(fHeadNotePowerState
);
7052 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7057 case kIOPM_SyncTellPriorityClientsPowerDown
:
7058 if (!fDoNotPowerDown
)
7060 fMachineState
= kIOPM_SyncNotifyWillChange
;
7061 fOutOfBandParameter
= kNotifyPriority
;
7062 tellChangeDown(fHeadNotePowerState
);
7066 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7067 PM_ERROR("%s: idle revert\n", fName
);
7068 tellChangeUp(fCurrentPowerState
);
7069 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7074 case kIOPM_SyncNotifyWillChange
:
7075 if (kIOPMSyncNoChildNotify
& fHeadNoteChangeFlags
)
7077 fMachineState
= kIOPM_SyncFinish
;
7080 fMachineState
= kIOPM_SyncNotifyDidChange
;
7081 fDriverCallReason
= kDriverCallInformPreChange
;
7085 case kIOPM_SyncNotifyDidChange
:
7086 fIsPreChange
= false;
7088 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
)
7090 fMachineState
= kIOPM_SyncFinish
;
7094 assert(IS_ROOT_DOMAIN
);
7095 fMachineState
= kIOPM_SyncTellCapabilityDidChange
;
7098 fDriverCallReason
= kDriverCallInformPostChange
;
7102 case kIOPM_SyncTellCapabilityDidChange
:
7103 tellSystemCapabilityChange( kIOPM_SyncFinish
);
7106 case kIOPM_SyncFinish
:
7107 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
)
7108 ParentChangeAcknowledgePowerChange();
7113 case kIOPM_TellCapabilityChangeDone
:
7116 if (fOutOfBandParameter
== kNotifyCapabilityChangePriority
)
7118 MS_POP(); // tellSystemCapabilityChange()
7121 fOutOfBandParameter
= kNotifyCapabilityChangePriority
;
7125 if (fOutOfBandParameter
== kNotifyCapabilityChangeApps
)
7127 MS_POP(); // tellSystemCapabilityChange()
7130 fOutOfBandParameter
= kNotifyCapabilityChangeApps
;
7132 tellClientsWithResponse( fOutOfBandMessage
);
7136 panic("servicePMWorkQueue: unknown machine state %x",
7142 if (fMachineState
== kIOPM_Finished
)
7152 //*********************************************************************************
7153 // [private] executePMRequest
7154 //*********************************************************************************
7156 void IOService::executePMRequest( IOPMRequest
* request
)
7158 assert( kIOPM_Finished
== fMachineState
);
7160 switch (request
->getType())
7162 case kIOPMRequestTypePMStop
:
7163 handlePMstop( request
);
7166 case kIOPMRequestTypeAddPowerChild1
:
7167 addPowerChild1( request
);
7170 case kIOPMRequestTypeAddPowerChild2
:
7171 addPowerChild2( request
);
7174 case kIOPMRequestTypeAddPowerChild3
:
7175 addPowerChild3( request
);
7178 case kIOPMRequestTypeRegisterPowerDriver
:
7179 handleRegisterPowerDriver( request
);
7182 case kIOPMRequestTypeAdjustPowerState
:
7183 fAdjustPowerScheduled
= false;
7187 case kIOPMRequestTypePowerDomainWillChange
:
7188 handlePowerDomainWillChangeTo( request
);
7191 case kIOPMRequestTypePowerDomainDidChange
:
7192 handlePowerDomainDidChangeTo( request
);
7195 case kIOPMRequestTypeRequestPowerState
:
7196 case kIOPMRequestTypeRequestPowerStateOverride
:
7197 handleRequestPowerState( request
);
7200 case kIOPMRequestTypePowerOverrideOnPriv
:
7201 case kIOPMRequestTypePowerOverrideOffPriv
:
7202 handlePowerOverrideChanged( request
);
7205 case kIOPMRequestTypeActivityTickle
:
7206 handleActivityTickle( request
);
7209 case kIOPMRequestTypeSynchronizePowerTree
:
7210 handleSynchronizePowerTree( request
);
7213 case kIOPMRequestTypeSetIdleTimerPeriod
:
7215 fIdleTimerPeriod
= (uintptr_t) request
->fArg0
;
7216 if ((false == fLockedFlags
.PMStop
) && (fIdleTimerPeriod
> 0))
7221 case kIOPMRequestTypeIgnoreIdleTimer
:
7222 fIdleTimerIgnored
= request
->fArg0
? 1 : 0;
7226 panic("executePMRequest: unknown request type %x", request
->getType());
7230 //*********************************************************************************
7231 // [private] servicePMReplyQueue
7232 //*********************************************************************************
7234 bool IOService::servicePMReplyQueue( IOPMRequest
* request
, IOPMRequestQueue
* queue
)
7238 assert( request
&& queue
);
7239 assert( request
->isReplyType() );
7241 PM_LOG1("[A %02x] %p [%p %s] state %d\n",
7242 request
->getType(), request
, this, getName(), fMachineState
);
7244 switch ( request
->getType() )
7246 case kIOPMRequestTypeAllowPowerChange
:
7247 case kIOPMRequestTypeCancelPowerChange
:
7248 // Check if we are expecting this response.
7249 if (responseValid((uint32_t)(uintptr_t) request
->fArg0
,
7250 (int)(uintptr_t) request
->fArg1
))
7252 if (kIOPMRequestTypeCancelPowerChange
== request
->getType())
7254 // Clients are not allowed to cancel when kIOPMSkipAskPowerDown
7255 // flag is set. Only root domain will set this flag.
7257 if ((fHeadNoteChangeFlags
& kIOPMSkipAskPowerDown
) == 0)
7259 fDoNotPowerDown
= true;
7261 OSString
* name
= (OSString
*) request
->fArg2
;
7262 getPMRootDomain()->pmStatsRecordApplicationResponse(
7263 gIOPMStatsApplicationResponseCancel
,
7264 name
? name
->getCStringNoCopy() : "", 0,
7265 0, (int)(uintptr_t) request
->fArg1
);
7272 cleanClientResponses(false);
7276 // OSString containing app name in Arg2 must be released.
7277 if (request
->getType() == kIOPMRequestTypeCancelPowerChange
)
7279 OSObject
* obj
= (OSObject
*) request
->fArg2
;
7280 if (obj
) obj
->release();
7284 case kIOPMRequestTypeAckPowerChange
:
7285 more
= handleAcknowledgePowerChange( request
);
7288 case kIOPMRequestTypeAckSetPowerState
:
7289 if (fDriverTimer
== -1)
7291 // driver acked while setPowerState() call is in-flight.
7292 // take this ack, return value from setPowerState() is irrelevant.
7293 OUR_PMLog(kPMLogDriverAcknowledgeSet
,
7294 (uintptr_t) this, fDriverTimer
);
7297 else if (fDriverTimer
> 0)
7299 // expected ack, stop the timer
7302 #if LOG_SETPOWER_TIMES
7303 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
7304 if (nsec
> LOG_SETPOWER_TIMES
)
7305 PM_LOG("%s::setPowerState(%p, %lu -> %lu) async took %d ms\n",
7306 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
7308 PMEventDetails
*details
= PMEventDetails::eventDetails(
7309 kIOPMEventTypeSetPowerStateDelayed
, // type
7311 (uintptr_t)this, // owner unique
7312 NULL
, // interest name
7313 (uint8_t)getPowerState(), // old
7314 (uint8_t)fHeadNotePowerState
, // new
7316 NS_TO_US(nsec
)); // usec completion time
7318 getPMRootDomain()->recordAndReleasePMEventGated( details
);
7320 OUR_PMLog(kPMLogDriverAcknowledgeSet
, (uintptr_t) this, fDriverTimer
);
7327 OUR_PMLog(kPMLogAcknowledgeErr4
, (uintptr_t) this, 0);
7331 case kIOPMRequestTypeInterestChanged
:
7332 handleInterestChanged( request
);
7336 case kIOPMRequestTypeIdleCancel
:
7337 if ((fMachineState
== kIOPM_OurChangeTellClientsPowerDown
)
7338 || (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
)
7339 || (fMachineState
== kIOPM_SyncTellClientsPowerDown
)
7340 || (fMachineState
== kIOPM_SyncTellPriorityClientsPowerDown
))
7342 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7343 PM_LOG2("%s: cancel from machine state %d\n",
7344 getName(), fMachineState
);
7345 fDoNotPowerDown
= true;
7346 // Stop waiting for app replys.
7347 if ((fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
) ||
7348 (fMachineState
== kIOPM_SyncTellPriorityClientsPowerDown
))
7349 cleanClientResponses(false);
7354 case kIOPMRequestTypeChildNotifyDelayCancel
:
7355 if (fMachineState
== kIOPM_NotifyChildrenDelayed
)
7357 PM_LOG2("%s: delay notify cancelled\n", getName());
7358 notifyChildrenDelayed();
7363 panic("servicePMReplyQueue: unknown reply type %x",
7364 request
->getType());
7367 more
|= gIOPMFreeQueue
->queuePMRequest(request
);
7369 gIOPMWorkQueue
->incrementProducerCount();
7374 //*********************************************************************************
7375 // [private] assertPMDriverCall / deassertPMDriverCall
7376 //*********************************************************************************
7378 bool IOService::assertPMDriverCall(
7379 IOPMDriverCallEntry
* entry
,
7380 IOOptionBits options
,
7381 IOPMinformee
* inform
)
7383 IOService
* target
= 0;
7391 if (fLockedFlags
.PMStop
)
7396 if (((options
& kIOPMADC_NoInactiveCheck
) == 0) && isInactive())
7403 if (!inform
->active
)
7407 target
= inform
->whatObject
;
7408 if (target
->isInactive())
7414 entry
->thread
= current_thread();
7415 entry
->target
= target
;
7416 queue_enter(&fPMDriverCallQueue
, entry
, IOPMDriverCallEntry
*, link
);
7425 void IOService::deassertPMDriverCall( IOPMDriverCallEntry
* entry
)
7427 bool wakeup
= false;
7431 assert( !queue_empty(&fPMDriverCallQueue
) );
7432 queue_remove(&fPMDriverCallQueue
, entry
, IOPMDriverCallEntry
*, link
);
7433 if (fLockedFlags
.PMDriverCallWait
)
7441 PM_LOCK_WAKEUP(&fPMDriverCallQueue
);
7444 void IOService::waitForPMDriverCall( IOService
* target
)
7446 const IOPMDriverCallEntry
* entry
;
7447 thread_t thread
= current_thread();
7448 AbsoluteTime deadline
;
7455 queue_iterate(&fPMDriverCallQueue
, entry
, const IOPMDriverCallEntry
*, link
)
7457 // Target of interested driver call
7458 if (target
&& (target
!= entry
->target
))
7461 if (entry
->thread
== thread
)
7465 PM_LOG("%s: %s(%s) on PM thread\n",
7466 fName
, __FUNCTION__
, target
? target
->getName() : "");
7467 OSReportWithBacktrace("%s: %s(%s) on PM thread\n",
7468 fName
, __FUNCTION__
, target
? target
->getName() : "");
7480 fLockedFlags
.PMDriverCallWait
= true;
7481 clock_interval_to_deadline(15, kSecondScale
, &deadline
);
7482 waitResult
= PM_LOCK_SLEEP(&fPMDriverCallQueue
, deadline
);
7483 fLockedFlags
.PMDriverCallWait
= false;
7484 if (THREAD_TIMED_OUT
== waitResult
)
7486 PM_ERROR("%s: waitForPMDriverCall timeout\n", fName
);
7493 //*********************************************************************************
7494 // [private] Debug helpers
7495 //*********************************************************************************
7497 const char * IOService::getIOMessageString( uint32_t msg
)
7499 #define MSG_ENTRY(x) {x, #x}
7501 static const IONamedValue msgNames
[] = {
7502 MSG_ENTRY( kIOMessageCanDevicePowerOff
),
7503 MSG_ENTRY( kIOMessageDeviceWillPowerOff
),
7504 MSG_ENTRY( kIOMessageDeviceWillNotPowerOff
),
7505 MSG_ENTRY( kIOMessageDeviceHasPoweredOn
),
7506 MSG_ENTRY( kIOMessageCanSystemPowerOff
),
7507 MSG_ENTRY( kIOMessageSystemWillPowerOff
),
7508 MSG_ENTRY( kIOMessageSystemWillNotPowerOff
),
7509 MSG_ENTRY( kIOMessageCanSystemSleep
),
7510 MSG_ENTRY( kIOMessageSystemWillSleep
),
7511 MSG_ENTRY( kIOMessageSystemWillNotSleep
),
7512 MSG_ENTRY( kIOMessageSystemHasPoweredOn
),
7513 MSG_ENTRY( kIOMessageSystemWillRestart
),
7514 MSG_ENTRY( kIOMessageSystemWillPowerOn
),
7515 MSG_ENTRY( kIOMessageSystemCapabilityChange
)
7518 return IOFindNameForValue(msg
, msgNames
);
7522 // MARK: IOPMRequest
7524 //*********************************************************************************
7525 // IOPMRequest Class
7527 // Requests from PM clients, and also used for inter-object messaging within PM.
7528 //*********************************************************************************
7530 OSDefineMetaClassAndStructors( IOPMRequest
, IOCommand
);
7532 IOPMRequest
* IOPMRequest::create( void )
7534 IOPMRequest
* me
= OSTypeAlloc(IOPMRequest
);
7535 if (me
&& !me
->init(0, kIOPMRequestTypeInvalid
))
7543 bool IOPMRequest::init( IOService
* target
, IOOptionBits type
)
7545 if (!IOCommand::init())
7550 fCompletionStatus
= kIOReturnSuccess
;
7558 void IOPMRequest::reset( void )
7560 assert( fWorkWaitCount
== 0 );
7561 assert( fFreeWaitCount
== 0 );
7563 detachNextRequest();
7564 detachRootRequest();
7566 fType
= kIOPMRequestTypeInvalid
;
7569 if (fCompletionAction
)
7571 fCompletionAction(fCompletionTarget
, fCompletionParam
, fCompletionStatus
);
7582 bool IOPMRequest::attachNextRequest( IOPMRequest
* next
)
7588 // Postpone the execution of the next request after
7590 fRequestNext
= next
;
7591 fRequestNext
->fWorkWaitCount
++;
7592 #if LOG_REQUEST_ATTACH
7593 PM_LOG("Attached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
7594 this, (uint32_t) fType
, fRequestNext
,
7595 (uint32_t) fRequestNext
->fType
,
7596 (uint32_t) fRequestNext
->fWorkWaitCount
,
7597 fTarget
->getName());
7604 bool IOPMRequest::detachNextRequest( void )
7610 assert(fRequestNext
->fWorkWaitCount
);
7611 if (fRequestNext
->fWorkWaitCount
)
7612 fRequestNext
->fWorkWaitCount
--;
7613 #if LOG_REQUEST_ATTACH
7614 PM_LOG("Detached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
7615 this, (uint32_t) fType
, fRequestNext
,
7616 (uint32_t) fRequestNext
->fType
,
7617 (uint32_t) fRequestNext
->fWorkWaitCount
,
7618 fTarget
->getName());
7626 bool IOPMRequest::attachRootRequest( IOPMRequest
* root
)
7632 // Delay the completion of the root request after
7634 fRequestRoot
= root
;
7635 fRequestRoot
->fFreeWaitCount
++;
7636 #if LOG_REQUEST_ATTACH
7637 PM_LOG("Attached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
7638 this, (uint32_t) fType
, fRequestRoot
,
7639 (uint32_t) fRequestRoot
->fType
,
7640 (uint32_t) fRequestRoot
->fFreeWaitCount
,
7641 fTarget
->getName());
7648 bool IOPMRequest::detachRootRequest( void )
7654 assert(fRequestRoot
->fFreeWaitCount
);
7655 if (fRequestRoot
->fFreeWaitCount
)
7656 fRequestRoot
->fFreeWaitCount
--;
7657 #if LOG_REQUEST_ATTACH
7658 PM_LOG("Detached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
7659 this, (uint32_t) fType
, fRequestRoot
,
7660 (uint32_t) fRequestRoot
->fType
,
7661 (uint32_t) fRequestRoot
->fFreeWaitCount
,
7662 fTarget
->getName());
7671 // MARK: IOPMRequestQueue
7673 //*********************************************************************************
7674 // IOPMRequestQueue Class
7676 // Global queues. Queues are created once and never released.
7677 //*********************************************************************************
7679 OSDefineMetaClassAndStructors( IOPMRequestQueue
, IOEventSource
);
7681 IOPMRequestQueue
* IOPMRequestQueue::create( IOService
* inOwner
, Action inAction
)
7683 IOPMRequestQueue
* me
= OSTypeAlloc(IOPMRequestQueue
);
7684 if (me
&& !me
->init(inOwner
, inAction
))
7692 bool IOPMRequestQueue::init( IOService
* inOwner
, Action inAction
)
7694 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
))
7697 queue_init(&fQueue
);
7698 fLock
= IOLockAlloc();
7699 return (fLock
!= 0);
7702 void IOPMRequestQueue::free( void )
7709 return IOEventSource::free();
7712 void IOPMRequestQueue::queuePMRequest( IOPMRequest
* request
)
7716 queue_enter(&fQueue
, request
, IOPMRequest
*, fCommandChain
);
7717 IOLockUnlock(fLock
);
7718 if (workLoop
) signalWorkAvailable();
7722 IOPMRequestQueue::queuePMRequestChain( IOPMRequest
** requests
, IOItemCount count
)
7726 assert(requests
&& count
);
7732 queue_enter(&fQueue
, next
, IOPMRequest
*, fCommandChain
);
7734 IOLockUnlock(fLock
);
7735 if (workLoop
) signalWorkAvailable();
7738 bool IOPMRequestQueue::checkForWork( void )
7740 Action dqAction
= (Action
) action
;
7741 IOPMRequest
* request
;
7745 IOLockLock( fLock
);
7747 while (!queue_empty(&fQueue
))
7749 queue_remove_first( &fQueue
, request
, IOPMRequest
*, fCommandChain
);
7750 IOLockUnlock( fLock
);
7751 target
= request
->getTarget();
7753 more
|= (*dqAction
)( target
, request
, this );
7754 IOLockLock( fLock
);
7757 IOLockUnlock( fLock
);
7762 // MARK: IOPMWorkQueue
7764 //*********************************************************************************
7765 // IOPMWorkQueue Class
7767 // Queue of IOServicePM objects with busy IOPMRequest(s).
7768 //*********************************************************************************
7770 OSDefineMetaClassAndStructors( IOPMWorkQueue
, IOEventSource
);
7773 IOPMWorkQueue::create( IOService
* inOwner
, Action work
, Action retire
)
7775 IOPMWorkQueue
* me
= OSTypeAlloc(IOPMWorkQueue
);
7776 if (me
&& !me
->init(inOwner
, work
, retire
))
7784 bool IOPMWorkQueue::init( IOService
* inOwner
, Action work
, Action retire
)
7786 if (!work
|| !retire
||
7787 !IOEventSource::init(inOwner
, (IOEventSourceAction
)0))
7790 queue_init(&fWorkQueue
);
7793 fRetireAction
= retire
;
7794 fConsumerCount
= fProducerCount
= 0;
7799 bool IOPMWorkQueue::queuePMRequest( IOPMRequest
* request
, IOServicePM
* pwrMgt
)
7806 assert( onThread() );
7807 assert( queue_next(&request
->fCommandChain
) ==
7808 queue_prev(&request
->fCommandChain
) );
7812 // Add new request to the tail of the per-service request queue.
7813 // Then immediately check the request queue to minimize latency
7814 // if the queue was empty.
7816 empty
= queue_empty(&pwrMgt
->RequestHead
);
7817 queue_enter(&pwrMgt
->RequestHead
, request
, IOPMRequest
*, fCommandChain
);
7820 more
= checkRequestQueue(&pwrMgt
->RequestHead
, &empty
);
7823 // New Request is blocked, add IOServicePM to work queue.
7824 assert( queue_next(&pwrMgt
->WorkChain
) ==
7825 queue_prev(&pwrMgt
->WorkChain
) );
7827 queue_enter(&fWorkQueue
, pwrMgt
, IOServicePM
*, WorkChain
);
7829 PM_LOG3("IOPMWorkQueue: [%u] added %s@%p to queue\n",
7830 fQueueLength
, pwrMgt
->Name
, pwrMgt
);
7837 bool IOPMWorkQueue::checkRequestQueue( queue_head_t
* queue
, bool * empty
)
7839 IOPMRequest
* request
;
7844 assert(!queue_empty(queue
));
7846 request
= (IOPMRequest
*) queue_first(queue
);
7847 if (request
->isWorkBlocked())
7848 break; // cannot start, blocked on attached request
7850 target
= request
->getTarget();
7851 done
= (*fWorkAction
)( target
, request
, this );
7853 break; // work started, blocked on PM state machine
7855 assert(gIOPMBusyCount
> 0);
7859 queue_remove_first(queue
, request
, IOPMRequest
*, fCommandChain
);
7860 more
|= (*fRetireAction
)( target
, request
, this );
7861 done
= queue_empty(queue
);
7868 // Retired request blocks another request, since the
7869 // blocked request may reside in the work queue, we
7870 // must bump the producer count to avoid work stall.
7877 bool IOPMWorkQueue::checkForWork( void )
7879 IOServicePM
* entry
;
7884 #if WORK_QUEUE_STATS
7885 fStatCheckForWork
++;
7888 // Each producer signal triggers a full iteration over
7889 // all IOServicePM entries in the work queue.
7891 while (fConsumerCount
!= fProducerCount
)
7893 PM_LOG3("IOPMWorkQueue: checkForWork %u %u\n",
7894 fProducerCount
, fConsumerCount
);
7896 fConsumerCount
= fProducerCount
;
7898 #if WORK_QUEUE_STATS
7899 if (queue_empty(&fWorkQueue
))
7905 uint32_t cachedWorkCount
= gIOPMWorkCount
;
7908 entry
= (IOServicePM
*) queue_first(&fWorkQueue
);
7909 while (!queue_end(&fWorkQueue
, (queue_entry_t
) entry
))
7911 more
|= checkRequestQueue(&entry
->RequestHead
, &empty
);
7913 // Get next entry, points to head if current entry is last.
7914 next
= (IOServicePM
*) queue_next(&entry
->WorkChain
);
7916 // if request queue is empty, remove IOServicePM from queue.
7919 assert(fQueueLength
);
7920 if (fQueueLength
) fQueueLength
--;
7921 PM_LOG3("IOPMWorkQueue: [%u] removed %s@%p from queue\n",
7922 fQueueLength
, entry
->Name
, entry
);
7923 queue_remove(&fWorkQueue
, entry
, IOServicePM
*, WorkChain
);
7928 #if WORK_QUEUE_STATS
7929 if (cachedWorkCount
== gIOPMWorkCount
)
7937 void IOPMWorkQueue::signalWorkAvailable( void )
7940 IOEventSource::signalWorkAvailable();
7943 void IOPMWorkQueue::incrementProducerCount( void )
7949 // MARK: IOPMCompletionQueue
7951 //*********************************************************************************
7952 // IOPMCompletionQueue Class
7953 //*********************************************************************************
7955 OSDefineMetaClassAndStructors( IOPMCompletionQueue
, IOEventSource
);
7957 IOPMCompletionQueue
*
7958 IOPMCompletionQueue::create( IOService
* inOwner
, Action inAction
)
7960 IOPMCompletionQueue
* me
= OSTypeAlloc(IOPMCompletionQueue
);
7961 if (me
&& !me
->init(inOwner
, inAction
))
7969 bool IOPMCompletionQueue::init( IOService
* inOwner
, Action inAction
)
7971 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
))
7974 queue_init(&fQueue
);
7978 bool IOPMCompletionQueue::queuePMRequest( IOPMRequest
* request
)
7983 // unblock dependent request
7984 more
= request
->detachNextRequest();
7985 queue_enter(&fQueue
, request
, IOPMRequest
*, fCommandChain
);
7989 bool IOPMCompletionQueue::checkForWork( void )
7991 Action dqAction
= (Action
) action
;
7992 IOPMRequest
* request
;
7997 request
= (IOPMRequest
*) queue_first(&fQueue
);
7998 while (!queue_end(&fQueue
, (queue_entry_t
) request
))
8000 next
= (IOPMRequest
*) queue_next(&request
->fCommandChain
);
8001 if (!request
->isFreeBlocked())
8003 queue_remove(&fQueue
, request
, IOPMRequest
*, fCommandChain
);
8004 target
= request
->getTarget();
8006 more
|= (*dqAction
)( target
, request
, this );
8015 // MARK: IOServicePM
8017 OSDefineMetaClassAndStructors(IOServicePM
, OSObject
)
8019 //*********************************************************************************
8022 // Serialize IOServicePM for debugging.
8023 //*********************************************************************************
8026 setPMProperty( OSDictionary
* dict
, const char * key
, uint64_t value
)
8028 OSNumber
* num
= OSNumber::withNumber(value
, sizeof(value
) * 8);
8031 dict
->setObject(key
, num
);
8036 IOReturn
IOServicePM::gatedSerialize( OSSerialize
* s
)
8038 OSDictionary
* dict
;
8042 if (IdleTimerPeriod
)
8045 #if WORK_QUEUE_STATS
8046 if (gIOPMRootNode
== ControllingDriver
)
8051 dict
= OSDictionary::withDictionary(
8052 PowerClients
, PowerClients
->getCount() + dictSize
);
8054 dict
= OSDictionary::withCapacity(dictSize
);
8058 setPMProperty(dict
, "CurrentPowerState", CurrentPowerState
);
8059 if (NumberOfPowerStates
)
8060 setPMProperty(dict
, "MaxPowerState", NumberOfPowerStates
-1);
8061 if (DesiredPowerState
!= CurrentPowerState
)
8062 setPMProperty(dict
, "DesiredPowerState", DesiredPowerState
);
8063 if (kIOPM_Finished
!= MachineState
)
8064 setPMProperty(dict
, "MachineState", MachineState
);
8065 if (DeviceOverrideEnabled
)
8066 dict
->setObject("PowerOverrideOn", kOSBooleanTrue
);
8068 if (IdleTimerPeriod
)
8074 clock_get_uptime(&now
);
8076 // The idle timer period in milliseconds.
8077 setPMProperty(dict
, "IdleTimerPeriod", IdleTimerPeriod
* 1000ULL);
8079 // The number of activity tickles recorded since device idle
8080 setPMProperty(dict
, "ActivityTickles", ActivityTickleCount
);
8082 if (AbsoluteTime_to_scalar(&DeviceActiveTimestamp
))
8084 // The number of milliseconds since the last activity tickle.
8086 SUB_ABSOLUTETIME(&delta
, &DeviceActiveTimestamp
);
8087 absolutetime_to_nanoseconds(delta
, &nsecs
);
8088 setPMProperty(dict
, "TimeSinceLastTickle", NS_TO_MS(nsecs
));
8091 if (AbsoluteTime_to_scalar(&IdleTimerStartTime
))
8093 // The number of milliseconds since the last device idle.
8095 SUB_ABSOLUTETIME(&delta
, &IdleTimerStartTime
);
8096 absolutetime_to_nanoseconds(delta
, &nsecs
);
8097 setPMProperty(dict
, "TimeSinceDeviceIdle", NS_TO_MS(nsecs
));
8101 #if WORK_QUEUE_STATS
8102 if (gIOPMRootNode
== Owner
)
8104 setPMProperty(dict
, "WQ-CheckForWork",
8105 gIOPMWorkQueue
->fStatCheckForWork
);
8106 setPMProperty(dict
, "WQ-ScanEntries",
8107 gIOPMWorkQueue
->fStatScanEntries
);
8108 setPMProperty(dict
, "WQ-QueueEmpty",
8109 gIOPMWorkQueue
->fStatQueueEmpty
);
8110 setPMProperty(dict
, "WQ-NoWorkDone",
8111 gIOPMWorkQueue
->fStatNoWorkDone
);
8115 if (HasAdvisoryDesire
&& !gIOPMAdvisoryTickleEnabled
)
8117 // Don't report advisory tickle when it has no influence
8118 dict
->removeObject(gIOPMPowerClientAdvisoryTickle
);
8121 ok
= dict
->serialize(s
);
8125 return (ok
? kIOReturnSuccess
: kIOReturnNoMemory
);
8128 bool IOServicePM::serialize( OSSerialize
* s
) const
8130 IOReturn ret
= kIOReturnNotReady
;
8134 ret
= gIOPMWorkLoop
->runAction(
8135 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOServicePM::gatedSerialize
),
8136 (OSObject
*) this, (void *) s
);
8139 return (kIOReturnSuccess
== ret
);
8142 void IOServicePM::pmPrint(
8145 uintptr_t param2
) const
8147 gPlatform
->PMLog(Name
, event
, param1
, param2
);
8150 void IOServicePM::pmTrace(
8153 uintptr_t param2
) const
8155 const char * who
= Name
;
8156 uint64_t regId
= Owner
->getRegistryEntryID();
8159 static const uint32_t sStartStopBitField
[] =
8160 { 0x00000000, 0x00000040 }; // Only Program Hardware so far
8162 // Arcane formula from Hacker's Delight by Warren
8163 // abs(x) = ((int) x >> 31) ^ (x + ((int) x >> 31))
8164 uint32_t sgnevent
= ((int) event
>> 31);
8165 uint32_t absevent
= sgnevent
^ (event
+ sgnevent
);
8166 uint32_t code
= IODBG_POWER(absevent
);
8168 uint32_t bit
= 1 << (absevent
& 0x1f);
8169 if ((absevent
< (sizeof(sStartStopBitField
) * 8)) &&
8170 (sStartStopBitField
[absevent
>> 5] & bit
))
8172 // Or in the START or END bits, Start = 1 & END = 2
8173 // If sgnevent == 0 then START - 0 => START
8174 // else if sgnevent == -1 then START - -1 => END
8175 code
|= DBG_FUNC_START
- sgnevent
;
8178 // Copy the first characters of the name into an uintptr_t
8179 for (uint32_t i
= 0; (i
< sizeof(uintptr_t) && who
[i
] != 0); i
++)
8181 ((char *) &name
)[sizeof(uintptr_t) - i
- 1] = who
[i
];
8184 IOTimeStampConstant(code
, name
, (uintptr_t) regId
, param1
, param2
);
8187 PMEventDetails
* PMEventDetails::eventDetails(uint32_t type
,
8188 const char *ownerName
,
8189 uintptr_t ownerUnique
,
8190 const char *interestName
,
8194 uint32_t elapsedTimeUS
) {
8196 PMEventDetails
*myself
;
8197 myself
= new PMEventDetails
;
8200 myself
->eventType
= type
;
8201 myself
->ownerName
= ownerName
;
8202 myself
->ownerUnique
= ownerUnique
;
8203 myself
->interestName
= interestName
;
8204 myself
->oldState
= oldState
;
8205 myself
->newState
= newState
;
8206 myself
->result
= result
;
8207 myself
->elapsedTimeUS
= elapsedTimeUS
;
8209 myself
->eventClassifier
= kIOPMEventClassDriverEvent
;
8216 PMEventDetails
* PMEventDetails::eventDetails(uint32_t type
,
8221 PMEventDetails
*myself
;
8222 myself
= new PMEventDetails
;
8225 myself
->eventType
= type
;
8226 myself
->uuid
= uuid
;
8227 myself
->reason
= reason
;
8228 myself
->result
= result
;
8230 myself
->eventClassifier
= kIOPMEventClassSystemEvent
;