Loading...
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
/*
 * Copyright (c) 2019 Apple Inc. All rights reserved.
 *
 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
 *
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Apple Public Source License
 * Version 2.0 (the 'License'). You may not use this file except in
 * compliance with the License. The rights granted to you under the License
 * may not be used to create, or enable the creation or redistribution of,
 * unlawful or unlicensed copies of an Apple operating system, or to
 * circumvent, violate, or enable the circumvention or violation of, any
 * terms of an Apple operating system software license agreement.
 *
 * Please obtain a copy of the License at
 * http://www.opensource.apple.com/apsl/ and read it before using this file.
 *
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 * Please see the License for the specific language governing rights and
 * limitations under the License.
 *
 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
 */

#ifndef _IOKIT_IOSERVICEPMPRIVATE_H
#define _IOKIT_IOSERVICEPMPRIVATE_H

#include <IOKit/IOCommand.h>
#include <IOKit/IOEventSource.h>

//******************************************************************************
// PM command types
//******************************************************************************

enum {
	/* Command Types */
	kIOPMRequestTypeInvalid                     = 0x00,
	kIOPMRequestTypePMStop                      = 0x01,
	kIOPMRequestTypeAddPowerChild1              = 0x02,
	kIOPMRequestTypeAddPowerChild2              = 0x03,
	kIOPMRequestTypeAddPowerChild3              = 0x04,
	kIOPMRequestTypeRegisterPowerDriver         = 0x05,
	kIOPMRequestTypeAdjustPowerState            = 0x06,
	kIOPMRequestTypePowerDomainWillChange       = 0x07,
	kIOPMRequestTypePowerDomainDidChange        = 0x08,
	kIOPMRequestTypePowerOverrideOnPriv         = 0x09,
	kIOPMRequestTypePowerOverrideOffPriv        = 0x0A,
	kIOPMRequestTypeActivityTickle              = 0x0B,
	kIOPMRequestTypeRequestPowerState           = 0x0C,
	kIOPMRequestTypeSynchronizePowerTree        = 0x0D,
	kIOPMRequestTypeRequestPowerStateOverride   = 0x0E,
	kIOPMRequestTypeSetIdleTimerPeriod          = 0x0F,
	kIOPMRequestTypeIgnoreIdleTimer             = 0x10,
	kIOPMRequestTypeQuiescePowerTree            = 0x11,

	/* Reply Types */
	kIOPMRequestTypeReplyStart                  = 0x80,
	kIOPMRequestTypeAckPowerChange              = 0x81,
	kIOPMRequestTypeAckSetPowerState            = 0x82,
	kIOPMRequestTypeAllowPowerChange            = 0x83,
	kIOPMRequestTypeCancelPowerChange           = 0x84,
	kIOPMRequestTypeInterestChanged             = 0x85,
	kIOPMRequestTypeIdleCancel                  = 0x86,
	kIOPMRequestTypeChildNotifyDelayCancel      = 0x87
};

//******************************************************************************
// PM actions - For root domain only
//******************************************************************************

struct IOPMActions;

typedef void
(*IOPMActionPowerChangeStart)(
	void *                  target,
	IOService *             service,
	IOPMActions *           actions,
	IOPMPowerStateIndex     powerState,
	IOPMPowerChangeFlags *  changeFlags,
	IOPMRequestTag          requestTag );

typedef void
(*IOPMActionPowerChangeDone)(
	void *                  target,
	IOService *             service,
	IOPMActions *           actions,
	IOPMPowerStateIndex     powerState,
	IOPMPowerChangeFlags    changeFlags,
	IOPMRequestTag          requestTag );

typedef void
(*IOPMActionPowerChangeOverride)(
	void *                  target,
	IOService *             service,
	IOPMActions *           actions,
	IOPMPowerStateIndex *   powerState,
	IOPMPowerChangeFlags *  changeFlags,
	IOPMRequestTag          requestTag );

typedef void
(*IOPMActionActivityTickle)(
	void *                  target,
	IOService *             service,
	IOPMActions *           actions );

typedef void
(*IOPMActionUpdatePowerClient)(
	void *                  target,
	IOService *             service,
	IOPMActions *           actions,
	const OSSymbol *        powerClient,
	IOPMPowerStateIndex     oldPowerState,
	IOPMPowerStateIndex     newPowerState
	);

