]> git.saurik.com Git - apple/xnu.git/blame - iokit/Kernel/IOInterruptEventSource.cpp
xnu-344.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 *
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/*
23Copyright (c) 1998 Apple Computer, Inc. All rights reserved.
24
25HISTORY
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) \
39do { \
40 IOTimeStampStart(IODBG_INTES(t), \
41 (unsigned int) this, (unsigned int) owner); \
42} while(0)
43
44#define IOTimeTypeStampE(t) \
45do { \
46 IOTimeStampEnd(IODBG_INTES(t), \
47 (unsigned int) this, (unsigned int) owner); \
48} while(0)
49
50#define IOTimeStampLatency() \
51do { \
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
64OSDefineMetaClassAndStructors(IOInterruptEventSource, IOEventSource)
65OSMetaClassDefineReservedUnused(IOInterruptEventSource, 0);
66OSMetaClassDefineReservedUnused(IOInterruptEventSource, 1);
67OSMetaClassDefineReservedUnused(IOInterruptEventSource, 2);
68OSMetaClassDefineReservedUnused(IOInterruptEventSource, 3);
69OSMetaClassDefineReservedUnused(IOInterruptEventSource, 4);
70OSMetaClassDefineReservedUnused(IOInterruptEventSource, 5);
71OSMetaClassDefineReservedUnused(IOInterruptEventSource, 6);
72OSMetaClassDefineReservedUnused(IOInterruptEventSource, 7);
73
74bool IOInterruptEventSource::init(OSObject *inOwner,
75 Action inAction = 0,
76 IOService *inProvider = 0,
77 int inIntIndex = 0)
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 = (IOInterruptAction)
101 &IOInterruptEventSource::disableInterruptOccurred;
102 }
103 else
104 intHandler = (IOInterruptAction)
105 &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
117IOInterruptEventSource *
118IOInterruptEventSource::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->free();
127 return 0;
128 }
129
130 return me;
131}
132
133void IOInterruptEventSource::free()
134{
135 if (provider && intIndex != -1)
136 provider->unregisterInterrupt(intIndex);
137
138 super::free();
139}
140
141void IOInterruptEventSource::enable()
142{
143 if (provider && intIndex != -1) {
144 provider->enableInterrupt(intIndex);
145 explicitDisable = false;
146 }
147}
148
149void IOInterruptEventSource::disable()
150{
151 if (provider && intIndex != -1) {
152 provider->disableInterrupt(intIndex);
153 explicitDisable = true;
154 }
155}
156
157const IOService *IOInterruptEventSource::getProvider() const
158{
159 return provider;
160}
161
162int IOInterruptEventSource::getIntIndex() const
163{
164 return intIndex;
165}
166
167bool IOInterruptEventSource::getAutoDisable() const
168{
169 return autoDisable;
170}
171
172bool 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
207void IOInterruptEventSource::normalInterruptOccurred
208 (void */*refcon*/, IOService */*prov*/, int /*source*/)
209{
210IOTimeTypeStampS(IOINTES_INTCTXT);
211IOTimeStampLatency();
212
213 producerCount++;
214
215IOTimeTypeStampS(IOINTES_SEMA);
216 signalWorkAvailable();
217IOTimeTypeStampE(IOINTES_SEMA);
218
219IOTimeTypeStampE(IOINTES_INTCTXT);
220}
221
222void IOInterruptEventSource::disableInterruptOccurred
223 (void */*refcon*/, IOService *prov, int source)
224{
225IOTimeTypeStampS(IOINTES_INTCTXT);
226IOTimeStampLatency();
227
228 prov->disableInterrupt(source); /* disable the interrupt */
229
230 producerCount++;
231
232IOTimeTypeStampS(IOINTES_SEMA);
233 signalWorkAvailable();
234IOTimeTypeStampE(IOINTES_SEMA);
235
236IOTimeTypeStampE(IOINTES_INTCTXT);
237}
238
239void 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}