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