struct IOPMActions {
	void *                          target;
	uint32_t                        parameter;
	IOPMActionPowerChangeStart      actionPowerChangeStart;
	IOPMActionPowerChangeDone       actionPowerChangeDone;
	IOPMActionPowerChangeOverride   actionPowerChangeOverride;
	IOPMActionActivityTickle        actionActivityTickle;
	IOPMActionUpdatePowerClient     actionUpdatePowerClient;
};

// IOPMActions parameter flags
enum {
	kPMActionsFlagIsDisplayWrangler = 0x00000100,
	kPMActionsFlagIsGraphicsDevice  = 0x00000200,
	kPMActionsFlagIsAudioDevice     = 0x00000400,
	kPMActionsFlagLimitPower        = 0x00000800,
	kPMActionsPCIBitNumberMask      = 0x000000ff
};

//******************************************************************************
// Internal concise representation of IOPMPowerState
struct IOPMPSEntry {
	IOPMPowerFlags      capabilityFlags;
	IOPMPowerFlags      outputPowerFlags;
	IOPMPowerFlags      inputPowerFlags;
	uint32_t            staticPower;
	uint32_t            settleUpTime;
	uint32_t            settleDownTime;
	IOPMPowerStateIndex stateOrder;
	IOPMPowerStateIndex stateOrderToIndex;
};

//******************************************************************************
// IOServicePM
//******************************************************************************

class IOServicePM : public OSObject
{
	friend class IOService;
	friend class IOPMWorkQueue;

	OSDeclareDefaultStructors( IOServicePM );

private:
// Link IOServicePM objects on IOPMWorkQueue.
	queue_chain_t           WorkChain;

// Queue of IOPMRequest objects.
	queue_head_t            RequestHead;

// IOService creator and owner.
	IOService *             Owner;

// List of interested drivers (protected by PMLock).
	IOPMinformeeList *      InterestedDrivers;

// How long to wait for controlling driver to acknowledge.
	IOReturn                DriverTimer;

// Current power management machine state.
	uint32_t                MachineState;

	thread_call_t           AckTimer;
	thread_call_t           SettleTimer;
	thread_call_t           IdleTimer;
	thread_call_t           WatchdogTimer;
	thread_call_t           SpinDumpTimer;

	IOLock  *               WatchdogLock;
	OSArray *               BlockedArray;
	uint64_t                PendingResponseDeadline;
	uint64_t                WatchdogDeadline;

// Settle time after changing power state.
	uint32_t                SettleTimeUS;
	uint32_t                IdleTimerGeneration;

// The flags describing current change note.
	IOPMPowerChangeFlags    HeadNoteChangeFlags;

// The new power state number being changed to.
	IOPMPowerStateIndex     HeadNotePowerState;

// Points to the entry in the power state array.
	IOPMPSEntry *           HeadNotePowerArrayEntry;

// Power flags supplied by all parents (domain).
	IOPMPowerFlags          HeadNoteDomainFlags;

// Power flags supplied by domain accounting for parent changes.
	IOPMPowerFlags          HeadNoteDomainTargetFlags;

// Connection attached to the changing parent.
	IOPowerConnection *     HeadNoteParentConnection;

// Power flags supplied by the changing parent.
	IOPMPowerFlags          HeadNoteParentFlags;

// Number of acks still outstanding.
	uint32_t                HeadNotePendingAcks;

// PM state lock.
	IOLock *                PMLock;

	unsigned int            InitialPowerChange          :1;
	unsigned int            InitialSetPowerState        :1;
	unsigned int            DeviceOverrideEnabled       :1;
	unsigned int            DoNotPowerDown              :1;
	unsigned int            ParentsKnowState            :1;
	unsigned int            StrictTreeOrder             :1;
	unsigned int            IdleTimerStopped            :1;
	unsigned int            AdjustPowerScheduled        :1;

