1 /*
2  * Copyright (c) 2001-2002 Apple Computer, Inc. All rights reserved.
3  *
4  * @APPLE_LICENSE_HEADER_START@
5  *
6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
7  *
8  * This file contains Original Code and/or Modifications of Original Code
9  * as defined in and that are subject to the Apple Public Source License
10  * Version 2.0 (the 'License'). You may not use this file except in
11  * compliance with the License. Please obtain a copy of the License at
12  * http://www.opensource.apple.com/apsl/ and read it before using this
13  * file.
14  *
15  * The Original Code and all software distributed under the License are
16  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20  * Please see the License for the specific language governing rights and
21  * limitations under the License.
22  *
23  * @APPLE_LICENSE_HEADER_END@
24  */
25 
26 #include "IOPMPowerStateQueue.h"
27 #undef super
28 #define super IOEventSource
29 OSDefineMetaClassAndStructors(IOPMPowerStateQueue, IOEventSource);
30 
31 IOPMPowerStateQueue *IOPMPowerStateQueue::PMPowerStateQueue(OSObject *inOwner)
32 {
33     IOPMPowerStateQueue     *me = new IOPMPowerStateQueue;
34 
35     if(me && !me->init(inOwner, 0) )
36     {
37         me->release();
38         return NULL;
39     }
40 
41     return me;
42 }
43 
44 bool IOPMPowerStateQueue::init(OSObject *owner, Action action)
45 {
46     if(!(super::init(owner, (IOEventSource::Action) action))) return false;
47 
48     // Queue of powerstate changes
49     changes = NULL;
50 
51     return true;
52 }
53 
54 
55 bool IOPMPowerStateQueue::unIdleOccurred(IOService *inTarget, unsigned long inState)
56 {
57     PowerChangeEntry             *new_one = NULL;
58 
59     new_one = (PowerChangeEntry *)IOMalloc(sizeof(PowerChangeEntry));
60     if(!new_one) return false;
61 
62     new_one->actionType = IOPMPowerStateQueue::kUnIdle;
63     new_one->state = inState;
64     new_one->target = inTarget;
65 
66     // Change to queue
67     OSEnqueueAtomic((void **)&changes, (void *)new_one, 0);
68 
69     signalWorkAvailable();
70 
71     return true;
72 }
73 
74 // checkForWork() is called in a gated context
75 bool IOPMPowerStateQueue::checkForWork()
76 {
77     PowerChangeEntry            *theNode;
78     int                         theState;
79     IOService                   *theTarget;
80     UInt16                      theAction;
81 
82     // Dequeue and process the state change request
83     if((theNode = (PowerChangeEntry *)OSDequeueAtomic((void **)&changes, 0)))
84     {
85         theState = theNode->state;
86         theTarget = theNode->target;
87         theAction = theNode->actionType;
88         IOFree((void *)theNode, sizeof(PowerChangeEntry));
89 
90         switch (theAction)
91         {
92             case kUnIdle:
93                 theTarget->command_received(theState, 0, 0, 0);
94                 break;
95         }
96     }
97 
98     // Return true if there's more work to be done
99     if(changes) return true;
100     else return false;
101 }
102