]> git.saurik.com Git - apple/xnu.git/blob - iokit/Kernel/IOInterruptEventSource.cpp
xnu-792.tar.gz
[apple/xnu.git] / iokit / Kernel / IOInterruptEventSource.cpp
1 /*
2 * Copyright (c) 1998-2000 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 Copyright (c) 1998 Apple Computer, Inc. All rights reserved.
24
25 HISTORY
26 1998-7-13 Godfrey van der Linden(gvdl)
27 Created.
28 */
29 #include <IOKit/IOInterruptEventSource.h>
30 #include <IOKit/IOLib.h>
31 #include <IOKit/IOService.h>
32 #include <IOKit/IOInterrupts.h>
33 #include <IOKit/IOTimeStamp.h>
34 #include <IOKit/IOWorkLoop.h>
35
36 #if KDEBUG
37
38 #define IOTimeTypeStampS(t) \
39 do { \
40 IOTimeStampStart(IODBG_INTES(t), \
41 (unsigned int) this, (unsigned int) owner); \
42 } while(0)
43
44 #define IOTimeTypeStampE(t) \
45 do { \
46 IOTimeStampEnd(IODBG_INTES(t), \
47 (unsigned int) this, (unsigned int) owner); \
48 } while(0)
49
50 #define IOTimeStampLatency() \
51 do { \
52 IOTimeStampEnd(IODBG_INTES(IOINTES_LAT), \
53 (unsigned int) this, (unsigned int) owner); \
54 } while(0)
55
56 #else /* !KDEBUG */
57 #define IOTimeTypeStampS(t)
58 #define IOTimeTypeStampE(t)
59 #define IOTimeStampLatency()
60 #endif /* KDEBUG */
61
62 #define super IOEventSource
63
64 OSDefineMetaClassAndStructors(IOInterruptEventSource, IOEventSource)
65 OSMetaClassDefineReservedUnused(IOInterruptEventSource, 0);
66 OSMetaClassDefineReservedUnused(IOInterruptEventSource, 1);
67 OSMetaClassDefineReservedUnused(IOInterruptEventSource, 2);
68 OSMetaClassDefineReservedUnused(IOInterruptEventSource, 3);
69 OSMetaClassDefineReservedUnused(IOInterruptEventSource, 4);
70 OSMetaClassDefineReservedUnused(IOInterruptEventSource, 5);
71 OSMetaClassDefineReservedUnused(IOInterruptEventSource, 6);
72 OSMetaClassDefineReservedUnused(IOInterruptEventSource, 7);
73
74 bool IOInterruptEventSource::init(OSObject *inOwner,
75 Action inAction,
76 IOService *inProvider,
77 int inIntIndex)
78 {
79 bool res = true;
80
81 if ( !super::init(inOwner, (IOEventSourceAction) inAction) )
82 return false;
83
84 provider = inProvider;
85 producerCount = consumerCount = 0;
86 autoDisable = explicitDisable = false;
87 intIndex = -1;
88
89 // Assumes inOwner holds a reference(retain) on the provider
90 if (inProvider) {
91 int intType;
92
93 res = (kIOReturnSuccess
94 == inProvider->getInterruptType(inIntIndex, &intType));
95 if (res) {
96 IOInterruptAction intHandler;
97
98 autoDisable = (intType == kIOInterruptTypeLevel);
99 if (autoDisable) {
100 intHandler = OSMemberFunctionCast(IOInterruptAction,
101 this, &IOInterruptEventSource::disableInterruptOccurred);
102 }
103 else
104 intHandler = OSMemberFunctionCast(IOInterruptAction,
105 this, &IOInterruptEventSource::normalInterruptOccurred);
106
107 res = (kIOReturnSuccess == inProvider->registerInterrupt
108 (inIntIndex, this, intHandler));
109 if (res)
110 intIndex = inIntIndex;
111 }
112 }
113
114 return res;
115 }
116
117 IOInterruptEventSource *
118 IOInterruptEventSource::interruptEventSource(OSObject *inOwner,
119 Action inAction,
120 IOService *inProvider,
121 int inIntIndex)
122 {
123 IOInterruptEventSource *me = new IOInterruptEventSource;
124
125 if (me && !me->init(inOwner, inAction, inProvider, inIntIndex)) {
126 me->release();
127 return 0;
128 }
129
130 return me;
131 }
132
133 void IOInterruptEventSource::free()
134 {
135 if (provider && intIndex != -1)
136 provider->unregisterInterrupt(intIndex);
137
138 super::free();
139 }
140
141 void IOInterruptEventSource::enable()
142 {
143 if (provider && intIndex != -1) {
144 provider->enableInterrupt(intIndex);
145 explicitDisable = false;
146 }
147 }
148
149 void IOInterruptEventSource::disable()
150 {
151 if (provider && intIndex != -1) {
152 provider->disableInterrupt(intIndex);
153 explicitDisable = true;
154 }
155 }
156
157 const IOService *IOInterruptEventSource::getProvider() const
158 {
159 return provider;
160 }
161
162 int IOInterruptEventSource::getIntIndex() const
163 {
164 return intIndex;
165 }
166
167 bool IOInterruptEventSource::getAutoDisable() const
168 {
169 return autoDisable;
170 }
171
172 bool IOInterruptEventSource::checkForWork()
173 {
174 unsigned int cacheProdCount = producerCount;
175 int numInts = cacheProdCount - consumerCount;
176 IOInterruptEventAction intAction = (IOInterruptEventAction) action;
177
178 if (numInts > 0) {
179
180 IOTimeStampLatency();
181 IOTimeTypeStampS(IOINTES_CLIENT);
182 IOTimeStampConstant(IODBG_INTES(IOINTES_ACTION),
183 (unsigned int) intAction, (unsigned int) owner);
184 (*intAction)(owner, this, numInts);
185 IOTimeTypeStampE(IOINTES_CLIENT);
186
187 consumerCount = cacheProdCount;
188 if (autoDisable && !explicitDisable)
189 enable();
190 }
191 else if (numInts < 0) {
192 IOTimeStampLatency();
193 IOTimeTypeStampS(IOINTES_CLIENT);
194 IOTimeStampConstant(IODBG_INTES(IOINTES_ACTION),
195 (unsigned int) intAction, (unsigned int) owner);
196 (*intAction)(owner, this, -numInts);
197 IOTimeTypeStampE(IOINTES_CLIENT);
198
199 consumerCount = cacheProdCount;
200 if (autoDisable && !explicitDisable)
201 enable();
202 }
203
204 return false;
205 }
206
207 void IOInterruptEventSource::normalInterruptOccurred
208 (void */*refcon*/, IOService */*prov*/, int /*source*/)
209 {
210 IOTimeTypeStampS(IOINTES_INTCTXT);
211 IOTimeStampLatency();
212
213 producerCount++;
214
215 IOTimeTypeStampS(IOINTES_SEMA);
216 signalWorkAvailable();
217 IOTimeTypeStampE(IOINTES_SEMA);
218
219 IOTimeTypeStampE(IOINTES_INTCTXT);
220 }
221
222 void IOInterruptEventSource::disableInterruptOccurred
223 (void */*refcon*/, IOService *prov, int source)
224 {
225 IOTimeTypeStampS(IOINTES_INTCTXT);
226 IOTimeStampLatency();
227
228 prov->disableInterrupt(source); /* disable the interrupt */
229
230 producerCount++;
231
232 IOTimeTypeStampS(IOINTES_SEMA);
233 signalWorkAvailable();
234 IOTimeTypeStampE(IOINTES_SEMA);
235
236 IOTimeTypeStampE(IOINTES_INTCTXT);
237 }
238
239 void IOInterruptEventSource::interruptOccurred
240 (void *refcon, IOService *prov, int source)
241 {
242 if (autoDisable && prov)
243 disableInterruptOccurred(refcon, prov, source);
244 else
245 normalInterruptOccurred(refcon, prov, source);
246 }