	unsigned int            IsPreChange                 :1;
	unsigned int            DriverCallBusy              :1;
	unsigned int            PCDFunctionOverride         :1;
	unsigned int            IdleTimerIgnored            :1;
	unsigned int            HasAdvisoryDesire           :1;
	unsigned int            AdvisoryTickleUsed          :1;
	unsigned int            ResetPowerStateOnWake       :1;

// Time of last device activity.
	AbsoluteTime            DeviceActiveTimestamp;
	AbsoluteTime            MaxPowerStateEntryTime;
	AbsoluteTime            MaxPowerStateExitTime;

// Used to protect activity flag.
	IOLock *                ActivityLock;

// Idle timer's period in seconds.
	unsigned long           IdleTimerPeriod;
	unsigned long           IdleTimerMinPowerState;
	unsigned long           NextIdleTimerPeriod;
	AbsoluteTime            IdleTimerStartTime;

// Power state desired by a subclassed device object.
	IOPMPowerStateIndex     DeviceDesire;

// This is the power state we desire currently.
	IOPMPowerStateIndex     DesiredPowerState;

// This is what our parent thinks our need is.
	IOPMPowerFlags          PreviousRequestPowerFlags;

// Cache result from getName(), used in logging.
	const char *            Name;

// Number of power states in the power array.
	IOPMPowerStateIndex     NumberOfPowerStates;

// Ordered highest power state in the power array.
	IOPMPowerStateIndex     HighestPowerState;

// Power state array.
	IOPMPSEntry *           PowerStates;

// The controlling driver.
	IOService *             ControllingDriver;

// Our current power state.
	IOPMPowerStateIndex     CurrentPowerState;

// Logical OR of power flags for each power domain parent.
	IOPMPowerFlags          ParentsCurrentPowerFlags;

// The highest power state we can achieve in current power domain.
	IOPMPowerStateIndex     MaxPowerState;

// Logical OR of all output power flags in the power state array.
	IOPMPowerFlags          MergedOutputPowerFlags;

// OSArray which manages responses from notified apps and clients.
	OSArray *               ResponseArray;
	OSArray *               NotifyClientArray;

// Used to uniquely identify power management notification to apps and clients.
	UInt16                  SerialNumber;

// Used to communicate desired function to tellClientsWithResponse().
// This is used because it avoids changing the signatures of the affected virtual methods.
	int                     OutOfBandParameter;

	AbsoluteTime            DriverCallStartTime;
	IOPMPowerFlags          CurrentCapabilityFlags;
	unsigned long           CurrentPowerConsumption;
	IOPMPowerStateIndex     TempClampPowerState;
	OSArray *               NotifyChildArray;
	OSDictionary *          PowerClients;
	thread_call_t           DriverCallEntry;
	void *                  DriverCallParamPtr;
	IOItemCount             DriverCallParamCount;
	IOItemCount             DriverCallParamSlots;
	uint32_t                DriverCallReason;
	uint32_t                OutOfBandMessage;
	uint32_t                TempClampCount;
	uint32_t                OverrideMaxPowerState;
	uint32_t                DeviceUsablePowerState;

// Protected by ActivityLock - BEGIN
	IOPMPowerStateIndex     ActivityTicklePowerState;
	IOPMPowerStateIndex     AdvisoryTicklePowerState;
	uint32_t                ActivityTickleCount;
	uint32_t                DeviceWasActive     : 1;
	uint32_t                AdvisoryTickled     : 1;
// Protected by ActivityLock - END

	uint32_t                WaitReason;
	uint32_t                SavedMachineState;

// Protected by PMLock - BEGIN
	struct {
		uint32_t            PMStop              : 1;
		uint32_t            PMDriverCallWait    : 1;
	} LockedFlags;

	queue_head_t            PMDriverCallQueue;
	OSSet *                 InsertInterestSet;
	OSSet *                 RemoveInterestSet;

// IOReporter Data
	uint32_t                ReportClientCnt;
	void *                  ReportBuf;
// Protected by PMLock - END

#if PM_VARS_SUPPORT
	IOPMprot *              PMVars;
#endif

	IOPMActions             PMActions;

// Serialize IOServicePM state for debug output.
	IOReturn gatedSerialize( OSSerialize * s ) const;
	virtual bool serialize( OSSerialize * s ) const APPLE_KEXT_OVERRIDE;

// PM log and trace
	void pmPrint( uint32_t event, uintptr_t param1, uintptr_t param2 ) const;
	void pmTrace( uint32_t event, uint32_t eventFunc, uintptr_t param1, uintptr_t param2 ) const;
};

