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