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