#define fOwner                      pwrMgt->Owner
#define fInterestedDrivers          pwrMgt->InterestedDrivers
#define fDriverTimer                pwrMgt->DriverTimer
#define fMachineState               pwrMgt->MachineState
#define fAckTimer                   pwrMgt->AckTimer
#define fSettleTimer                pwrMgt->SettleTimer
#define fIdleTimer                  pwrMgt->IdleTimer
#define fWatchdogTimer              pwrMgt->WatchdogTimer
#define fWatchdogDeadline           pwrMgt->WatchdogDeadline
#define fWatchdogLock               pwrMgt->WatchdogLock
#define fBlockedArray               pwrMgt->BlockedArray
#define fPendingResponseDeadline    pwrMgt->PendingResponseDeadline
#define fSettleTimeUS               pwrMgt->SettleTimeUS
#define fIdleTimerGeneration        pwrMgt->IdleTimerGeneration
#define fHeadNoteChangeFlags        pwrMgt->HeadNoteChangeFlags
#define fHeadNotePowerState         pwrMgt->HeadNotePowerState
#define fHeadNotePowerArrayEntry    pwrMgt->HeadNotePowerArrayEntry
#define fHeadNoteDomainFlags        pwrMgt->HeadNoteDomainFlags
#define fHeadNoteDomainTargetFlags  pwrMgt->HeadNoteDomainTargetFlags
#define fHeadNoteParentConnection   pwrMgt->HeadNoteParentConnection
#define fHeadNoteParentFlags        pwrMgt->HeadNoteParentFlags
#define fHeadNotePendingAcks        pwrMgt->HeadNotePendingAcks
#define fPMLock                     pwrMgt->PMLock
#define fInitialPowerChange         pwrMgt->InitialPowerChange
#define fInitialSetPowerState       pwrMgt->InitialSetPowerState
#define fDeviceOverrideEnabled      pwrMgt->DeviceOverrideEnabled
#define fDoNotPowerDown             pwrMgt->DoNotPowerDown
#define fParentsKnowState           pwrMgt->ParentsKnowState
#define fStrictTreeOrder            pwrMgt->StrictTreeOrder
#define fIdleTimerStopped           pwrMgt->IdleTimerStopped
#define fAdjustPowerScheduled       pwrMgt->AdjustPowerScheduled
#define fIsPreChange                pwrMgt->IsPreChange
#define fDriverCallBusy             pwrMgt->DriverCallBusy
#define fPCDFunctionOverride        pwrMgt->PCDFunctionOverride
#define fIdleTimerIgnored           pwrMgt->IdleTimerIgnored
#define fHasAdvisoryDesire          pwrMgt->HasAdvisoryDesire
#define fAdvisoryTickleUsed         pwrMgt->AdvisoryTickleUsed
#define fResetPowerStateOnWake      pwrMgt->ResetPowerStateOnWake
#define fDeviceActiveTimestamp      pwrMgt->DeviceActiveTimestamp
#define fMaxPowerStateEntryTime     pwrMgt->MaxPowerStateEntryTime
#define fMaxPowerStateExitTime      pwrMgt->MaxPowerStateExitTime
#define fActivityLock               pwrMgt->ActivityLock
#define fIdleTimerPeriod            pwrMgt->IdleTimerPeriod
#define fIdleTimerMinPowerState     pwrMgt->IdleTimerMinPowerState
#define fNextIdleTimerPeriod        pwrMgt->NextIdleTimerPeriod
#define fIdleTimerStartTime         pwrMgt->IdleTimerStartTime
#define fDeviceDesire               pwrMgt->DeviceDesire
#define fDesiredPowerState          pwrMgt->DesiredPowerState
#define fPreviousRequestPowerFlags  pwrMgt->PreviousRequestPowerFlags
#define fName                       pwrMgt->Name
#define fNumberOfPowerStates        pwrMgt->NumberOfPowerStates
#define fHighestPowerState          pwrMgt->HighestPowerState
#define fPowerStates                pwrMgt->PowerStates
#define fControllingDriver          pwrMgt->ControllingDriver
#define fCurrentPowerState          pwrMgt->CurrentPowerState
#define fParentsCurrentPowerFlags   pwrMgt->ParentsCurrentPowerFlags
#define fMaxPowerState              pwrMgt->MaxPowerState
#define fMergedOutputPowerFlags     pwrMgt->MergedOutputPowerFlags
#define fResponseArray              pwrMgt->ResponseArray
#define fNotifyClientArray          pwrMgt->NotifyClientArray
#define fSerialNumber               pwrMgt->SerialNumber
#define fOutOfBandParameter         pwrMgt->OutOfBandParameter
#define fDriverCallStartTime        pwrMgt->DriverCallStartTime
#define fCurrentCapabilityFlags     pwrMgt->CurrentCapabilityFlags
#define fCurrentPowerConsumption    pwrMgt->CurrentPowerConsumption
#define fTempClampPowerState        pwrMgt->TempClampPowerState
#define fNotifyChildArray           pwrMgt->NotifyChildArray
#define fPowerClients               pwrMgt->PowerClients
#define fDriverCallEntry            pwrMgt->DriverCallEntry
#define fDriverCallParamPtr         pwrMgt->DriverCallParamPtr
#define fDriverCallParamCount       pwrMgt->DriverCallParamCount
#define fDriverCallParamSlots       pwrMgt->DriverCallParamSlots
#define fDriverCallReason           pwrMgt->DriverCallReason
#define fOutOfBandMessage           pwrMgt->OutOfBandMessage
#define fTempClampCount             pwrMgt->TempClampCount
#define fOverrideMaxPowerState      pwrMgt->OverrideMaxPowerState
#define fDeviceUsablePowerState     pwrMgt->DeviceUsablePowerState
#define fActivityTicklePowerState   pwrMgt->ActivityTicklePowerState
#define fAdvisoryTicklePowerState   pwrMgt->AdvisoryTicklePowerState
#define fActivityTickleCount        pwrMgt->ActivityTickleCount
#define fDeviceWasActive            pwrMgt->DeviceWasActive
#define fAdvisoryTickled            pwrMgt->AdvisoryTickled
#define fWaitReason                 pwrMgt->WaitReason
#define fSavedMachineState          pwrMgt->SavedMachineState
#define fLockedFlags                pwrMgt->LockedFlags
#define fPMDriverCallQueue          pwrMgt->PMDriverCallQueue
#define fInsertInterestSet          pwrMgt->InsertInterestSet
#define fRemoveInterestSet          pwrMgt->RemoveInterestSet
#define fReportClientCnt            pwrMgt->ReportClientCnt
#define fReportBuf                  pwrMgt->ReportBuf
#define fPMVars                     pwrMgt->PMVars
#define fPMActions                  pwrMgt->PMActions

