]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (c) 2007 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 | /*! @class IOServicePM | |
33 | @abstract Power management class. | |
34 | */ | |
35 | class IOServicePM : public OSObject | |
36 | { | |
37 | friend class IOService; | |
38 | ||
39 | OSDeclareDefaultStructors( IOServicePM ) | |
40 | ||
41 | private: | |
42 | // List of interested drivers. | |
43 | IOPMinformeeList * InterestedDrivers; | |
44 | ||
45 | // How long to wait for controlling driver to acknowledge. | |
46 | IOReturn DriverTimer; | |
47 | ||
48 | // Current power management machine state. | |
49 | uint32_t MachineState; | |
50 | ||
51 | thread_call_t AckTimer; | |
52 | thread_call_t SettleTimer; | |
53 | ||
54 | // Settle time after changing power state. | |
55 | unsigned long SettleTimeUS; | |
56 | ||
57 | // The flags describing current change note. | |
58 | unsigned long HeadNoteFlags; | |
59 | ||
60 | // The new power state number being changed to. | |
61 | unsigned long HeadNotePowerState; | |
62 | ||
63 | // Points to the entry in the power state array. | |
64 | IOPMPowerState * HeadNotePowerArrayEntry; | |
65 | ||
66 | // Power flags supplied by all parents (domain). | |
67 | unsigned long HeadNoteDomainFlags; | |
68 | ||
69 | // Power flags supplied by domain accounting for parent changes. | |
70 | IOPMPowerFlags HeadNoteDomainTargetFlags; | |
71 | ||
72 | // Connection attached to the changing parent. | |
73 | IOPowerConnection * HeadNoteParentConnection; | |
74 | ||
75 | // Power flags supplied by the changing parent. | |
76 | unsigned long HeadNoteParentFlags; | |
77 | ||
78 | // Number of acks still outstanding. | |
79 | unsigned long HeadNotePendingAcks; | |
80 | ||
81 | // PM state lock. | |
82 | IOLock * PMLock; | |
83 | ||
84 | // Initialized to true, then set to false after the initial power change. | |
85 | bool InitialChange; | |
86 | ||
87 | // Ignore children and driver desires if true. | |
88 | bool DeviceOverrides; | |
89 | ||
90 | // True if device was active since last idle timer expiration. | |
91 | bool DeviceActive; | |
92 | ||
93 | // Keeps track of any negative responses from notified apps and clients. | |
94 | bool DoNotPowerDown; | |
95 | ||
96 | // True if all our parents know the state of their power domain. | |
97 | bool ParentsKnowState; | |
98 | ||
99 | bool StrictTreeOrder; | |
100 | bool IdleTimerStopped; | |
101 | bool AdjustPowerScheduled; | |
102 | ||
103 | // Time of last device activity. | |
104 | AbsoluteTime DeviceActiveTimestamp; | |
105 | ||
106 | // Used to protect activity flag. | |
107 | IOLock * ActivityLock; | |
108 | ||
109 | // Idle timer event source. | |
110 | IOTimerEventSource * IdleTimerEventSource; | |
111 | ||
112 | // Idle timer's period in seconds. | |
113 | unsigned long IdleTimerPeriod; | |
114 | unsigned long IdleTimerMinPowerState; | |
115 | AbsoluteTime IdleTimerStartTime; | |
116 | ||
117 | // Power state desired by a subclassed device object. | |
118 | unsigned long DeviceDesire; | |
119 | ||
120 | // This is the power state we desire currently. | |
121 | unsigned long DesiredPowerState; | |
122 | ||
123 | // This is what our parent thinks our need is. | |
124 | unsigned long PreviousRequest; | |
125 | ||
126 | // Cache result from getName(), used in logging. | |
127 | const char * Name; | |
128 | ||
129 | // Number of power states in the power array. | |
130 | unsigned long NumberOfPowerStates; | |
131 | ||
132 | // Power state array. | |
133 | IOPMPowerState * PowerStates; | |
134 | ||
135 | // The controlling driver. | |
136 | IOService * ControllingDriver; | |
137 | ||
138 | // Our current power state. | |
139 | unsigned long CurrentPowerState; | |
140 | ||
141 | // Logical OR of power flags for each power domain parent. | |
142 | IOPMPowerFlags ParentsCurrentPowerFlags; | |
143 | ||
144 | // The highest power state we can achieve in current power domain. | |
145 | unsigned long MaxCapability; | |
146 | ||
147 | // Logical OR of all output power character flags in the array. | |
148 | IOPMPowerFlags OutputPowerCharacterFlags; | |
149 | ||
150 | // OSArray which manages responses from notified apps and clients. | |
151 | OSArray * ResponseArray; | |
152 | OSArray * NotifyClientArray; | |
153 | ||
154 | // Used to uniquely identify power management notification to apps and clients. | |
155 | UInt16 SerialNumber; | |
156 | ||
157 | // Used to communicate desired function to tellClientsWithResponse(). | |
158 | // This is used because it avoids changing the signatures of the affected virtual methods. | |
159 | int OutOfBandParameter; | |
160 | ||
161 | AbsoluteTime DriverCallStartTime; | |
162 | IOPMPowerFlags CurrentCapabilityFlags; | |
163 | long ActivityTicklePowerState; | |
164 | unsigned long CurrentPowerConsumption; | |
165 | unsigned long TempClampPowerState; | |
166 | IOPMWorkQueue * PMWorkQueue; | |
167 | OSSet * InsertInterestSet; | |
168 | OSSet * RemoveInterestSet; | |
169 | OSArray * NotifyChildArray; | |
170 | OSDictionary * PowerClients; | |
171 | thread_call_t DriverCallEntry; | |
172 | void * DriverCallParamPtr; | |
173 | IOItemCount DriverCallParamCount; | |
174 | IOItemCount DriverCallParamSlots; | |
175 | uint32_t DriverCallReason; | |
176 | uint32_t TempClampCount; | |
177 | uint32_t OverrideMaxPowerState; | |
178 | uint32_t ActivityTickleCount; | |
179 | uint32_t WaitReason; | |
180 | uint32_t NextMachineState; | |
181 | uint32_t RootDomainState; | |
182 | uint32_t ThreadAssertionCount; | |
183 | ||
184 | // Protected by PMLock | |
185 | struct { | |
186 | uint32_t DriverCallBusy : 1; | |
187 | uint32_t PMStop : 1; | |
188 | } LockedFlags; | |
189 | ||
190 | thread_t ThreadAssertionThread; | |
191 | ||
192 | #if PM_VARS_SUPPORT | |
193 | IOPMprot * PMVars; | |
194 | #endif | |
195 | ||
196 | // Serialize IOServicePM state for debug output. | |
197 | IOReturn gatedSerialize( OSSerialize * s ); | |
198 | virtual bool serialize( OSSerialize * s ) const; | |
199 | }; | |
200 | ||
201 | #define fInterestedDrivers pwrMgt->InterestedDrivers | |
202 | #define fDriverTimer pwrMgt->DriverTimer | |
203 | #define fAckTimer pwrMgt->AckTimer | |
204 | #define fSettleTimer pwrMgt->SettleTimer | |
205 | #define fMachineState pwrMgt->MachineState | |
206 | #define fSettleTimeUS pwrMgt->SettleTimeUS | |
207 | #define fHeadNoteFlags pwrMgt->HeadNoteFlags | |
208 | #define fHeadNotePowerState pwrMgt->HeadNotePowerState | |
209 | #define fHeadNotePowerArrayEntry pwrMgt->HeadNotePowerArrayEntry | |
210 | #define fHeadNoteDomainFlags pwrMgt->HeadNoteDomainFlags | |
211 | #define fHeadNoteDomainTargetFlags pwrMgt->HeadNoteDomainTargetFlags | |
212 | #define fHeadNoteParentConnection pwrMgt->HeadNoteParentConnection | |
213 | #define fHeadNoteParentFlags pwrMgt->HeadNoteParentFlags | |
214 | #define fHeadNotePendingAcks pwrMgt->HeadNotePendingAcks | |
215 | #define fPMLock pwrMgt->PMLock | |
216 | #define fInitialChange pwrMgt->InitialChange | |
217 | #define fDeviceOverrides pwrMgt->DeviceOverrides | |
218 | #define fActivityLock pwrMgt->ActivityLock | |
219 | #define fIdleTimerEventSource pwrMgt->IdleTimerEventSource | |
220 | #define fIdleTimerPeriod pwrMgt->IdleTimerPeriod | |
221 | #define fIdleTimerMinPowerState pwrMgt->IdleTimerMinPowerState | |
222 | #define fDeviceActive pwrMgt->DeviceActive | |
223 | #define fIdleTimerStartTime pwrMgt->IdleTimerStartTime | |
224 | #define fDeviceActiveTimestamp pwrMgt->DeviceActiveTimestamp | |
225 | #define fActivityTickleCount pwrMgt->ActivityTickleCount | |
226 | #define fDeviceDesire pwrMgt->DeviceDesire | |
227 | #define fDesiredPowerState pwrMgt->DesiredPowerState | |
228 | #define fPreviousRequest pwrMgt->PreviousRequest | |
229 | #define fName pwrMgt->Name | |
230 | #define fNumberOfPowerStates pwrMgt->NumberOfPowerStates | |
231 | #define fPowerStates pwrMgt->PowerStates | |
232 | #define fControllingDriver pwrMgt->ControllingDriver | |
233 | #define fAggressivenessValue pwrMgt->AggressivenessValue | |
234 | #define fAggressivenessValid pwrMgt->AggressivenessValid | |
235 | #define fCurrentPowerState pwrMgt->CurrentPowerState | |
236 | #define fParentsKnowState pwrMgt->ParentsKnowState | |
237 | #define fParentsCurrentPowerFlags pwrMgt->ParentsCurrentPowerFlags | |
238 | #define fMaxCapability pwrMgt->MaxCapability | |
239 | #define fOutputPowerCharacterFlags pwrMgt->OutputPowerCharacterFlags | |
240 | #define fSerialNumber pwrMgt->SerialNumber | |
241 | #define fResponseArray pwrMgt->ResponseArray | |
242 | #define fNotifyClientArray pwrMgt->NotifyClientArray | |
243 | #define fDoNotPowerDown pwrMgt->DoNotPowerDown | |
244 | #define fOutOfBandParameter pwrMgt->OutOfBandParameter | |
245 | #define fDriverCallStartTime pwrMgt->DriverCallStartTime | |
246 | #define fCurrentCapabilityFlags pwrMgt->CurrentCapabilityFlags | |
247 | #define fCurrentPowerConsumption pwrMgt->CurrentPowerConsumption | |
248 | #define fTempClampPowerState pwrMgt->TempClampPowerState | |
249 | #define fTempClampCount pwrMgt->TempClampCount | |
250 | #define fOverrideMaxPowerState pwrMgt->OverrideMaxPowerState | |
251 | #define fPMWorkQueue pwrMgt->PMWorkQueue | |
252 | #define fWaitReason pwrMgt->WaitReason | |
253 | #define fNextMachineState pwrMgt->NextMachineState | |
254 | #define fDriverCallReason pwrMgt->DriverCallReason | |
255 | #define fDriverCallEntry pwrMgt->DriverCallEntry | |
256 | #define fDriverCallParamPtr pwrMgt->DriverCallParamPtr | |
257 | #define fDriverCallParamCount pwrMgt->DriverCallParamCount | |
258 | #define fDriverCallParamSlots pwrMgt->DriverCallParamSlots | |
259 | #define fActivityTickled pwrMgt->ActivityTickled | |
260 | #define fInsertInterestSet pwrMgt->InsertInterestSet | |
261 | #define fRemoveInterestSet pwrMgt->RemoveInterestSet | |
262 | #define fStrictTreeOrder pwrMgt->StrictTreeOrder | |
263 | #define fNotifyChildArray pwrMgt->NotifyChildArray | |
264 | #define fIdleTimerStopped pwrMgt->IdleTimerStopped | |
265 | #define fAdjustPowerScheduled pwrMgt->AdjustPowerScheduled | |
266 | #define fActivityTicklePowerState pwrMgt->ActivityTicklePowerState | |
267 | #define fPMVars pwrMgt->PMVars | |
268 | #define fPowerClients pwrMgt->PowerClients | |
269 | #define fRootDomainState pwrMgt->RootDomainState | |
270 | #define fThreadAssertionCount pwrMgt->ThreadAssertionCount | |
271 | #define fThreadAssertionThread pwrMgt->ThreadAssertionThread | |
272 | #define fLockedFlags pwrMgt->LockedFlags | |
273 | ||
274 | /* | |
275 | When an IOService is waiting for acknowledgement to a power change | |
276 | notification from an interested driver or the controlling driver, | |
277 | the ack timer is ticking every tenth of a second. | |
278 | (100000000 nanoseconds are one tenth of a second). | |
279 | */ | |
280 | #define ACK_TIMER_PERIOD 100000000 | |
281 | ||
282 | #define kIOPMParentInitiated 0x01 // this power change initiated by our parent | |
283 | #define kIOPMWeInitiated 0x02 // this power change initiated by this device | |
284 | #define kIOPMNotDone 0x04 // we couldn't make this change | |
285 | #define kIOPMDomainWillChange 0x08 // change started by PowerDomainWillChangeTo | |
286 | #define kIOPMDomainDidChange 0x10 // change started by PowerDomainDidChangeTo | |
287 | #define kIOPMDomainPowerDrop 0x20 // Domain is lowering power | |
288 | #define kIOPMSynchronize 0x40 // change triggered by power tree re-sync | |
289 | ||
290 | enum { | |
291 | kDriverCallInformPreChange, | |
292 | kDriverCallInformPostChange, | |
293 | kDriverCallSetPowerState | |
294 | }; | |
295 | ||
296 | struct DriverCallParam { | |
297 | OSObject * Target; | |
298 | IOReturn Result; | |
299 | }; | |
300 | ||
301 | // values of outofbandparameter | |
302 | enum { | |
303 | kNotifyApps, | |
304 | kNotifyPriority | |
305 | }; | |
306 | ||
307 | typedef bool (*IOPMMessageFilter)(OSObject * object, void * context); | |
308 | ||
309 | // used for applyToInterested | |
310 | struct IOPMInterestContext { | |
311 | OSArray * responseFlags; | |
312 | OSArray * notifyClients; | |
313 | UInt16 serialNumber; | |
314 | UInt16 counter; | |
315 | UInt32 maxTimeRequested; | |
316 | int msgType; | |
317 | IOService * us; | |
318 | unsigned long stateNumber; | |
319 | IOPMPowerFlags stateFlags; | |
320 | const char * errorLog; | |
321 | IOPMMessageFilter filterFunc; | |
322 | }; | |
323 | ||
324 | //********************************************************************************* | |
325 | // PM Statistics & Diagnostics | |
326 | //********************************************************************************* | |
327 | ||
328 | extern const OSSymbol *gIOPMStatsApplicationResponseTimedOut; | |
329 | extern const OSSymbol *gIOPMStatsApplicationResponseCancel; | |
330 | extern const OSSymbol *gIOPMStatsApplicationResponseSlow; | |
331 | ||
332 | //********************************************************************************* | |
333 | // PM command types | |
334 | //********************************************************************************* | |
335 | ||
336 | enum { | |
337 | /* Command Types */ | |
338 | kIOPMRequestTypeInvalid = 0x00, | |
339 | kIOPMRequestTypePMStop = 0x01, | |
340 | kIOPMRequestTypeAddPowerChild1 = 0x02, | |
341 | kIOPMRequestTypeAddPowerChild2 = 0x03, | |
342 | kIOPMRequestTypeAddPowerChild3 = 0x04, | |
343 | kIOPMRequestTypeRegisterPowerDriver = 0x05, | |
344 | kIOPMRequestTypeAdjustPowerState = 0x06, | |
345 | kIOPMRequestTypePowerDomainWillChange = 0x07, | |
346 | kIOPMRequestTypePowerDomainDidChange = 0x08, | |
347 | kIOPMRequestTypePowerOverrideOnPriv = 0x09, | |
348 | kIOPMRequestTypePowerOverrideOffPriv = 0x0A, | |
349 | kIOPMRequestTypeActivityTickle = 0x0B, | |
350 | kIOPMRequestTypeRequestPowerState = 0x0C, | |
351 | kIOPMRequestTypeSynchronizePowerTree = 0x0D, | |
352 | kIOPMRequestTypeRequestPowerStateOverride = 0x0E, | |
353 | kIOPMRequestTypeSetIdleTimerPeriod = 0x0F, | |
354 | ||
355 | /* Reply Types */ | |
356 | kIOPMRequestTypeReplyStart = 0x80, | |
357 | kIOPMRequestTypeAckPowerChange = 0x81, | |
358 | kIOPMRequestTypeAckSetPowerState = 0x82, | |
359 | kIOPMRequestTypeAllowPowerChange = 0x83, | |
360 | kIOPMRequestTypeCancelPowerChange = 0x84, | |
361 | kIOPMRequestTypeInterestChanged = 0x85, | |
362 | kIOPMRequestTypeIdleCancel = 0x86 | |
363 | }; | |
364 | ||
365 | //********************************************************************************* | |
366 | // IOServicePM internal helper classes | |
367 | //********************************************************************************* | |
368 | ||
369 | typedef void (*IOPMCompletionAction)(void * target, void * param, IOReturn status); | |
370 | ||
371 | class IOPMRequest : public IOCommand | |
372 | { | |
373 | OSDeclareDefaultStructors( IOPMRequest ) | |
374 | ||
375 | protected: | |
376 | IOService * fTarget; // request target | |
377 | IOPMRequest * fRequestNext; // the next request in the chain | |
378 | IOPMRequest * fRequestRoot; // the root request in the issue tree | |
379 | IOItemCount fWorkWaitCount; // execution blocked if non-zero | |
380 | IOItemCount fFreeWaitCount; // completion blocked if non-zero | |
381 | uint32_t fType; // request type | |
382 | ||
383 | IOPMCompletionAction fCompletionAction; | |
384 | void * fCompletionTarget; | |
385 | void * fCompletionParam; | |
386 | IOReturn fCompletionStatus; | |
387 | ||
388 | public: | |
389 | void * fArg0; | |
390 | void * fArg1; | |
391 | void * fArg2; | |
392 | ||
393 | inline bool isWorkBlocked( void ) const | |
394 | { | |
395 | return (fWorkWaitCount != 0); | |
396 | } | |
397 | ||
398 | inline bool isFreeBlocked( void ) const | |
399 | { | |
400 | return (fFreeWaitCount != 0); | |
401 | } | |
402 | ||
403 | inline IOPMRequest * getNextRequest( void ) const | |
404 | { | |
405 | return fRequestNext; | |
406 | } | |
407 | ||
408 | inline IOPMRequest * getRootRequest( void ) const | |
409 | { | |
410 | if (fRequestRoot) return fRequestRoot; | |
411 | if (fCompletionAction) return (IOPMRequest *) this; | |
412 | return 0; | |
413 | } | |
414 | ||
415 | inline uint32_t getType( void ) const | |
416 | { | |
417 | return fType; | |
418 | } | |
419 | ||
420 | inline bool isReplyType( void ) const | |
421 | { | |
422 | return (fType > kIOPMRequestTypeReplyStart); | |
423 | } | |
424 | ||
425 | inline IOService * getTarget( void ) const | |
426 | { | |
427 | return fTarget; | |
428 | } | |
429 | ||
430 | inline bool isCompletionInstalled( void ) | |
431 | { | |
432 | return (fCompletionAction != 0); | |
433 | } | |
434 | ||
435 | inline void installCompletionAction( | |
436 | IOPMCompletionAction action, | |
437 | void * target, | |
438 | void * param ) | |
439 | { | |
440 | fCompletionAction = action; | |
441 | fCompletionTarget = target; | |
442 | fCompletionParam = param; | |
443 | } | |
444 | ||
445 | static IOPMRequest * create( void ); | |
446 | bool init( IOService * owner, IOOptionBits type ); | |
447 | void reset( void ); | |
448 | void attachNextRequest( IOPMRequest * next ); | |
449 | void detachNextRequest( void ); | |
450 | void attachRootRequest( IOPMRequest * root ); | |
451 | void detachRootRequest( void ); | |
452 | }; | |
453 | ||
454 | class IOPMRequestQueue : public IOEventSource | |
455 | { | |
456 | OSDeclareDefaultStructors( IOPMRequestQueue ) | |
457 | ||
458 | public: | |
459 | typedef bool (*Action)( IOService *, IOPMRequest *, IOPMRequestQueue * ); | |
460 | ||
461 | protected: | |
462 | queue_head_t fQueue; | |
463 | IOLock * fLock; | |
464 | ||
465 | virtual bool checkForWork( void ); | |
466 | virtual void free( void ); | |
467 | virtual bool init( IOService * inOwner, Action inAction ); | |
468 | ||
469 | public: | |
470 | static IOPMRequestQueue * create( IOService * inOwner, Action inAction ); | |
471 | void queuePMRequest( IOPMRequest * request ); | |
472 | void queuePMRequestChain( IOPMRequest ** requests, IOItemCount count ); | |
473 | void signalWorkAvailable( void ); | |
474 | }; | |
475 | ||
476 | class IOPMWorkQueue : public IOEventSource | |
477 | { | |
478 | OSDeclareDefaultStructors( IOPMWorkQueue ) | |
479 | ||
480 | public: | |
481 | typedef bool (*Action)( IOService *, IOPMRequest *, IOPMWorkQueue * ); | |
482 | ||
483 | protected: | |
484 | queue_head_t fWorkQueue; | |
485 | Action fWorkAction; | |
486 | Action fRetireAction; | |
487 | ||
488 | virtual bool checkForWork( void ); | |
489 | virtual bool init( IOService * inOwner, Action work, Action retire ); | |
490 | ||
491 | public: | |
492 | static IOPMWorkQueue * create( IOService * inOwner, Action work, Action retire ); | |
493 | void queuePMRequest( IOPMRequest * request ); | |
494 | }; | |
495 | ||
496 | class IOPMCompletionQueue : public IOEventSource | |
497 | { | |
498 | OSDeclareDefaultStructors( IOPMCompletionQueue ) | |
499 | ||
500 | public: | |
501 | typedef bool (*Action)( IOService *, IOPMRequest *, IOPMCompletionQueue * ); | |
502 | ||
503 | protected: | |
504 | queue_head_t fQueue; | |
505 | ||
506 | virtual bool checkForWork( void ); | |
507 | virtual bool init( IOService * inOwner, Action inAction ); | |
508 | ||
509 | public: | |
510 | static IOPMCompletionQueue * create( IOService * inOwner, Action inAction ); | |
511 | void queuePMRequest( IOPMRequest * request ); | |
512 | }; | |
513 | ||
514 | #endif /* !_IOKIT_IOSERVICEPMPRIVATE_H */ |