1 | /* |
2 | * Copyright (c) 2019-2020 Apple Inc. All rights reserved. |
3 | * |
4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
5 | * |
6 | * This file contains Original Code and/or Modifications of Original Code |
7 | * as defined in and that are subject to the Apple Public Source License |
8 | * Version 2.0 (the 'License'). You may not use this file except in |
9 | * compliance with the License. The rights granted to you under the 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. |
14 | * |
15 | * Please obtain a copy of the License at |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. |
17 | * |
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. |
25 | * |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
27 | */ |
28 | |
29 | #ifndef _IOKIT_IOSERVICEPMPRIVATE_H |
30 | #define _IOKIT_IOSERVICEPMPRIVATE_H |
31 | |
32 | #include <IOKit/IOCommand.h> |
33 | #include <IOKit/IOEventSource.h> |
34 | |
35 | #define USE_SETTLE_TIMER 0 |
36 | |
37 | //****************************************************************************** |
38 | // PM command types |
39 | //****************************************************************************** |
40 | |
41 | enum { |
42 | /* Command Types */ |
43 | kIOPMRequestTypeInvalid = 0x00, |
44 | kIOPMRequestTypePMStop = 0x01, |
45 | kIOPMRequestTypeAddPowerChild1 = 0x02, |
46 | kIOPMRequestTypeAddPowerChild2 = 0x03, |
47 | kIOPMRequestTypeAddPowerChild3 = 0x04, |
48 | kIOPMRequestTypeRegisterPowerDriver = 0x05, |
49 | kIOPMRequestTypeAdjustPowerState = 0x06, |
50 | kIOPMRequestTypePowerDomainWillChange = 0x07, |
51 | kIOPMRequestTypePowerDomainDidChange = 0x08, |
52 | kIOPMRequestTypePowerOverrideOnPriv = 0x09, |
53 | kIOPMRequestTypePowerOverrideOffPriv = 0x0A, |
54 | kIOPMRequestTypeActivityTickle = 0x0B, |
55 | kIOPMRequestTypeRequestPowerState = 0x0C, |
56 | kIOPMRequestTypeSynchronizePowerTree = 0x0D, |
57 | kIOPMRequestTypeRequestPowerStateOverride = 0x0E, |
58 | kIOPMRequestTypeSetIdleTimerPeriod = 0x0F, |
59 | kIOPMRequestTypeIgnoreIdleTimer = 0x10, |
60 | kIOPMRequestTypeQuiescePowerTree = 0x11, |
61 | kIOPMRequestTypeDeferredActivityTickle = 0x12, |
62 | |
63 | /* Reply Types */ |
64 | kIOPMRequestTypeReplyStart = 0x80, |
65 | kIOPMRequestTypeAckPowerChange = 0x81, |
66 | kIOPMRequestTypeAckSetPowerState = 0x82, |
67 | kIOPMRequestTypeAllowPowerChange = 0x83, |
68 | kIOPMRequestTypeCancelPowerChange = 0x84, |
69 | kIOPMRequestTypeInterestChanged = 0x85, |
70 | kIOPMRequestTypeIdleCancel = 0x86, |
71 | kIOPMRequestTypeChildNotifyDelayCancel = 0x87 |
72 | }; |
73 | |
74 | //****************************************************************************** |
75 | // PM actions - For root domain only |
76 | //****************************************************************************** |
77 | |
78 | struct IOPMActions; |
79 | |
80 | typedef void |
81 | (*IOPMActionPowerChangeStart)( |
82 | void * target, |
83 | IOService * service, |
84 | IOPMActions * actions, |
85 | const IOPMRequest * request, |
86 | IOPMPowerStateIndex powerState, |
87 | IOPMPowerChangeFlags * changeFlagsPtr ); |
88 | |
89 | typedef void |
90 | (*IOPMActionPowerChangeDone)( |
91 | void * target, |
92 | IOService * service, |
93 | IOPMActions * actions, |
94 | const IOPMRequest * request, |
95 | IOPMPowerStateIndex powerState, |
96 | IOPMPowerChangeFlags changeFlags ); |
97 | |
98 | typedef void |
99 | (*IOPMActionPowerChangeOverride)( |
100 | void * target, |
101 | IOService * service, |
102 | IOPMActions * actions, |
103 | const IOPMRequest * request, |
104 | IOPMPowerStateIndex * powerStatePtr, |
105 | IOPMPowerChangeFlags * changeFlagsPtr ); |
106 | |
107 | typedef void |
108 | (*IOPMActionActivityTickle)( |
109 | void * target, |
110 | IOService * service, |
111 | IOPMActions * actions ); |
112 | |
113 | typedef void |
114 | (*IOPMActionUpdatePowerClient)( |
115 | void * target, |
116 | IOService * service, |
117 | IOPMActions * actions, |
118 | const OSSymbol * powerClient, |
119 | IOPMPowerStateIndex oldPowerState, |
120 | IOPMPowerStateIndex newPowerState ); |
121 | |
122 | struct IOPMActions { |
123 | void * target; |
124 | IOPMActionPowerChangeStart actionPowerChangeStart; |
125 | IOPMActionPowerChangeDone actionPowerChangeDone; |
126 | IOPMActionPowerChangeOverride actionPowerChangeOverride; |
127 | IOPMActionActivityTickle actionActivityTickle; |
128 | IOPMActionUpdatePowerClient actionUpdatePowerClient; |
129 | uint32_t darkWakePowerState; |
130 | uint16_t flags; |
131 | uint16_t state; |
132 | }; |
133 | |
134 | // IOPMActions flags |
135 | enum { |
136 | kPMActionsPCIBitNumberMask = 0x00ff, |
137 | kPMActionsFlagIsDisplayWrangler = 0x0100, |
138 | kPMActionsFlagIsGraphicsDriver = 0x0200, |
139 | kPMActionsFlagIsAudioDriver = 0x0400, |
140 | kPMActionsFlagHasDarkWakePowerState = 0x0800 |
141 | }; |
142 | |
143 | // IOPMActions state |
144 | enum { |
145 | kPMActionsStatePowerClamped = 0x0001 |
146 | }; |
147 | |
148 | //****************************************************************************** |
149 | // Internal concise representation of IOPMPowerState |
150 | struct IOPMPSEntry { |
151 | IOPMPowerFlags capabilityFlags; |
152 | IOPMPowerFlags outputPowerFlags; |
153 | IOPMPowerFlags inputPowerFlags; |
154 | unsigned long staticPower; |
155 | #if USE_SETTLE_TIMER |
156 | uint32_t settleUpTime; |
157 | uint32_t settleDownTime; |
158 | #endif |
159 | IOPMPowerStateIndex stateOrder; |
160 | IOPMPowerStateIndex stateOrderToIndex; |
161 | }; |
162 | |
163 | //****************************************************************************** |
164 | // IOServicePM |
165 | //****************************************************************************** |
166 | |
167 | class IOServicePM : public OSObject |
168 | { |
169 | friend class IOService; |
170 | friend class IOPMWorkQueue; |
171 | |
172 | OSDeclareDefaultStructors( IOServicePM ); |
173 | |
174 | private: |
175 | // Link IOServicePM objects on IOPMWorkQueue. |
176 | queue_chain_t WorkChain; |
177 | |
178 | // Queue of IOPMRequest objects. |
179 | queue_head_t RequestHead; |
180 | |
181 | // IOService creator and owner. |
182 | IOService * Owner; |
183 | |
184 | // List of interested drivers (protected by PMLock). |
185 | IOPMinformeeList * InterestedDrivers; |
186 | |
187 | // How long to wait for controlling driver to acknowledge. |
188 | IOReturn DriverTimer; |
189 | |
190 | // Current power management machine state. |
191 | uint32_t MachineState; |
192 | |
193 | thread_call_t AckTimer; |
194 | #if USE_SETTLE_TIMER |
195 | thread_call_t SettleTimer; |
196 | #endif |
197 | thread_call_t IdleTimer; |
198 | thread_call_t WatchdogTimer; |
199 | thread_call_t SpinDumpTimer; |
200 | |
201 | IOLock * WatchdogLock; |
202 | OSArray * BlockedArray; |
203 | uint64_t PendingResponseDeadline; |
204 | uint64_t WatchdogDeadline; |
205 | |
206 | // Settle time after changing power state. |
207 | #if USE_SETTLE_TIMER |
208 | uint32_t SettleTimeUS; |
209 | #endif |
210 | IOPMPowerStateIndex IdleTimerGeneration; |
211 | |
212 | // The flags describing current change note. |
213 | IOPMPowerChangeFlags HeadNoteChangeFlags; |
214 | |
215 | // The new power state number being changed to. |
216 | IOPMPowerStateIndex HeadNotePowerState; |
217 | |
218 | // Points to the entry in the power state array. |
219 | IOPMPSEntry * HeadNotePowerArrayEntry; |
220 | |
221 | // Power flags supplied by all parents (domain). |
222 | IOPMPowerFlags HeadNoteDomainFlags; |
223 | |
224 | // Power flags supplied by domain accounting for parent changes. |
225 | IOPMPowerFlags HeadNoteDomainTargetFlags; |
226 | |
227 | // Connection attached to the changing parent. |
228 | IOPowerConnection * HeadNoteParentConnection; |
229 | |
230 | // Power flags supplied by the changing parent. |
231 | IOPMPowerFlags HeadNoteParentFlags; |
232 | |
233 | // Number of acks still outstanding. |
234 | uint32_t HeadNotePendingAcks; |
235 | |
236 | // PM state lock. |
237 | IOLock * PMLock; |
238 | |
239 | unsigned int InitialPowerChange :1; |
240 | unsigned int InitialSetPowerState :1; |
241 | unsigned int DeviceOverrideEnabled :1; |
242 | unsigned int DoNotPowerDown :1; |
243 | unsigned int ParentsKnowState :1; |
244 | unsigned int StrictTreeOrder :1; |
245 | unsigned int IdleTimerStopped :1; |
246 | unsigned int AdjustPowerScheduled :1; |
247 | |
248 | unsigned int IsPreChange :1; |
249 | unsigned int DriverCallBusy :1; |
250 | unsigned int PCDFunctionOverride :1; |
251 | unsigned int IdleTimerIgnored :1; |
252 | unsigned int HasAdvisoryDesire :1; |
253 | unsigned int AdvisoryTickleUsed :1; |
254 | unsigned int ResetPowerStateOnWake :1; |
255 | |
256 | // Time of last device activity. |
257 | AbsoluteTime DeviceActiveTimestamp; |
258 | AbsoluteTime MaxPowerStateEntryTime; |
259 | AbsoluteTime MaxPowerStateExitTime; |
260 | |
261 | // Used to protect activity flag. |
262 | IOLock * ActivityLock; |
263 | |
264 | // Idle timer's period in seconds. |
265 | int IdleTimerPeriod; |
266 | int NextIdleTimerPeriod; |
267 | IOPMPowerStateIndex IdleTimerMinPowerState; |
268 | AbsoluteTime IdleTimerStartTime; |
269 | |
270 | // Power state desired by a subclassed device object. |
271 | IOPMPowerStateIndex DeviceDesire; |
272 | |
273 | // This is the power state we desire currently. |
274 | IOPMPowerStateIndex DesiredPowerState; |
275 | |
276 | // This is what our parent thinks our need is. |
277 | IOPMPowerFlags PreviousRequestPowerFlags; |
278 | |
279 | // Cache result from getName(), used in logging. |
280 | const char * Name; |
281 | |
282 | // Number of power states in the power array. |
283 | IOPMPowerStateIndex NumberOfPowerStates; |
284 | |
285 | // Ordered highest power state in the power array. |
286 | IOPMPowerStateIndex HighestPowerState; |
287 | |
288 | // Power state array. |
289 | IOPMPSEntry * PowerStates; |
290 | |
291 | // The controlling driver. |
292 | IOService * ControllingDriver; |
293 | |
294 | // Our current power state. |
295 | IOPMPowerStateIndex CurrentPowerState; |
296 | |
297 | // Logical OR of power flags for each power domain parent. |
298 | IOPMPowerFlags ParentsCurrentPowerFlags; |
299 | |
300 | // The highest power state we can achieve in current power domain. |
301 | IOPMPowerStateIndex MaxPowerState; |
302 | |
303 | // Logical OR of all output power flags in the power state array. |
304 | IOPMPowerFlags MergedOutputPowerFlags; |
305 | |
306 | // OSArray which manages responses from notified apps and clients. |
307 | OSArray * ResponseArray; |
308 | OSArray * NotifyClientArray; |
309 | |
310 | // Used to uniquely identify power management notification to apps and clients. |
311 | uint16_t SerialNumber; |
312 | |
313 | // Used to communicate desired function to tellClientsWithResponse(). |
314 | // This is used because it avoids changing the signatures of the affected virtual methods. |
315 | int OutOfBandParameter; |
316 | |
317 | AbsoluteTime DriverCallStartTime; |
318 | IOPMPowerFlags CurrentCapabilityFlags; |
319 | unsigned long CurrentPowerConsumption; |
320 | IOPMPowerStateIndex TempClampPowerState; |
321 | OSArray * NotifyChildArray; |
322 | OSDictionary * PowerClients; |
323 | thread_call_t DriverCallEntry; |
324 | void * DriverCallParamPtr; |
325 | IOItemCount DriverCallParamCount; |
326 | IOItemCount DriverCallParamSlots; |
327 | uint32_t DriverCallReason; |
328 | uint32_t OutOfBandMessage; |
329 | uint32_t TempClampCount; |
330 | IOPMPowerStateIndex OverrideMaxPowerState; |
331 | IOPMPowerStateIndex DeviceUsablePowerState; |
332 | |
333 | // Thread to be run alongside DriverCallEntry to provide logging. |
334 | thread_call_t DriverCallTimer; |
335 | |
336 | // Protected by ActivityLock - BEGIN |
337 | IOPMPowerStateIndex ActivityTicklePowerState; |
338 | IOPMPowerStateIndex AdvisoryTicklePowerState; |
339 | uint32_t ActivityTickleCount; |
340 | uint32_t DeviceWasActive : 1; |
341 | uint32_t AdvisoryTickled : 1; |
342 | // Protected by ActivityLock - END |
343 | |
344 | uint32_t WaitReason; |
345 | uint32_t SavedMachineState; |
346 | |
347 | // Protected by PMLock - BEGIN |
348 | struct { |
349 | uint32_t PMStop : 1; |
350 | uint32_t PMDriverCallWait : 1; |
351 | } LockedFlags; |
352 | |
353 | queue_head_t PMDriverCallQueue; |
354 | OSSet * InsertInterestSet; |
355 | OSSet * RemoveInterestSet; |
356 | |
357 | // IOReporter Data |
358 | uint32_t ReportClientCnt; |
359 | void * ReportBuf; |
360 | // Protected by PMLock - END |
361 | |
362 | #if PM_VARS_SUPPORT |
363 | IOPMprot * PMVars; |
364 | #endif |
365 | |
366 | IOPMActions PMActions; |
367 | |
368 | // Serialize IOServicePM state for debug output. |
369 | IOReturn gatedSerialize( OSSerialize * s ) const; |
370 | virtual bool serialize( OSSerialize * s ) const APPLE_KEXT_OVERRIDE; |
371 | |
372 | // PM log and trace |
373 | void pmPrint( uint32_t event, uintptr_t param1, uintptr_t param2 ) const; |
374 | void pmTrace( uint32_t event, uint32_t eventFunc, uintptr_t param1, uintptr_t param2 ) const; |
375 | }; |
376 | |
377 | #define fOwner pwrMgt->Owner |
378 | #define fInterestedDrivers pwrMgt->InterestedDrivers |
379 | #define fDriverTimer pwrMgt->DriverTimer |
380 | #define fMachineState pwrMgt->MachineState |
381 | #define fAckTimer pwrMgt->AckTimer |
382 | #define fSettleTimer pwrMgt->SettleTimer |
383 | #define fIdleTimer pwrMgt->IdleTimer |
384 | #define fWatchdogTimer pwrMgt->WatchdogTimer |
385 | #define fWatchdogDeadline pwrMgt->WatchdogDeadline |
386 | #define fWatchdogLock pwrMgt->WatchdogLock |
387 | #define fBlockedArray pwrMgt->BlockedArray |
388 | #define fPendingResponseDeadline pwrMgt->PendingResponseDeadline |
389 | #define fSettleTimeUS pwrMgt->SettleTimeUS |
390 | #define fIdleTimerGeneration pwrMgt->IdleTimerGeneration |
391 | #define fHeadNoteChangeFlags pwrMgt->HeadNoteChangeFlags |
392 | #define fHeadNotePowerState pwrMgt->HeadNotePowerState |
393 | #define fHeadNotePowerArrayEntry pwrMgt->HeadNotePowerArrayEntry |
394 | #define fHeadNoteDomainFlags pwrMgt->HeadNoteDomainFlags |
395 | #define fHeadNoteDomainTargetFlags pwrMgt->HeadNoteDomainTargetFlags |
396 | #define fHeadNoteParentConnection pwrMgt->HeadNoteParentConnection |
397 | #define fHeadNoteParentFlags pwrMgt->HeadNoteParentFlags |
398 | #define fHeadNotePendingAcks pwrMgt->HeadNotePendingAcks |
399 | #define fPMLock pwrMgt->PMLock |
400 | #define fInitialPowerChange pwrMgt->InitialPowerChange |
401 | #define fInitialSetPowerState pwrMgt->InitialSetPowerState |
402 | #define fDeviceOverrideEnabled pwrMgt->DeviceOverrideEnabled |
403 | #define fDoNotPowerDown pwrMgt->DoNotPowerDown |
404 | #define fParentsKnowState pwrMgt->ParentsKnowState |
405 | #define fStrictTreeOrder pwrMgt->StrictTreeOrder |
406 | #define fIdleTimerStopped pwrMgt->IdleTimerStopped |
407 | #define fAdjustPowerScheduled pwrMgt->AdjustPowerScheduled |
408 | #define fIsPreChange pwrMgt->IsPreChange |
409 | #define fDriverCallBusy pwrMgt->DriverCallBusy |
410 | #define fPCDFunctionOverride pwrMgt->PCDFunctionOverride |
411 | #define fIdleTimerIgnored pwrMgt->IdleTimerIgnored |
412 | #define fHasAdvisoryDesire pwrMgt->HasAdvisoryDesire |
413 | #define fAdvisoryTickleUsed pwrMgt->AdvisoryTickleUsed |
414 | #define fResetPowerStateOnWake pwrMgt->ResetPowerStateOnWake |
415 | #define fDeviceActiveTimestamp pwrMgt->DeviceActiveTimestamp |
416 | #define fMaxPowerStateEntryTime pwrMgt->MaxPowerStateEntryTime |
417 | #define fMaxPowerStateExitTime pwrMgt->MaxPowerStateExitTime |
418 | #define fActivityLock pwrMgt->ActivityLock |
419 | #define fIdleTimerPeriod pwrMgt->IdleTimerPeriod |
420 | #define fIdleTimerMinPowerState pwrMgt->IdleTimerMinPowerState |
421 | #define fNextIdleTimerPeriod pwrMgt->NextIdleTimerPeriod |
422 | #define fIdleTimerStartTime pwrMgt->IdleTimerStartTime |
423 | #define fDeviceDesire pwrMgt->DeviceDesire |
424 | #define fDesiredPowerState pwrMgt->DesiredPowerState |
425 | #define fPreviousRequestPowerFlags pwrMgt->PreviousRequestPowerFlags |
426 | #define fName pwrMgt->Name |
427 | #define fNumberOfPowerStates pwrMgt->NumberOfPowerStates |
428 | #define fHighestPowerState pwrMgt->HighestPowerState |
429 | #define fPowerStates pwrMgt->PowerStates |
430 | #define fControllingDriver pwrMgt->ControllingDriver |
431 | #define fCurrentPowerState pwrMgt->CurrentPowerState |
432 | #define fParentsCurrentPowerFlags pwrMgt->ParentsCurrentPowerFlags |
433 | #define fMaxPowerState pwrMgt->MaxPowerState |
434 | #define fMergedOutputPowerFlags pwrMgt->MergedOutputPowerFlags |
435 | #define fResponseArray pwrMgt->ResponseArray |
436 | #define fNotifyClientArray pwrMgt->NotifyClientArray |
437 | #define fSerialNumber pwrMgt->SerialNumber |
438 | #define fOutOfBandParameter pwrMgt->OutOfBandParameter |
439 | #define fDriverCallStartTime pwrMgt->DriverCallStartTime |
440 | #define fCurrentCapabilityFlags pwrMgt->CurrentCapabilityFlags |
441 | #define fCurrentPowerConsumption pwrMgt->CurrentPowerConsumption |
442 | #define fTempClampPowerState pwrMgt->TempClampPowerState |
443 | #define fNotifyChildArray pwrMgt->NotifyChildArray |
444 | #define fPowerClients pwrMgt->PowerClients |
445 | #define fDriverCallEntry pwrMgt->DriverCallEntry |
446 | #define fDriverCallParamPtr pwrMgt->DriverCallParamPtr |
447 | #define fDriverCallParamCount pwrMgt->DriverCallParamCount |
448 | #define fDriverCallParamSlots pwrMgt->DriverCallParamSlots |
449 | #define fDriverCallReason pwrMgt->DriverCallReason |
450 | #define fOutOfBandMessage pwrMgt->OutOfBandMessage |
451 | #define fTempClampCount pwrMgt->TempClampCount |
452 | #define fOverrideMaxPowerState pwrMgt->OverrideMaxPowerState |
453 | #define fDeviceUsablePowerState pwrMgt->DeviceUsablePowerState |
454 | #define fDriverCallTimer pwrMgt->DriverCallTimer |
455 | #define fActivityTicklePowerState pwrMgt->ActivityTicklePowerState |
456 | #define fAdvisoryTicklePowerState pwrMgt->AdvisoryTicklePowerState |
457 | #define fActivityTickleCount pwrMgt->ActivityTickleCount |
458 | #define fDeviceWasActive pwrMgt->DeviceWasActive |
459 | #define fAdvisoryTickled pwrMgt->AdvisoryTickled |
460 | #define fWaitReason pwrMgt->WaitReason |
461 | #define fSavedMachineState pwrMgt->SavedMachineState |
462 | #define fLockedFlags pwrMgt->LockedFlags |
463 | #define fPMDriverCallQueue pwrMgt->PMDriverCallQueue |
464 | #define fInsertInterestSet pwrMgt->InsertInterestSet |
465 | #define fRemoveInterestSet pwrMgt->RemoveInterestSet |
466 | #define fReportClientCnt pwrMgt->ReportClientCnt |
467 | #define fReportBuf pwrMgt->ReportBuf |
468 | #define fPMVars pwrMgt->PMVars |
469 | #define fPMActions pwrMgt->PMActions |
470 | |
471 | #define StateOrder(state) (((state) < fNumberOfPowerStates) \ |
472 | ? pwrMgt->PowerStates[(state)].stateOrder \ |
473 | : (state)) |
474 | #define StateMax(a, b) (StateOrder((a)) < StateOrder((b)) ? (b) : (a)) |
475 | #define StateMin(a, b) (StateOrder((a)) < StateOrder((b)) ? (a) : (b)) |
476 | |
477 | #define kPowerStateZero (0) |
478 | |
479 | /* |
480 | * When an IOService is waiting for acknowledgement to a power change |
481 | * notification from an interested driver or the controlling driver, |
482 | * the ack timer is ticking every tenth of a second. |
483 | * (100000000 nanoseconds are one tenth of a second). |
484 | */ |
485 | #define ACK_TIMER_PERIOD 100000000 |
486 | |
487 | #if defined(__i386__) || defined(__x86_64__) |
488 | #define WATCHDOG_SLEEP_TIMEOUT (180) // 180 secs |
489 | #define WATCHDOG_WAKE_TIMEOUT (180) // 180 secs |
490 | #else |
491 | #define WATCHDOG_SLEEP_TIMEOUT (35) // 35 secs (kMaxTimeRequested + 5s) |
492 | #define WATCHDOG_WAKE_TIMEOUT (35) // 35 secs (kMaxTimeRequested + 5s) |
493 | #endif |
494 | |
495 | // Max wait time in microseconds for kernel priority and capability clients |
496 | // with async message handlers to acknowledge. |
497 | // |
498 | #define kPriorityClientMaxWait (90 * 1000 * 1000) |
499 | #define kCapabilityClientMaxWait (240 * 1000 * 1000) |
500 | |
501 | // Attributes describing a power state change. |
502 | // See IOPMPowerChangeFlags data type. |
503 | // |
504 | #define kIOPMParentInitiated 0x0001 // power change initiated by our parent |
505 | #define kIOPMSelfInitiated 0x0002 // power change initiated by this device |
506 | #define kIOPMNotDone 0x0004 // we couldn't make this change |
507 | #define kIOPMDomainWillChange 0x0008 // change started by PowerDomainWillChangeTo |
508 | #define kIOPMDomainDidChange 0x0010 // change started by PowerDomainDidChangeTo |
509 | #define kIOPMDomainPowerDrop 0x0020 // Domain is lowering power |
510 | #define kIOPMIgnoreChildren 0x0040 // Ignore children and driver power desires |
511 | #define kIOPMSkipAskPowerDown 0x0080 // skip the ask app phase |
512 | #define kIOPMSynchronize 0x0100 // change triggered by power tree re-sync |
513 | #define kIOPMSyncNoChildNotify 0x0200 // sync root domain only, not entire tree |
514 | #define kIOPMSyncTellPowerDown 0x0400 // send the ask/will power off messages |
515 | #define kIOPMSyncCancelPowerDown 0x0800 // sleep cancel for maintenance wake |
516 | #define kIOPMInitialPowerChange 0x1000 // set for initial power change |
517 | #define kIOPMRootChangeUp 0x2000 // Root power domain change up |
518 | #define kIOPMRootChangeDown 0x4000 // Root power domain change down |
519 | #define kIOPMExpireIdleTimer 0x8000 // Accelerate idle timer expiration |
520 | |
521 | #define kIOPMRootBroadcastFlags (kIOPMSynchronize | \ |
522 | kIOPMRootChangeUp | kIOPMRootChangeDown) |
523 | |
524 | // Activity tickle request flags |
525 | #define kTickleTypePowerDrop 0x01 |
526 | #define kTickleTypePowerRise 0x02 |
527 | #define kTickleTypeActivity 0x04 |
528 | #define kTickleTypeAdvisory 0x08 |
529 | |
530 | enum { |
531 | kDriverCallInformPreChange, |
532 | kDriverCallInformPostChange, |
533 | kDriverCallSetPowerState, |
534 | kRootDomainInformPreChange |
535 | }; |
536 | |
537 | struct DriverCallParam { |
538 | OSObject * Target; |
539 | IOReturn Result; |
540 | }; |
541 | |
542 | // values of OutOfBandParameter |
543 | enum { |
544 | kNotifyApps, |
545 | kNotifyPriority, |
546 | kNotifyCapabilityChangeApps, |
547 | kNotifyCapabilityChangePriority |
548 | }; |
549 | |
550 | typedef bool (*IOPMMessageFilter)( |
551 | void * target, void * object, void * arg1, void * arg2, void * arg3 ); |
552 | |
553 | // used for applyToInterested |
554 | struct IOPMInterestContext { |
555 | OSArray * responseArray; |
556 | OSArray * notifyClients; |
557 | uint16_t serialNumber; |
558 | uint8_t isPreChange; |
559 | uint8_t enableTracing; |
560 | uint32_t maxTimeRequested; |
561 | uint32_t messageType; |
562 | uint32_t notifyType; |
563 | uint32_t skippedInDark; |
564 | uint32_t notSkippedInDark; |
565 | IOService * us; |
566 | IOPMPowerStateIndex stateNumber; |
567 | IOPMPowerFlags stateFlags; |
568 | IOPMPowerChangeFlags changeFlags; |
569 | IOPMMessageFilter messageFilter; |
570 | }; |
571 | |
572 | // track client ack requirements |
573 | class IOPMClientAck : public OSObject { |
574 | OSDeclareDefaultStructors( IOPMClientAck ); |
575 | public: |
576 | uint64_t completionTimestamp; // absolute time |
577 | uint32_t maxTimeRequested; // microseconds |
578 | }; |
579 | |
580 | // assertPMDriverCall() options |
581 | enum { |
582 | kIOPMDriverCallNoInactiveCheck = 1 |
583 | }; |
584 | |
585 | // assertPMDriverCall() method |
586 | enum { |
587 | kIOPMDriverCallMethodUnknown = 0, |
588 | kIOPMDriverCallMethodSetPowerState = 1, |
589 | kIOPMDriverCallMethodWillChange = 2, |
590 | kIOPMDriverCallMethodDidChange = 3, |
591 | kIOPMDriverCallMethodChangeDone = 4, |
592 | kIOPMDriverCallMethodSetAggressive = 5 |
593 | }; |
594 | |
595 | //****************************************************************************** |
596 | // PM Statistics & Diagnostics |
597 | //****************************************************************************** |
598 | |
599 | extern OSPtr<const OSSymbol> gIOPMStatsResponseTimedOut; |
600 | extern OSPtr<const OSSymbol> gIOPMStatsResponseCancel; |
601 | extern OSPtr<const OSSymbol> gIOPMStatsResponseSlow; |
602 | extern OSPtr<const OSSymbol> gIOPMStatsResponsePrompt; |
603 | extern OSPtr<const OSSymbol> gIOPMStatsDriverPSChangeSlow; |
604 | |
605 | //****************************************************************************** |
606 | // IOPMRequest |
607 | //****************************************************************************** |
608 | |
609 | class IOPMRequest : public IOCommand |
610 | { |
611 | OSDeclareDefaultStructors( IOPMRequest ); |
612 | |
613 | protected: |
614 | IOService * fTarget; // request target |
615 | IOPMRequest * fRequestNext; // the next request in the chain |
616 | IOPMRequest * fRequestRoot; // the root request in the call tree |
617 | uint32_t fWorkWaitCount; // execution blocked if non-zero |
618 | uint32_t fFreeWaitCount; // completion blocked if non-zero |
619 | uint64_t fTimestamp; // MCTU |
620 | uint32_t fRequestType; // request type |
621 | bool fIsQuiesceBlocker; |
622 | |
623 | IOPMCompletionAction fCompletionAction; |
624 | void * fCompletionTarget; |
625 | void * fCompletionParam; |
626 | |
627 | public: |
628 | uint32_t fTag; |
629 | void * fArg0; |
630 | void * fArg1; |
631 | void * fArg2; |
632 | |
633 | inline bool |
634 | isWorkBlocked( void ) const |
635 | { |
636 | return fWorkWaitCount != 0; |
637 | } |
638 | |
639 | inline bool |
640 | isFreeBlocked( void ) const |
641 | { |
642 | return fFreeWaitCount != 0; |
643 | } |
644 | |
645 | inline IOPMRequest * |
646 | getNextRequest( void ) const |
647 | { |
648 | return fRequestNext; |
649 | } |
650 | |
651 | inline IOPMRequest * |
652 | getRootRequest( void ) const |
653 | { |
654 | if (fRequestRoot) { |
655 | return fRequestRoot; |
656 | } |
657 | #if NOT_READY |
658 | if (fCompletionAction) { |
659 | return (IOPMRequest *) this; |
660 | } |
661 | #endif |
662 | return NULL; |
663 | } |
664 | |
665 | inline uint32_t |
666 | getType( void ) const |
667 | { |
668 | return fRequestType; |
669 | } |
670 | |
671 | inline uint32_t |
672 | getTag( void ) const |
673 | { |
674 | return fTag; |
675 | } |
676 | |
677 | inline bool |
678 | isReplyType( void ) const |
679 | { |
680 | return fRequestType > kIOPMRequestTypeReplyStart; |
681 | } |
682 | |
683 | inline IOService * |
684 | getTarget( void ) const |
685 | { |
686 | return fTarget; |
687 | } |
688 | |
689 | inline bool |
690 | isQuiesceBlocker( void ) const |
691 | { |
692 | return fIsQuiesceBlocker; |
693 | } |
694 | |
695 | inline bool |
696 | isQuiesceType( void ) const |
697 | { |
698 | return (kIOPMRequestTypeQuiescePowerTree == fRequestType) && |
699 | (fCompletionAction != NULL) && (fCompletionTarget != NULL); |
700 | } |
701 | |
702 | inline void |
703 | installCompletionAction( |
704 | void * target, |
705 | IOPMCompletionAction action, |
706 | void * param ) |
707 | { |
708 | fCompletionTarget = target; |
709 | fCompletionAction = action; |
710 | fCompletionParam = param; |
711 | } |
712 | |
713 | inline void |
714 | setTimestamp( uint64_t time ) |
715 | { |
716 | fTimestamp = time; |
717 | } |
718 | |
719 | inline uint64_t |
720 | getTimestamp( void ) const |
721 | { |
722 | return fTimestamp; |
723 | } |
724 | |
725 | static IOPMRequest * create( void ); |
726 | bool init( IOService * owner, IOOptionBits type ); |
727 | void reset( void ); |
728 | bool attachNextRequest( IOPMRequest * next ); |
729 | bool detachNextRequest( void ); |
730 | bool attachRootRequest( IOPMRequest * root ); |
731 | bool detachRootRequest( void ); |
732 | }; |
733 | |
734 | //****************************************************************************** |
735 | // IOPMRequestQueue |
736 | //****************************************************************************** |
737 | |
738 | class IOPMRequestQueue : public IOEventSource |
739 | { |
740 | OSDeclareDefaultStructors( IOPMRequestQueue ); |
741 | |
742 | public: |
743 | typedef bool (*Action)( IOService *, IOPMRequest *, IOPMRequestQueue * ); |
744 | |
745 | protected: |
746 | queue_head_t fQueue; |
747 | IOLock * fLock; |
748 | |
749 | enum { kMaxDequeueCount = 256 }; |
750 | |
751 | virtual bool checkForWork( void ) APPLE_KEXT_OVERRIDE; |
752 | virtual void free( void ) APPLE_KEXT_OVERRIDE; |
753 | virtual bool init( IOService * inOwner, Action inAction ); |
754 | |
755 | public: |
756 | static IOPMRequestQueue * create( IOService * inOwner, Action inAction ); |
757 | void queuePMRequest( LIBKERN_CONSUMED IOPMRequest * request ); |
758 | void queuePMRequestChain( IOPMRequest ** requests, IOItemCount count ); |
759 | }; |
760 | |
761 | //****************************************************************************** |
762 | // IOPMWorkQueue |
763 | //****************************************************************************** |
764 | |
765 | #define WORK_QUEUE_STATS 1 |
766 | |
767 | class IOPMWorkQueue : public IOEventSource |
768 | { |
769 | OSDeclareDefaultStructors( IOPMWorkQueue ); |
770 | |
771 | public: |
772 | typedef bool (*Action)( IOService *, IOPMRequest *, IOPMWorkQueue * ); |
773 | |
774 | #if WORK_QUEUE_STATS |
775 | uint64_t fStatCheckForWork; |
776 | uint64_t fStatScanEntries; |
777 | uint64_t fStatQueueEmpty; |
778 | uint64_t fStatNoWorkDone; |
779 | #endif |
780 | |
781 | protected: |
782 | queue_head_t fWorkQueue; |
783 | Action fInvokeAction; |
784 | Action fRetireAction; |
785 | uint32_t fQueueLength; |
786 | uint32_t fConsumerCount; |
787 | volatile uint32_t fProducerCount; |
788 | IOPMRequest * fQuiesceRequest; |
789 | AbsoluteTime fQuiesceStartTime; |
790 | AbsoluteTime fQuiesceFinishTime; |
791 | |
792 | virtual bool checkForWork( void ) APPLE_KEXT_OVERRIDE; |
793 | virtual bool init( IOService * inOwner, Action invoke, Action retire ); |
794 | bool checkRequestQueue( queue_head_t * queue, bool * empty ); |
795 | |
796 | public: |
797 | static IOPMWorkQueue * create( IOService * inOwner, Action invoke, Action retire ); |
798 | bool queuePMRequest( IOPMRequest * request, IOServicePM * pwrMgt ); |
799 | void signalWorkAvailable( void ); |
800 | void incrementProducerCount( void ); |
801 | void attachQuiesceRequest( IOPMRequest * quiesceRequest ); |
802 | void finishQuiesceRequest( IOPMRequest * quiesceRequest ); |
803 | }; |
804 | |
805 | //****************************************************************************** |
806 | // IOPMCompletionQueue |
807 | //****************************************************************************** |
808 | |
809 | class IOPMCompletionQueue : public IOEventSource |
810 | { |
811 | OSDeclareDefaultStructors( IOPMCompletionQueue ); |
812 | |
813 | public: |
814 | typedef bool (*Action)( IOService *, IOPMRequest *, IOPMCompletionQueue * ); |
815 | |
816 | protected: |
817 | queue_head_t fQueue; |
818 | |
819 | virtual bool checkForWork( void ) APPLE_KEXT_OVERRIDE; |
820 | virtual bool init( IOService * inOwner, Action inAction ); |
821 | |
822 | public: |
823 | static IOPMCompletionQueue * create( IOService * inOwner, Action inAction ); |
824 | bool queuePMRequest( IOPMRequest * request ); |
825 | }; |
826 | |
827 | #endif /* !_IOKIT_IOSERVICEPMPRIVATE_H */ |
828 | |