#define StateOrder(state)           (((state) < fNumberOfPowerStates)               \
	                            ? pwrMgt->PowerStates[(state)].stateOrder       \
	                            : (state))
#define StateMax(a, b)               (StateOrder((a)) < StateOrder((b)) ? (b) : (a))
#define StateMin(a, b)               (StateOrder((a)) < StateOrder((b)) ? (a) : (b))

#define kPowerStateZero             (0)

/*
 *  When an IOService is waiting for acknowledgement to a power change
 *  notification from an interested driver or the controlling driver,
 *  the ack timer is ticking every tenth of a second.
 *  (100000000 nanoseconds are one tenth of a second).
 */
#define ACK_TIMER_PERIOD            100000000

#if defined(__i386__) || defined(__x86_64__)
#define WATCHDOG_SLEEP_TIMEOUT      (180)   // 180 secs
#define WATCHDOG_WAKE_TIMEOUT       (180)   // 180  secs
#else
#define WATCHDOG_SLEEP_TIMEOUT      (180)   // 180 secs
#define WATCHDOG_WAKE_TIMEOUT       (180)   // 180 secs
#endif

// Max wait time in microseconds for kernel priority and capability clients
// with async message handlers to acknowledge.
//
#define kPriorityClientMaxWait      (90 * 1000 * 1000)
#define kCapabilityClientMaxWait    (240 * 1000 * 1000)

// Attributes describing a power state change.
// See IOPMPowerChangeFlags data type.
//
#define kIOPMParentInitiated        0x0001  // power change initiated by our  parent
#define kIOPMSelfInitiated          0x0002  // power change initiated by this device
#define kIOPMNotDone                0x0004  // we couldn't make this change
#define kIOPMDomainWillChange       0x0008  // change started by PowerDomainWillChangeTo
#define kIOPMDomainDidChange        0x0010  // change started by PowerDomainDidChangeTo
#define kIOPMDomainPowerDrop        0x0020  // Domain is lowering power
#define kIOPMIgnoreChildren         0x0040  // Ignore children and driver power desires
#define kIOPMSkipAskPowerDown       0x0080  // skip the ask app phase
#define kIOPMSynchronize            0x0100  // change triggered by power tree re-sync
#define kIOPMSyncNoChildNotify      0x0200  // sync root domain only, not entire tree
#define kIOPMSyncTellPowerDown      0x0400  // send the ask/will power off messages
#define kIOPMSyncCancelPowerDown    0x0800  // sleep cancel for maintenance wake
#define kIOPMInitialPowerChange     0x1000  // set for initial power change
#define kIOPMRootChangeUp           0x2000  // Root power domain change up
#define kIOPMRootChangeDown         0x4000  // Root power domain change down
#define kIOPMExpireIdleTimer        0x8000  // Accelerate idle timer expiration

