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