#define kIOPMRootBroadcastFlags     (kIOPMSynchronize  | \
	                             kIOPMRootChangeUp | kIOPMRootChangeDown)

// Activity tickle request flags
#define kTickleTypePowerDrop        0x01
#define kTickleTypePowerRise        0x02
#define kTickleTypeActivity         0x04
#define kTickleTypeAdvisory         0x08

enum {
	kDriverCallInformPreChange,
	kDriverCallInformPostChange,
	kDriverCallSetPowerState,
	kRootDomainInformPreChange
};

struct DriverCallParam {
	OSObject *  Target;
	IOReturn    Result;
};

// values of OutOfBandParameter
enum {
	kNotifyApps,
	kNotifyPriority,
	kNotifyCapabilityChangeApps,
	kNotifyCapabilityChangePriority
};

typedef bool (*IOPMMessageFilter)(
	void * target, void * object, void * arg1, void * arg2, void * arg3 );

// used for applyToInterested
struct IOPMInterestContext {
	OSArray *               responseArray;
	OSArray *               notifyClients;
	uint16_t                serialNumber;
	uint8_t                 isPreChange;
	uint8_t                 enableTracing;
	uint32_t                maxTimeRequested;
	uint32_t                messageType;
	uint32_t                notifyType;
	uint32_t                skippedInDark;
	uint32_t                notSkippedInDark;
	IOService *             us;
	IOPMPowerStateIndex     stateNumber;
	IOPMPowerFlags          stateFlags;
	IOPMPowerChangeFlags    changeFlags;
	const char *            errorLog;
	IOPMMessageFilter       messageFilter;
};

// assertPMDriverCall() options
enum {
	kIOPMDriverCallNoInactiveCheck = 1
};

// assertPMDriverCall() method
enum {
	kIOPMDriverCallMethodUnknown       = 0,
	kIOPMDriverCallMethodSetPowerState = 1,
	kIOPMDriverCallMethodWillChange    = 2,
	kIOPMDriverCallMethodDidChange     = 3,
	kIOPMDriverCallMethodChangeDone    = 4,
	kIOPMDriverCallMethodSetAggressive = 5
};

//******************************************************************************
// PM Statistics & Diagnostics
//******************************************************************************

extern const OSSymbol *gIOPMStatsResponseTimedOut;
extern const OSSymbol *gIOPMStatsResponseCancel;
extern const OSSymbol *gIOPMStatsResponseSlow;
extern const OSSymbol *gIOPMStatsResponsePrompt;
extern const OSSymbol *gIOPMStatsDriverPSChangeSlow;

//******************************************************************************
// IOPMRequest
//******************************************************************************

class IOPMRequest : public IOCommand
{
	OSDeclareDefaultStructors( IOPMRequest );

protected:
	IOService *          fTarget;       // request target
	IOPMRequest *        fRequestNext;  // the next request in the chain
	IOPMRequest *        fRequestRoot;  // the root request in the call tree
	IOItemCount          fWorkWaitCount;// execution blocked if non-zero
	IOItemCount          fFreeWaitCount;// completion blocked if non-zero
	uint32_t             fRequestType;  // request type
	bool                 fIsQuiesceBlocker;

	IOPMCompletionAction fCompletionAction;
	void *               fCompletionTarget;
	void *               fCompletionParam;

public:
	uint32_t             fRequestTag;
	void *               fArg0;
	void *               fArg1;
	void *               fArg2;

	inline bool
	isWorkBlocked( void ) const
	{
		return fWorkWaitCount != 0;
	}

	inline bool
	isFreeBlocked( void ) const
	{
		return fFreeWaitCount != 0;
	}

	inline IOPMRequest *
	getNextRequest( void ) const
	{
		return fRequestNext;
	}

	inline IOPMRequest *
	getRootRequest( void ) const
	{
		if (fRequestRoot) {
			return fRequestRoot;
		}
#if NOT_READY
		if (fCompletionAction) {
			return (IOPMRequest *) this;
		}
#endif
		return NULL;
	}

	inline uint32_t
	getType( void ) const
	{
		return fRequestType;
	}

	inline bool
	isReplyType( void ) const
	{
		return fRequestType > kIOPMRequestTypeReplyStart;
	}

	inline IOService *
	getTarget( void ) const
	{
		return fTarget;
	}

	inline bool
	isQuiesceBlocker( void ) const
	{
		return fIsQuiesceBlocker;
	}

	inline bool
	isQuiesceType( void ) const
	{
		return (kIOPMRequestTypeQuiescePowerTree == fRequestType) &&
		       (fCompletionAction != NULL) && (fCompletionTarget != NULL);
	}

	inline void
	installCompletionAction(
		void *               target,
		IOPMCompletionAction action,
		void *               param )
	{
		fCompletionTarget = target;
		fCompletionAction = action;
		fCompletionParam  = param;
	}

	static IOPMRequest * create( void );
	bool   init( IOService * owner, IOOptionBits type );
	void   reset( void );
	bool   attachNextRequest( IOPMRequest * next );
	bool   detachNextRequest( void );
	bool   attachRootRequest( IOPMRequest * root );
	bool   detachRootRequest( void );
};

//******************************************************************************
// IOPMRequestQueue
//******************************************************************************

class IOPMRequestQueue : public IOEventSource
{
	OSDeclareDefaultStructors( IOPMRequestQueue );

public:
	typedef bool (*Action)( IOService *, IOPMRequest *, IOPMRequestQueue * );

protected:
	queue_head_t    fQueue;
	IOLock *        fLock;

	enum { kMaxDequeueCount = 256 };

	virtual bool checkForWork( void ) APPLE_KEXT_OVERRIDE;
	virtual void free( void ) APPLE_KEXT_OVERRIDE;
	virtual bool init( IOService * inOwner, Action inAction );

public:
	static  IOPMRequestQueue * create( IOService * inOwner, Action inAction );
	void    queuePMRequest( IOPMRequest * request );
	void    queuePMRequestChain( IOPMRequest ** requests, IOItemCount count );
};

//******************************************************************************
// IOPMWorkQueue
//******************************************************************************

#define WORK_QUEUE_STATS    1

class IOPMWorkQueue : public IOEventSource
{
	OSDeclareDefaultStructors( IOPMWorkQueue );

public:
	typedef bool (*Action)( IOService *, IOPMRequest *, IOPMWorkQueue * );

#if WORK_QUEUE_STATS
	uint64_t            fStatCheckForWork;
	uint64_t            fStatScanEntries;
	uint64_t            fStatQueueEmpty;
	uint64_t            fStatNoWorkDone;
#endif

protected:
	queue_head_t        fWorkQueue;
	Action              fInvokeAction;
	Action              fRetireAction;
	uint32_t            fQueueLength;
	uint32_t            fConsumerCount;
	volatile uint32_t   fProducerCount;
	IOPMRequest *       fQuiesceRequest;
	AbsoluteTime        fQuiesceStartTime;
	AbsoluteTime        fQuiesceFinishTime;

	virtual bool checkForWork( void ) APPLE_KEXT_OVERRIDE;
	virtual bool init( IOService * inOwner, Action invoke, Action retire );
	bool    checkRequestQueue( queue_head_t * queue, bool * empty );

public:
	static  IOPMWorkQueue * create( IOService * inOwner, Action invoke, Action retire );
	bool    queuePMRequest( IOPMRequest * request, IOServicePM * pwrMgt );
	void    signalWorkAvailable( void );
	void    incrementProducerCount( void );
	void    attachQuiesceRequest( IOPMRequest * quiesceRequest );
	void    finishQuiesceRequest( IOPMRequest * quiesceRequest );
};

//******************************************************************************
// IOPMCompletionQueue
//******************************************************************************

class IOPMCompletionQueue : public IOEventSource
{
	OSDeclareDefaultStructors( IOPMCompletionQueue );

public:
	typedef bool (*Action)( IOService *, IOPMRequest *, IOPMCompletionQueue * );

protected:
	queue_head_t    fQueue;

	virtual bool checkForWork( void ) APPLE_KEXT_OVERRIDE;
	virtual bool init( IOService * inOwner, Action inAction );

public:
	static  IOPMCompletionQueue * create( IOService * inOwner, Action inAction );
	bool    queuePMRequest( IOPMRequest * request );
};

#endif /* !_IOKIT_IOSERVICEPMPRIVATE_H */