1*2c2f96dcSApple OSS Distributions /*
2*2c2f96dcSApple OSS Distributions * Copyright (c) 2007-2012 Apple Inc. All rights reserved.
3*2c2f96dcSApple OSS Distributions * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved.
4*2c2f96dcSApple OSS Distributions *
5*2c2f96dcSApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6*2c2f96dcSApple OSS Distributions *
7*2c2f96dcSApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code
8*2c2f96dcSApple OSS Distributions * as defined in and that are subject to the Apple Public Source License
9*2c2f96dcSApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in
10*2c2f96dcSApple OSS Distributions * compliance with the License. The rights granted to you under the License
11*2c2f96dcSApple OSS Distributions * may not be used to create, or enable the creation or redistribution of,
12*2c2f96dcSApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to
13*2c2f96dcSApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any
14*2c2f96dcSApple OSS Distributions * terms of an Apple operating system software license agreement.
15*2c2f96dcSApple OSS Distributions *
16*2c2f96dcSApple OSS Distributions * Please obtain a copy of the License at
17*2c2f96dcSApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file.
18*2c2f96dcSApple OSS Distributions *
19*2c2f96dcSApple OSS Distributions * The Original Code and all software distributed under the License are
20*2c2f96dcSApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
21*2c2f96dcSApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
22*2c2f96dcSApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
23*2c2f96dcSApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
24*2c2f96dcSApple OSS Distributions * Please see the License for the specific language governing rights and
25*2c2f96dcSApple OSS Distributions * limitations under the License.
26*2c2f96dcSApple OSS Distributions *
27*2c2f96dcSApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
28*2c2f96dcSApple OSS Distributions */
29*2c2f96dcSApple OSS Distributions
30*2c2f96dcSApple OSS Distributions #include <IOKit/IOLib.h>
31*2c2f96dcSApple OSS Distributions #include <IOKit/IOService.h>
32*2c2f96dcSApple OSS Distributions #include <IOKit/IOPlatformExpert.h>
33*2c2f96dcSApple OSS Distributions #include <IOKit/IODeviceTreeSupport.h>
34*2c2f96dcSApple OSS Distributions #include <IOKit/IOInterrupts.h>
35*2c2f96dcSApple OSS Distributions #include <IOKit/IOInterruptController.h>
36*2c2f96dcSApple OSS Distributions #include <IOKit/IOKitDebug.h>
37*2c2f96dcSApple OSS Distributions #include <IOKit/IOTimeStamp.h>
38*2c2f96dcSApple OSS Distributions
39*2c2f96dcSApple OSS Distributions
40*2c2f96dcSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
41*2c2f96dcSApple OSS Distributions
42*2c2f96dcSApple OSS Distributions #define super IOService
43*2c2f96dcSApple OSS Distributions
44*2c2f96dcSApple OSS Distributions OSDefineMetaClassAndAbstractStructors(IOInterruptController, IOService);
45*2c2f96dcSApple OSS Distributions
46*2c2f96dcSApple OSS Distributions OSMetaClassDefineReservedUsedX86(IOInterruptController, 0);
47*2c2f96dcSApple OSS Distributions OSMetaClassDefineReservedUsedX86(IOInterruptController, 1);
48*2c2f96dcSApple OSS Distributions OSMetaClassDefineReservedUsedX86(IOInterruptController, 2);
49*2c2f96dcSApple OSS Distributions OSMetaClassDefineReservedUnused(IOInterruptController, 3);
50*2c2f96dcSApple OSS Distributions OSMetaClassDefineReservedUnused(IOInterruptController, 4);
51*2c2f96dcSApple OSS Distributions OSMetaClassDefineReservedUnused(IOInterruptController, 5);
52*2c2f96dcSApple OSS Distributions
53*2c2f96dcSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
54*2c2f96dcSApple OSS Distributions
55*2c2f96dcSApple OSS Distributions IOReturn
registerInterrupt(IOService * nub,int source,void * target,IOInterruptHandler handler,void * refCon)56*2c2f96dcSApple OSS Distributions IOInterruptController::registerInterrupt(IOService *nub, int source,
57*2c2f96dcSApple OSS Distributions void *target,
58*2c2f96dcSApple OSS Distributions IOInterruptHandler handler,
59*2c2f96dcSApple OSS Distributions void *refCon)
60*2c2f96dcSApple OSS Distributions {
61*2c2f96dcSApple OSS Distributions IOInterruptSource *interruptSources;
62*2c2f96dcSApple OSS Distributions IOInterruptVectorNumber vectorNumber;
63*2c2f96dcSApple OSS Distributions IOInterruptVector *vector;
64*2c2f96dcSApple OSS Distributions int wasDisabledSoft;
65*2c2f96dcSApple OSS Distributions IOReturn error;
66*2c2f96dcSApple OSS Distributions OSData *vectorData;
67*2c2f96dcSApple OSS Distributions IOOptionBits options;
68*2c2f96dcSApple OSS Distributions bool canBeShared, shouldBeShared, wasAlreadyRegisterd;
69*2c2f96dcSApple OSS Distributions
70*2c2f96dcSApple OSS Distributions IOService *originalNub = NULL;// Protected by wasAlreadyRegisterd
71*2c2f96dcSApple OSS Distributions int originalSource = 0;// Protected by wasAlreadyRegisterd
72*2c2f96dcSApple OSS Distributions
73*2c2f96dcSApple OSS Distributions
74*2c2f96dcSApple OSS Distributions interruptSources = nub->_interruptSources;
75*2c2f96dcSApple OSS Distributions vectorData = interruptSources[source].vectorData;
76*2c2f96dcSApple OSS Distributions vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
77*2c2f96dcSApple OSS Distributions vector = &vectors[vectorNumber];
78*2c2f96dcSApple OSS Distributions
79*2c2f96dcSApple OSS Distributions // Get the lock for this vector.
80*2c2f96dcSApple OSS Distributions IOLockLock(vector->interruptLock);
81*2c2f96dcSApple OSS Distributions
82*2c2f96dcSApple OSS Distributions // Check if the interrupt source can/should be shared.
83*2c2f96dcSApple OSS Distributions canBeShared = vectorCanBeShared(vectorNumber, vector);
84*2c2f96dcSApple OSS Distributions IODTGetInterruptOptions(nub, source, &options);
85*2c2f96dcSApple OSS Distributions #if defined(__i386__) || defined(__x86_64__)
86*2c2f96dcSApple OSS Distributions int interruptType;
87*2c2f96dcSApple OSS Distributions if (OSDynamicCast(IOPlatformDevice, getProvider()) &&
88*2c2f96dcSApple OSS Distributions (getInterruptType(nub, source, &interruptType) == kIOReturnSuccess) &&
89*2c2f96dcSApple OSS Distributions (kIOInterruptTypeLevel & interruptType)) {
90*2c2f96dcSApple OSS Distributions options |= kIODTInterruptShared;
91*2c2f96dcSApple OSS Distributions }
92*2c2f96dcSApple OSS Distributions #endif
93*2c2f96dcSApple OSS Distributions shouldBeShared = canBeShared && (options & kIODTInterruptShared);
94*2c2f96dcSApple OSS Distributions wasAlreadyRegisterd = vector->interruptRegistered;
95*2c2f96dcSApple OSS Distributions
96*2c2f96dcSApple OSS Distributions // If the vector is registered and can not be shared return error.
97*2c2f96dcSApple OSS Distributions if (wasAlreadyRegisterd && !canBeShared) {
98*2c2f96dcSApple OSS Distributions IOLockUnlock(vector->interruptLock);
99*2c2f96dcSApple OSS Distributions return kIOReturnNoResources;
100*2c2f96dcSApple OSS Distributions }
101*2c2f96dcSApple OSS Distributions
102*2c2f96dcSApple OSS Distributions // If this vector is already in use, and can be shared (implied),
103*2c2f96dcSApple OSS Distributions // or it is not registered and should be shared,
104*2c2f96dcSApple OSS Distributions // register as a shared interrupt.
105*2c2f96dcSApple OSS Distributions if (wasAlreadyRegisterd || shouldBeShared) {
106*2c2f96dcSApple OSS Distributions // If this vector is not already shared, break it out.
107*2c2f96dcSApple OSS Distributions if (vector->sharedController == NULL) {
108*2c2f96dcSApple OSS Distributions // Make the IOShareInterruptController instance
109*2c2f96dcSApple OSS Distributions vector->sharedController = new IOSharedInterruptController;
110*2c2f96dcSApple OSS Distributions if (vector->sharedController == NULL) {
111*2c2f96dcSApple OSS Distributions IOLockUnlock(vector->interruptLock);
112*2c2f96dcSApple OSS Distributions return kIOReturnNoMemory;
113*2c2f96dcSApple OSS Distributions }
114*2c2f96dcSApple OSS Distributions
115*2c2f96dcSApple OSS Distributions if (wasAlreadyRegisterd) {
116*2c2f96dcSApple OSS Distributions // Save the nub and source for the original consumer.
117*2c2f96dcSApple OSS Distributions originalNub = vector->nub;
118*2c2f96dcSApple OSS Distributions originalSource = vector->source;
119*2c2f96dcSApple OSS Distributions
120*2c2f96dcSApple OSS Distributions // Physically disable the interrupt, but mark it as being enabled in the hardware.
121*2c2f96dcSApple OSS Distributions // The interruptDisabledSoft now indicates the driver's request for enablement.
122*2c2f96dcSApple OSS Distributions disableVectorHard(vectorNumber, vector);
123*2c2f96dcSApple OSS Distributions vector->interruptDisabledHard = 0;
124*2c2f96dcSApple OSS Distributions }
125*2c2f96dcSApple OSS Distributions
126*2c2f96dcSApple OSS Distributions // Initialize the new shared interrupt controller.
127*2c2f96dcSApple OSS Distributions error = vector->sharedController->initInterruptController(this, vectorData);
128*2c2f96dcSApple OSS Distributions // If the IOSharedInterruptController could not be initalized,
129*2c2f96dcSApple OSS Distributions // if needed, put the original consumer's interrupt back to normal and
130*2c2f96dcSApple OSS Distributions // get rid of whats left of the shared controller.
131*2c2f96dcSApple OSS Distributions if (error != kIOReturnSuccess) {
132*2c2f96dcSApple OSS Distributions if (wasAlreadyRegisterd) {
133*2c2f96dcSApple OSS Distributions enableInterrupt(originalNub, originalSource);
134*2c2f96dcSApple OSS Distributions }
135*2c2f96dcSApple OSS Distributions vector->sharedController->release();
136*2c2f96dcSApple OSS Distributions vector->sharedController = NULL;
137*2c2f96dcSApple OSS Distributions IOLockUnlock(vector->interruptLock);
138*2c2f96dcSApple OSS Distributions return error;
139*2c2f96dcSApple OSS Distributions }
140*2c2f96dcSApple OSS Distributions
141*2c2f96dcSApple OSS Distributions // If there was an original consumer try to register it on the shared controller.
142*2c2f96dcSApple OSS Distributions if (wasAlreadyRegisterd) {
143*2c2f96dcSApple OSS Distributions error = vector->sharedController->registerInterrupt(originalNub,
144*2c2f96dcSApple OSS Distributions originalSource,
145*2c2f96dcSApple OSS Distributions vector->target,
146*2c2f96dcSApple OSS Distributions vector->handler,
147*2c2f96dcSApple OSS Distributions vector->refCon);
148*2c2f96dcSApple OSS Distributions // If the original consumer could not be moved to the shared controller,
149*2c2f96dcSApple OSS Distributions // put the original consumor's interrupt back to normal and
150*2c2f96dcSApple OSS Distributions // get rid of whats left of the shared controller.
151*2c2f96dcSApple OSS Distributions if (error != kIOReturnSuccess) {
152*2c2f96dcSApple OSS Distributions // Save the driver's interrupt enablement state.
153*2c2f96dcSApple OSS Distributions wasDisabledSoft = vector->interruptDisabledSoft;
154*2c2f96dcSApple OSS Distributions
155*2c2f96dcSApple OSS Distributions // Make the interrupt really hard disabled.
156*2c2f96dcSApple OSS Distributions vector->interruptDisabledSoft = 1;
157*2c2f96dcSApple OSS Distributions vector->interruptDisabledHard = 1;
158*2c2f96dcSApple OSS Distributions
159*2c2f96dcSApple OSS Distributions // Enable the original consumer's interrupt if needed.
160*2c2f96dcSApple OSS Distributions if (!wasDisabledSoft) {
161*2c2f96dcSApple OSS Distributions originalNub->enableInterrupt(originalSource);
162*2c2f96dcSApple OSS Distributions }
163*2c2f96dcSApple OSS Distributions enableInterrupt(originalNub, originalSource);
164*2c2f96dcSApple OSS Distributions
165*2c2f96dcSApple OSS Distributions vector->sharedController->release();
166*2c2f96dcSApple OSS Distributions vector->sharedController = NULL;
167*2c2f96dcSApple OSS Distributions IOLockUnlock(vector->interruptLock);
168*2c2f96dcSApple OSS Distributions return error;
169*2c2f96dcSApple OSS Distributions }
170*2c2f96dcSApple OSS Distributions }
171*2c2f96dcSApple OSS Distributions
172*2c2f96dcSApple OSS Distributions // Fill in vector with the shared controller's info.
173*2c2f96dcSApple OSS Distributions vector->handler = (IOInterruptHandler)vector->sharedController->getInterruptHandlerAddress();
174*2c2f96dcSApple OSS Distributions vector->nub = vector->sharedController;
175*2c2f96dcSApple OSS Distributions vector->source = 0;
176*2c2f96dcSApple OSS Distributions vector->target = vector->sharedController;
177*2c2f96dcSApple OSS Distributions vector->refCon = NULL;
178*2c2f96dcSApple OSS Distributions
179*2c2f96dcSApple OSS Distributions // If the interrupt was already registered,
180*2c2f96dcSApple OSS Distributions // save the driver's interrupt enablement state.
181*2c2f96dcSApple OSS Distributions if (wasAlreadyRegisterd) {
182*2c2f96dcSApple OSS Distributions wasDisabledSoft = vector->interruptDisabledSoft;
183*2c2f96dcSApple OSS Distributions } else {
184*2c2f96dcSApple OSS Distributions wasDisabledSoft = true;
185*2c2f96dcSApple OSS Distributions }
186*2c2f96dcSApple OSS Distributions
187*2c2f96dcSApple OSS Distributions // Do any specific initalization for this vector if it has not yet been used.
188*2c2f96dcSApple OSS Distributions if (!wasAlreadyRegisterd) {
189*2c2f96dcSApple OSS Distributions initVector(vectorNumber, vector);
190*2c2f96dcSApple OSS Distributions }
191*2c2f96dcSApple OSS Distributions
192*2c2f96dcSApple OSS Distributions // Make the interrupt really hard disabled.
193*2c2f96dcSApple OSS Distributions vector->interruptDisabledSoft = 1;
194*2c2f96dcSApple OSS Distributions vector->interruptDisabledHard = 1;
195*2c2f96dcSApple OSS Distributions vector->interruptRegistered = 1;
196*2c2f96dcSApple OSS Distributions
197*2c2f96dcSApple OSS Distributions // Enable the original consumer's interrupt if needed.
198*2c2f96dcSApple OSS Distributions // originalNub is protected by wasAlreadyRegisterd here (see line 184).
199*2c2f96dcSApple OSS Distributions if (!wasDisabledSoft) {
200*2c2f96dcSApple OSS Distributions originalNub->enableInterrupt(originalSource);
201*2c2f96dcSApple OSS Distributions }
202*2c2f96dcSApple OSS Distributions }
203*2c2f96dcSApple OSS Distributions
204*2c2f96dcSApple OSS Distributions error = vector->sharedController->registerInterrupt(nub, source, target,
205*2c2f96dcSApple OSS Distributions handler, refCon);
206*2c2f96dcSApple OSS Distributions IOLockUnlock(vector->interruptLock);
207*2c2f96dcSApple OSS Distributions return error;
208*2c2f96dcSApple OSS Distributions }
209*2c2f96dcSApple OSS Distributions
210*2c2f96dcSApple OSS Distributions // Fill in vector with the client's info.
211*2c2f96dcSApple OSS Distributions vector->handler = handler;
212*2c2f96dcSApple OSS Distributions vector->nub = nub;
213*2c2f96dcSApple OSS Distributions vector->source = source;
214*2c2f96dcSApple OSS Distributions vector->target = target;
215*2c2f96dcSApple OSS Distributions vector->refCon = refCon;
216*2c2f96dcSApple OSS Distributions
217*2c2f96dcSApple OSS Distributions // Do any specific initalization for this vector.
218*2c2f96dcSApple OSS Distributions initVector(vectorNumber, vector);
219*2c2f96dcSApple OSS Distributions
220*2c2f96dcSApple OSS Distributions // Get the vector ready. It starts hard disabled.
221*2c2f96dcSApple OSS Distributions vector->interruptDisabledHard = 1;
222*2c2f96dcSApple OSS Distributions vector->interruptDisabledSoft = 1;
223*2c2f96dcSApple OSS Distributions vector->interruptRegistered = 1;
224*2c2f96dcSApple OSS Distributions
225*2c2f96dcSApple OSS Distributions IOLockUnlock(vector->interruptLock);
226*2c2f96dcSApple OSS Distributions return kIOReturnSuccess;
227*2c2f96dcSApple OSS Distributions }
228*2c2f96dcSApple OSS Distributions
229*2c2f96dcSApple OSS Distributions IOReturn
unregisterInterrupt(IOService * nub,int source)230*2c2f96dcSApple OSS Distributions IOInterruptController::unregisterInterrupt(IOService *nub, int source)
231*2c2f96dcSApple OSS Distributions {
232*2c2f96dcSApple OSS Distributions IOInterruptSource *interruptSources;
233*2c2f96dcSApple OSS Distributions IOInterruptVectorNumber vectorNumber;
234*2c2f96dcSApple OSS Distributions IOInterruptVector *vector;
235*2c2f96dcSApple OSS Distributions OSData *vectorData;
236*2c2f96dcSApple OSS Distributions
237*2c2f96dcSApple OSS Distributions interruptSources = nub->_interruptSources;
238*2c2f96dcSApple OSS Distributions vectorData = interruptSources[source].vectorData;
239*2c2f96dcSApple OSS Distributions vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
240*2c2f96dcSApple OSS Distributions vector = &vectors[vectorNumber];
241*2c2f96dcSApple OSS Distributions
242*2c2f96dcSApple OSS Distributions // Get the lock for this vector.
243*2c2f96dcSApple OSS Distributions IOLockLock(vector->interruptLock);
244*2c2f96dcSApple OSS Distributions
245*2c2f96dcSApple OSS Distributions // Return success if it is not already registered
246*2c2f96dcSApple OSS Distributions if (!vector->interruptRegistered) {
247*2c2f96dcSApple OSS Distributions IOLockUnlock(vector->interruptLock);
248*2c2f96dcSApple OSS Distributions return kIOReturnSuccess;
249*2c2f96dcSApple OSS Distributions }
250*2c2f96dcSApple OSS Distributions
251*2c2f96dcSApple OSS Distributions // Soft disable the source.
252*2c2f96dcSApple OSS Distributions disableInterrupt(nub, source);
253*2c2f96dcSApple OSS Distributions
254*2c2f96dcSApple OSS Distributions // Turn the source off at hardware.
255*2c2f96dcSApple OSS Distributions disableVectorHard(vectorNumber, vector);
256*2c2f96dcSApple OSS Distributions
257*2c2f96dcSApple OSS Distributions // Clear all the storage for the vector except for interruptLock.
258*2c2f96dcSApple OSS Distributions vector->interruptActive = 0;
259*2c2f96dcSApple OSS Distributions vector->interruptDisabledSoft = 0;
260*2c2f96dcSApple OSS Distributions vector->interruptDisabledHard = 0;
261*2c2f96dcSApple OSS Distributions vector->interruptRegistered = 0;
262*2c2f96dcSApple OSS Distributions vector->nub = NULL;
263*2c2f96dcSApple OSS Distributions vector->source = 0;
264*2c2f96dcSApple OSS Distributions vector->handler = NULL;
265*2c2f96dcSApple OSS Distributions vector->target = NULL;
266*2c2f96dcSApple OSS Distributions vector->refCon = NULL;
267*2c2f96dcSApple OSS Distributions
268*2c2f96dcSApple OSS Distributions IOLockUnlock(vector->interruptLock);
269*2c2f96dcSApple OSS Distributions return kIOReturnSuccess;
270*2c2f96dcSApple OSS Distributions }
271*2c2f96dcSApple OSS Distributions
272*2c2f96dcSApple OSS Distributions IOReturn
getInterruptType(IOService * nub,int source,int * interruptType)273*2c2f96dcSApple OSS Distributions IOInterruptController::getInterruptType(IOService *nub, int source,
274*2c2f96dcSApple OSS Distributions int *interruptType)
275*2c2f96dcSApple OSS Distributions {
276*2c2f96dcSApple OSS Distributions IOInterruptSource *interruptSources;
277*2c2f96dcSApple OSS Distributions IOInterruptVectorNumber vectorNumber;
278*2c2f96dcSApple OSS Distributions IOInterruptVector *vector;
279*2c2f96dcSApple OSS Distributions OSData *vectorData;
280*2c2f96dcSApple OSS Distributions
281*2c2f96dcSApple OSS Distributions if (interruptType == NULL) {
282*2c2f96dcSApple OSS Distributions return kIOReturnBadArgument;
283*2c2f96dcSApple OSS Distributions }
284*2c2f96dcSApple OSS Distributions
285*2c2f96dcSApple OSS Distributions interruptSources = nub->_interruptSources;
286*2c2f96dcSApple OSS Distributions vectorData = interruptSources[source].vectorData;
287*2c2f96dcSApple OSS Distributions vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
288*2c2f96dcSApple OSS Distributions vector = &vectors[vectorNumber];
289*2c2f96dcSApple OSS Distributions
290*2c2f96dcSApple OSS Distributions *interruptType = getVectorType(vectorNumber, vector);
291*2c2f96dcSApple OSS Distributions
292*2c2f96dcSApple OSS Distributions return kIOReturnSuccess;
293*2c2f96dcSApple OSS Distributions }
294*2c2f96dcSApple OSS Distributions
295*2c2f96dcSApple OSS Distributions IOReturn
enableInterrupt(IOService * nub,int source)296*2c2f96dcSApple OSS Distributions IOInterruptController::enableInterrupt(IOService *nub, int source)
297*2c2f96dcSApple OSS Distributions {
298*2c2f96dcSApple OSS Distributions IOInterruptSource *interruptSources;
299*2c2f96dcSApple OSS Distributions IOInterruptVectorNumber vectorNumber;
300*2c2f96dcSApple OSS Distributions IOInterruptVector *vector;
301*2c2f96dcSApple OSS Distributions OSData *vectorData;
302*2c2f96dcSApple OSS Distributions
303*2c2f96dcSApple OSS Distributions interruptSources = nub->_interruptSources;
304*2c2f96dcSApple OSS Distributions vectorData = interruptSources[source].vectorData;
305*2c2f96dcSApple OSS Distributions vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
306*2c2f96dcSApple OSS Distributions vector = &vectors[vectorNumber];
307*2c2f96dcSApple OSS Distributions
308*2c2f96dcSApple OSS Distributions if (vector->interruptDisabledSoft) {
309*2c2f96dcSApple OSS Distributions vector->interruptDisabledSoft = 0;
310*2c2f96dcSApple OSS Distributions #if !defined(__i386__) && !defined(__x86_64__)
311*2c2f96dcSApple OSS Distributions OSMemoryBarrier();
312*2c2f96dcSApple OSS Distributions #endif
313*2c2f96dcSApple OSS Distributions
314*2c2f96dcSApple OSS Distributions if (!getPlatform()->atInterruptLevel()) {
315*2c2f96dcSApple OSS Distributions while (vector->interruptActive) {
316*2c2f96dcSApple OSS Distributions }
317*2c2f96dcSApple OSS Distributions }
318*2c2f96dcSApple OSS Distributions if (vector->interruptDisabledHard) {
319*2c2f96dcSApple OSS Distributions vector->interruptDisabledHard = 0;
320*2c2f96dcSApple OSS Distributions
321*2c2f96dcSApple OSS Distributions // A DSB ISH on ARM is needed to make sure the vector data are
322*2c2f96dcSApple OSS Distributions // properly initialized before the MMIO enabling the interrupts
323*2c2f96dcSApple OSS Distributions // in hardware. OSMemoryBarrier(), which maps to DMB, is not
324*2c2f96dcSApple OSS Distributions // sufficient here as the CPUs are not consumers of the device
325*2c2f96dcSApple OSS Distributions // write. Hence, the DMB does not guarantee the CPUs won't see an
326*2c2f96dcSApple OSS Distributions // interrupt before it initalizes the vector data properly.
327*2c2f96dcSApple OSS Distributions OSSynchronizeIO();
328*2c2f96dcSApple OSS Distributions
329*2c2f96dcSApple OSS Distributions enableVector(vectorNumber, vector);
330*2c2f96dcSApple OSS Distributions }
331*2c2f96dcSApple OSS Distributions }
332*2c2f96dcSApple OSS Distributions
333*2c2f96dcSApple OSS Distributions return kIOReturnSuccess;
334*2c2f96dcSApple OSS Distributions }
335*2c2f96dcSApple OSS Distributions
336*2c2f96dcSApple OSS Distributions IOReturn
disableInterrupt(IOService * nub,int source)337*2c2f96dcSApple OSS Distributions IOInterruptController::disableInterrupt(IOService *nub, int source)
338*2c2f96dcSApple OSS Distributions {
339*2c2f96dcSApple OSS Distributions IOInterruptSource *interruptSources;
340*2c2f96dcSApple OSS Distributions IOInterruptVectorNumber vectorNumber;
341*2c2f96dcSApple OSS Distributions IOInterruptVector *vector;
342*2c2f96dcSApple OSS Distributions OSData *vectorData;
343*2c2f96dcSApple OSS Distributions
344*2c2f96dcSApple OSS Distributions interruptSources = nub->_interruptSources;
345*2c2f96dcSApple OSS Distributions vectorData = interruptSources[source].vectorData;
346*2c2f96dcSApple OSS Distributions vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
347*2c2f96dcSApple OSS Distributions vector = &vectors[vectorNumber];
348*2c2f96dcSApple OSS Distributions
349*2c2f96dcSApple OSS Distributions vector->interruptDisabledSoft = 1;
350*2c2f96dcSApple OSS Distributions #if !defined(__i386__) && !defined(__x86_64__)
351*2c2f96dcSApple OSS Distributions OSMemoryBarrier();
352*2c2f96dcSApple OSS Distributions #endif
353*2c2f96dcSApple OSS Distributions
354*2c2f96dcSApple OSS Distributions if (!getPlatform()->atInterruptLevel()) {
355*2c2f96dcSApple OSS Distributions while (vector->interruptActive) {
356*2c2f96dcSApple OSS Distributions }
357*2c2f96dcSApple OSS Distributions }
358*2c2f96dcSApple OSS Distributions
359*2c2f96dcSApple OSS Distributions return kIOReturnSuccess;
360*2c2f96dcSApple OSS Distributions }
361*2c2f96dcSApple OSS Distributions
362*2c2f96dcSApple OSS Distributions IOReturn
causeInterrupt(IOService * nub,int source)363*2c2f96dcSApple OSS Distributions IOInterruptController::causeInterrupt(IOService *nub, int source)
364*2c2f96dcSApple OSS Distributions {
365*2c2f96dcSApple OSS Distributions IOInterruptSource *interruptSources;
366*2c2f96dcSApple OSS Distributions IOInterruptVectorNumber vectorNumber;
367*2c2f96dcSApple OSS Distributions IOInterruptVector *vector;
368*2c2f96dcSApple OSS Distributions OSData *vectorData;
369*2c2f96dcSApple OSS Distributions
370*2c2f96dcSApple OSS Distributions interruptSources = nub->_interruptSources;
371*2c2f96dcSApple OSS Distributions vectorData = interruptSources[source].vectorData;
372*2c2f96dcSApple OSS Distributions vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
373*2c2f96dcSApple OSS Distributions vector = &vectors[vectorNumber];
374*2c2f96dcSApple OSS Distributions
375*2c2f96dcSApple OSS Distributions causeVector(vectorNumber, vector);
376*2c2f96dcSApple OSS Distributions
377*2c2f96dcSApple OSS Distributions return kIOReturnSuccess;
378*2c2f96dcSApple OSS Distributions }
379*2c2f96dcSApple OSS Distributions
380*2c2f96dcSApple OSS Distributions IOInterruptAction
getInterruptHandlerAddress(void)381*2c2f96dcSApple OSS Distributions IOInterruptController::getInterruptHandlerAddress(void)
382*2c2f96dcSApple OSS Distributions {
383*2c2f96dcSApple OSS Distributions return NULL;
384*2c2f96dcSApple OSS Distributions }
385*2c2f96dcSApple OSS Distributions
386*2c2f96dcSApple OSS Distributions IOReturn
handleInterrupt(void * refCon,IOService * nub,int source)387*2c2f96dcSApple OSS Distributions IOInterruptController::handleInterrupt(void *refCon, IOService *nub,
388*2c2f96dcSApple OSS Distributions int source)
389*2c2f96dcSApple OSS Distributions {
390*2c2f96dcSApple OSS Distributions return kIOReturnInvalid;
391*2c2f96dcSApple OSS Distributions }
392*2c2f96dcSApple OSS Distributions
393*2c2f96dcSApple OSS Distributions
394*2c2f96dcSApple OSS Distributions // Methods to be overridden for simplifed interrupt controller subclasses.
395*2c2f96dcSApple OSS Distributions
396*2c2f96dcSApple OSS Distributions bool
vectorCanBeShared(IOInterruptVectorNumber,IOInterruptVector *)397*2c2f96dcSApple OSS Distributions IOInterruptController::vectorCanBeShared(IOInterruptVectorNumber /*vectorNumber*/,
398*2c2f96dcSApple OSS Distributions IOInterruptVector */*vector*/)
399*2c2f96dcSApple OSS Distributions {
400*2c2f96dcSApple OSS Distributions return false;
401*2c2f96dcSApple OSS Distributions }
402*2c2f96dcSApple OSS Distributions
403*2c2f96dcSApple OSS Distributions void
initVector(IOInterruptVectorNumber,IOInterruptVector *)404*2c2f96dcSApple OSS Distributions IOInterruptController::initVector(IOInterruptVectorNumber /*vectorNumber*/,
405*2c2f96dcSApple OSS Distributions IOInterruptVector */*vector*/)
406*2c2f96dcSApple OSS Distributions {
407*2c2f96dcSApple OSS Distributions }
408*2c2f96dcSApple OSS Distributions
409*2c2f96dcSApple OSS Distributions int
getVectorType(IOInterruptVectorNumber,IOInterruptVector *)410*2c2f96dcSApple OSS Distributions IOInterruptController::getVectorType(IOInterruptVectorNumber /*vectorNumber*/,
411*2c2f96dcSApple OSS Distributions IOInterruptVector */*vector*/)
412*2c2f96dcSApple OSS Distributions {
413*2c2f96dcSApple OSS Distributions return kIOInterruptTypeEdge;
414*2c2f96dcSApple OSS Distributions }
415*2c2f96dcSApple OSS Distributions
416*2c2f96dcSApple OSS Distributions void
disableVectorHard(IOInterruptVectorNumber,IOInterruptVector *)417*2c2f96dcSApple OSS Distributions IOInterruptController::disableVectorHard(IOInterruptVectorNumber /*vectorNumber*/,
418*2c2f96dcSApple OSS Distributions IOInterruptVector */*vector*/)
419*2c2f96dcSApple OSS Distributions {
420*2c2f96dcSApple OSS Distributions }
421*2c2f96dcSApple OSS Distributions
422*2c2f96dcSApple OSS Distributions void
enableVector(IOInterruptVectorNumber,IOInterruptVector *)423*2c2f96dcSApple OSS Distributions IOInterruptController::enableVector(IOInterruptVectorNumber /*vectorNumber*/,
424*2c2f96dcSApple OSS Distributions IOInterruptVector */*vector*/)
425*2c2f96dcSApple OSS Distributions {
426*2c2f96dcSApple OSS Distributions }
427*2c2f96dcSApple OSS Distributions
428*2c2f96dcSApple OSS Distributions void
causeVector(IOInterruptVectorNumber,IOInterruptVector *)429*2c2f96dcSApple OSS Distributions IOInterruptController::causeVector(IOInterruptVectorNumber /*vectorNumber*/,
430*2c2f96dcSApple OSS Distributions IOInterruptVector */*vector*/)
431*2c2f96dcSApple OSS Distributions {
432*2c2f96dcSApple OSS Distributions }
433*2c2f96dcSApple OSS Distributions
434*2c2f96dcSApple OSS Distributions void
setCPUInterruptProperties(IOService *)435*2c2f96dcSApple OSS Distributions IOInterruptController::setCPUInterruptProperties(IOService */*service*/)
436*2c2f96dcSApple OSS Distributions {
437*2c2f96dcSApple OSS Distributions }
438*2c2f96dcSApple OSS Distributions
439*2c2f96dcSApple OSS Distributions void
sendIPI(unsigned int,bool)440*2c2f96dcSApple OSS Distributions IOInterruptController::sendIPI(unsigned int /*cpu_id*/, bool /*deferred*/)
441*2c2f96dcSApple OSS Distributions {
442*2c2f96dcSApple OSS Distributions }
443*2c2f96dcSApple OSS Distributions
444*2c2f96dcSApple OSS Distributions void
cancelDeferredIPI(unsigned int)445*2c2f96dcSApple OSS Distributions IOInterruptController::cancelDeferredIPI(unsigned int /*cpu_id*/)
446*2c2f96dcSApple OSS Distributions {
447*2c2f96dcSApple OSS Distributions }
448*2c2f96dcSApple OSS Distributions
449*2c2f96dcSApple OSS Distributions void
timeStampSpuriousInterrupt(void)450*2c2f96dcSApple OSS Distributions IOInterruptController::timeStampSpuriousInterrupt(void)
451*2c2f96dcSApple OSS Distributions {
452*2c2f96dcSApple OSS Distributions uint64_t providerID = 0;
453*2c2f96dcSApple OSS Distributions IOService * provider = getProvider();
454*2c2f96dcSApple OSS Distributions
455*2c2f96dcSApple OSS Distributions if (provider) {
456*2c2f96dcSApple OSS Distributions providerID = provider->getRegistryEntryID();
457*2c2f96dcSApple OSS Distributions }
458*2c2f96dcSApple OSS Distributions
459*2c2f96dcSApple OSS Distributions IOTimeStampConstant(IODBG_INTC(IOINTC_SPURIOUS), providerID);
460*2c2f96dcSApple OSS Distributions }
461*2c2f96dcSApple OSS Distributions
462*2c2f96dcSApple OSS Distributions void
timeStampInterruptHandlerInternal(bool isStart,IOInterruptVectorNumber vectorNumber,IOInterruptVector * vector)463*2c2f96dcSApple OSS Distributions IOInterruptController::timeStampInterruptHandlerInternal(bool isStart, IOInterruptVectorNumber vectorNumber, IOInterruptVector *vector)
464*2c2f96dcSApple OSS Distributions {
465*2c2f96dcSApple OSS Distributions uint64_t providerID = 0;
466*2c2f96dcSApple OSS Distributions vm_offset_t unslidHandler = 0;
467*2c2f96dcSApple OSS Distributions vm_offset_t unslidTarget = 0;
468*2c2f96dcSApple OSS Distributions
469*2c2f96dcSApple OSS Distributions IOService * provider = getProvider();
470*2c2f96dcSApple OSS Distributions
471*2c2f96dcSApple OSS Distributions if (provider) {
472*2c2f96dcSApple OSS Distributions providerID = provider->getRegistryEntryID();
473*2c2f96dcSApple OSS Distributions }
474*2c2f96dcSApple OSS Distributions
475*2c2f96dcSApple OSS Distributions if (vector) {
476*2c2f96dcSApple OSS Distributions unslidHandler = VM_KERNEL_UNSLIDE((vm_offset_t)vector->handler);
477*2c2f96dcSApple OSS Distributions unslidTarget = VM_KERNEL_UNSLIDE_OR_PERM((vm_offset_t)vector->target);
478*2c2f96dcSApple OSS Distributions }
479*2c2f96dcSApple OSS Distributions
480*2c2f96dcSApple OSS Distributions
481*2c2f96dcSApple OSS Distributions if (isStart) {
482*2c2f96dcSApple OSS Distributions #if SCHED_HYGIENE_DEBUG
483*2c2f96dcSApple OSS Distributions ml_irq_debug_start((uintptr_t)vector->handler, (uintptr_t)vector);
484*2c2f96dcSApple OSS Distributions #endif
485*2c2f96dcSApple OSS Distributions IOTimeStampStartConstant(IODBG_INTC(IOINTC_HANDLER), (uintptr_t)vectorNumber, (uintptr_t)unslidHandler,
486*2c2f96dcSApple OSS Distributions (uintptr_t)unslidTarget, (uintptr_t)providerID);
487*2c2f96dcSApple OSS Distributions } else {
488*2c2f96dcSApple OSS Distributions IOTimeStampEndConstant(IODBG_INTC(IOINTC_HANDLER), (uintptr_t)vectorNumber, (uintptr_t)unslidHandler,
489*2c2f96dcSApple OSS Distributions (uintptr_t)unslidTarget, (uintptr_t)providerID);
490*2c2f96dcSApple OSS Distributions #if SCHED_HYGIENE_DEBUG
491*2c2f96dcSApple OSS Distributions ml_irq_debug_end();
492*2c2f96dcSApple OSS Distributions #endif
493*2c2f96dcSApple OSS Distributions }
494*2c2f96dcSApple OSS Distributions }
495*2c2f96dcSApple OSS Distributions
496*2c2f96dcSApple OSS Distributions void
timeStampInterruptHandlerStart(IOInterruptVectorNumber vectorNumber,IOInterruptVector * vector)497*2c2f96dcSApple OSS Distributions IOInterruptController::timeStampInterruptHandlerStart(IOInterruptVectorNumber vectorNumber, IOInterruptVector *vector)
498*2c2f96dcSApple OSS Distributions {
499*2c2f96dcSApple OSS Distributions timeStampInterruptHandlerInternal(true, vectorNumber, vector);
500*2c2f96dcSApple OSS Distributions }
501*2c2f96dcSApple OSS Distributions
502*2c2f96dcSApple OSS Distributions void
timeStampInterruptHandlerEnd(IOInterruptVectorNumber vectorNumber,IOInterruptVector * vector)503*2c2f96dcSApple OSS Distributions IOInterruptController::timeStampInterruptHandlerEnd(IOInterruptVectorNumber vectorNumber, IOInterruptVector *vector)
504*2c2f96dcSApple OSS Distributions {
505*2c2f96dcSApple OSS Distributions timeStampInterruptHandlerInternal(false, vectorNumber, vector);
506*2c2f96dcSApple OSS Distributions }
507*2c2f96dcSApple OSS Distributions
508*2c2f96dcSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
509*2c2f96dcSApple OSS Distributions
510*2c2f96dcSApple OSS Distributions #undef super
511*2c2f96dcSApple OSS Distributions #define super IOInterruptController
512*2c2f96dcSApple OSS Distributions
513*2c2f96dcSApple OSS Distributions OSDefineMetaClassAndStructors(IOSharedInterruptController, IOInterruptController);
514*2c2f96dcSApple OSS Distributions
515*2c2f96dcSApple OSS Distributions OSMetaClassDefineReservedUnused(IOSharedInterruptController, 0);
516*2c2f96dcSApple OSS Distributions OSMetaClassDefineReservedUnused(IOSharedInterruptController, 1);
517*2c2f96dcSApple OSS Distributions OSMetaClassDefineReservedUnused(IOSharedInterruptController, 2);
518*2c2f96dcSApple OSS Distributions OSMetaClassDefineReservedUnused(IOSharedInterruptController, 3);
519*2c2f96dcSApple OSS Distributions
520*2c2f96dcSApple OSS Distributions /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
521*2c2f96dcSApple OSS Distributions
522*2c2f96dcSApple OSS Distributions #define kIOSharedInterruptControllerDefaultVectors (128)
523*2c2f96dcSApple OSS Distributions
524*2c2f96dcSApple OSS Distributions IOReturn
initInterruptController(IOInterruptController * parentController,OSData * parentSource)525*2c2f96dcSApple OSS Distributions IOSharedInterruptController::initInterruptController(IOInterruptController *parentController, OSData *parentSource)
526*2c2f96dcSApple OSS Distributions {
527*2c2f96dcSApple OSS Distributions int cnt, interruptType;
528*2c2f96dcSApple OSS Distributions IOReturn error;
529*2c2f96dcSApple OSS Distributions
530*2c2f96dcSApple OSS Distributions if (!super::init()) {
531*2c2f96dcSApple OSS Distributions return kIOReturnNoResources;
532*2c2f96dcSApple OSS Distributions }
533*2c2f96dcSApple OSS Distributions
534*2c2f96dcSApple OSS Distributions // Set provider to this so enable/disable nub stuff works.
535*2c2f96dcSApple OSS Distributions provider = this;
536*2c2f96dcSApple OSS Distributions
537*2c2f96dcSApple OSS Distributions // Allocate the IOInterruptSource so this can act like a nub.
538*2c2f96dcSApple OSS Distributions _interruptSources = IONew(IOInterruptSource, 1);
539*2c2f96dcSApple OSS Distributions if (_interruptSources == NULL) {
540*2c2f96dcSApple OSS Distributions return kIOReturnNoMemory;
541*2c2f96dcSApple OSS Distributions }
542*2c2f96dcSApple OSS Distributions _numInterruptSources = 1;
543*2c2f96dcSApple OSS Distributions
544*2c2f96dcSApple OSS Distributions // Set up the IOInterruptSource to point at this.
545*2c2f96dcSApple OSS Distributions parentController->retain();
546*2c2f96dcSApple OSS Distributions parentSource->retain();
547*2c2f96dcSApple OSS Distributions _interruptSources[0].interruptController = parentController;
548*2c2f96dcSApple OSS Distributions _interruptSources[0].vectorData = parentSource;
549*2c2f96dcSApple OSS Distributions
550*2c2f96dcSApple OSS Distributions sourceIsLevel = false;
551*2c2f96dcSApple OSS Distributions error = provider->getInterruptType(0, &interruptType);
552*2c2f96dcSApple OSS Distributions if (error == kIOReturnSuccess) {
553*2c2f96dcSApple OSS Distributions if (interruptType & kIOInterruptTypeLevel) {
554*2c2f96dcSApple OSS Distributions sourceIsLevel = true;
555*2c2f96dcSApple OSS Distributions }
556*2c2f96dcSApple OSS Distributions }
557*2c2f96dcSApple OSS Distributions
558*2c2f96dcSApple OSS Distributions // Allocate the memory for the vectors
559*2c2f96dcSApple OSS Distributions numVectors = kIOSharedInterruptControllerDefaultVectors; // For now a constant number.
560*2c2f96dcSApple OSS Distributions vectors = IONewZero(IOInterruptVector, numVectors);
561*2c2f96dcSApple OSS Distributions if (vectors == NULL) {
562*2c2f96dcSApple OSS Distributions IODelete(_interruptSources, IOInterruptSource, 1);
563*2c2f96dcSApple OSS Distributions return kIOReturnNoMemory;
564*2c2f96dcSApple OSS Distributions }
565*2c2f96dcSApple OSS Distributions
566*2c2f96dcSApple OSS Distributions // Allocate the lock for the controller.
567*2c2f96dcSApple OSS Distributions controllerLock = IOSimpleLockAlloc();
568*2c2f96dcSApple OSS Distributions if (controllerLock == NULL) {
569*2c2f96dcSApple OSS Distributions return kIOReturnNoResources;
570*2c2f96dcSApple OSS Distributions }
571*2c2f96dcSApple OSS Distributions
572*2c2f96dcSApple OSS Distributions // Allocate locks for the vectors.
573*2c2f96dcSApple OSS Distributions for (cnt = 0; cnt < numVectors; cnt++) {
574*2c2f96dcSApple OSS Distributions vectors[cnt].interruptLock = IOLockAlloc();
575*2c2f96dcSApple OSS Distributions if (vectors[cnt].interruptLock == NULL) {
576*2c2f96dcSApple OSS Distributions for (cnt = 0; cnt < numVectors; cnt++) {
577*2c2f96dcSApple OSS Distributions if (vectors[cnt].interruptLock != NULL) {
578*2c2f96dcSApple OSS Distributions IOLockFree(vectors[cnt].interruptLock);
579*2c2f96dcSApple OSS Distributions }
580*2c2f96dcSApple OSS Distributions }
581*2c2f96dcSApple OSS Distributions return kIOReturnNoResources;
582*2c2f96dcSApple OSS Distributions }
583*2c2f96dcSApple OSS Distributions }
584*2c2f96dcSApple OSS Distributions
585*2c2f96dcSApple OSS Distributions numVectors = 0; // reset the high water mark for used vectors
586*2c2f96dcSApple OSS Distributions vectorsRegistered = 0;
587*2c2f96dcSApple OSS Distributions vectorsEnabled = 0;
588*2c2f96dcSApple OSS Distributions controllerDisabled = 1;
589*2c2f96dcSApple OSS Distributions
590*2c2f96dcSApple OSS Distributions return kIOReturnSuccess;
591*2c2f96dcSApple OSS Distributions }
592*2c2f96dcSApple OSS Distributions
593*2c2f96dcSApple OSS Distributions IOReturn
registerInterrupt(IOService * nub,int source,void * target,IOInterruptHandler handler,void * refCon)594*2c2f96dcSApple OSS Distributions IOSharedInterruptController::registerInterrupt(IOService *nub,
595*2c2f96dcSApple OSS Distributions int source,
596*2c2f96dcSApple OSS Distributions void *target,
597*2c2f96dcSApple OSS Distributions IOInterruptHandler handler,
598*2c2f96dcSApple OSS Distributions void *refCon)
599*2c2f96dcSApple OSS Distributions {
600*2c2f96dcSApple OSS Distributions IOInterruptSource *interruptSources;
601*2c2f96dcSApple OSS Distributions IOInterruptVectorNumber vectorNumber;
602*2c2f96dcSApple OSS Distributions IOInterruptVector *vector = NULL;
603*2c2f96dcSApple OSS Distributions OSData *vectorData;
604*2c2f96dcSApple OSS Distributions IOInterruptState interruptState;
605*2c2f96dcSApple OSS Distributions
606*2c2f96dcSApple OSS Distributions interruptSources = nub->_interruptSources;
607*2c2f96dcSApple OSS Distributions
608*2c2f96dcSApple OSS Distributions // Find a free vector.
609*2c2f96dcSApple OSS Distributions vectorNumber = kIOSharedInterruptControllerDefaultVectors;
610*2c2f96dcSApple OSS Distributions while (vectorsRegistered != kIOSharedInterruptControllerDefaultVectors) {
611*2c2f96dcSApple OSS Distributions for (vectorNumber = 0; vectorNumber < kIOSharedInterruptControllerDefaultVectors; vectorNumber++) {
612*2c2f96dcSApple OSS Distributions vector = &vectors[vectorNumber];
613*2c2f96dcSApple OSS Distributions
614*2c2f96dcSApple OSS Distributions // Get the lock for this vector.
615*2c2f96dcSApple OSS Distributions IOLockLock(vector->interruptLock);
616*2c2f96dcSApple OSS Distributions
617*2c2f96dcSApple OSS Distributions // Is it unregistered?
618*2c2f96dcSApple OSS Distributions if (!vector->interruptRegistered) {
619*2c2f96dcSApple OSS Distributions break;
620*2c2f96dcSApple OSS Distributions }
621*2c2f96dcSApple OSS Distributions
622*2c2f96dcSApple OSS Distributions // Move along to the next one.
623*2c2f96dcSApple OSS Distributions IOLockUnlock(vector->interruptLock);
624*2c2f96dcSApple OSS Distributions }
625*2c2f96dcSApple OSS Distributions
626*2c2f96dcSApple OSS Distributions if (vectorNumber != kIOSharedInterruptControllerDefaultVectors) {
627*2c2f96dcSApple OSS Distributions break;
628*2c2f96dcSApple OSS Distributions }
629*2c2f96dcSApple OSS Distributions }
630*2c2f96dcSApple OSS Distributions
631*2c2f96dcSApple OSS Distributions // Could not find a free one, so give up.
632*2c2f96dcSApple OSS Distributions if (vectorNumber == kIOSharedInterruptControllerDefaultVectors) {
633*2c2f96dcSApple OSS Distributions return kIOReturnNoResources;
634*2c2f96dcSApple OSS Distributions }
635*2c2f96dcSApple OSS Distributions
636*2c2f96dcSApple OSS Distributions // Create the vectorData for the IOInterruptSource.
637*2c2f96dcSApple OSS Distributions vectorData = OSData::withValue(vectorNumber);
638*2c2f96dcSApple OSS Distributions if (vectorData == NULL) {
639*2c2f96dcSApple OSS Distributions IOLockUnlock(vector->interruptLock);
640*2c2f96dcSApple OSS Distributions return kIOReturnNoMemory;
641*2c2f96dcSApple OSS Distributions }
642*2c2f96dcSApple OSS Distributions
643*2c2f96dcSApple OSS Distributions // Fill in the IOInterruptSource with the controller's info.
644*2c2f96dcSApple OSS Distributions interruptSources[source].interruptController = this;
645*2c2f96dcSApple OSS Distributions interruptSources[source].vectorData = vectorData;
646*2c2f96dcSApple OSS Distributions
647*2c2f96dcSApple OSS Distributions // Fill in vector with the client's info.
648*2c2f96dcSApple OSS Distributions vector->handler = handler;
649*2c2f96dcSApple OSS Distributions vector->nub = nub;
650*2c2f96dcSApple OSS Distributions vector->source = source;
651*2c2f96dcSApple OSS Distributions vector->target = target;
652*2c2f96dcSApple OSS Distributions vector->refCon = refCon;
653*2c2f96dcSApple OSS Distributions
654*2c2f96dcSApple OSS Distributions // Get the vector ready. It starts off soft disabled.
655*2c2f96dcSApple OSS Distributions vector->interruptDisabledSoft = 1;
656*2c2f96dcSApple OSS Distributions vector->interruptRegistered = 1;
657*2c2f96dcSApple OSS Distributions
658*2c2f96dcSApple OSS Distributions interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
659*2c2f96dcSApple OSS Distributions // Move the high water mark if needed
660*2c2f96dcSApple OSS Distributions if (++vectorsRegistered > numVectors) {
661*2c2f96dcSApple OSS Distributions numVectors = vectorsRegistered;
662*2c2f96dcSApple OSS Distributions }
663*2c2f96dcSApple OSS Distributions IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
664*2c2f96dcSApple OSS Distributions
665*2c2f96dcSApple OSS Distributions IOLockUnlock(vector->interruptLock);
666*2c2f96dcSApple OSS Distributions return kIOReturnSuccess;
667*2c2f96dcSApple OSS Distributions }
668*2c2f96dcSApple OSS Distributions
669*2c2f96dcSApple OSS Distributions IOReturn
unregisterInterrupt(IOService * nub,int source)670*2c2f96dcSApple OSS Distributions IOSharedInterruptController::unregisterInterrupt(IOService *nub,
671*2c2f96dcSApple OSS Distributions int source)
672*2c2f96dcSApple OSS Distributions {
673*2c2f96dcSApple OSS Distributions IOInterruptVectorNumber vectorNumber;
674*2c2f96dcSApple OSS Distributions IOInterruptVector *vector;
675*2c2f96dcSApple OSS Distributions IOInterruptState interruptState;
676*2c2f96dcSApple OSS Distributions
677*2c2f96dcSApple OSS Distributions for (vectorNumber = 0; vectorNumber < kIOSharedInterruptControllerDefaultVectors; vectorNumber++) {
678*2c2f96dcSApple OSS Distributions vector = &vectors[vectorNumber];
679*2c2f96dcSApple OSS Distributions
680*2c2f96dcSApple OSS Distributions // Get the lock for this vector.
681*2c2f96dcSApple OSS Distributions IOLockLock(vector->interruptLock);
682*2c2f96dcSApple OSS Distributions
683*2c2f96dcSApple OSS Distributions // Return success if it is not already registered
684*2c2f96dcSApple OSS Distributions if (!vector->interruptRegistered
685*2c2f96dcSApple OSS Distributions || (vector->nub != nub) || (vector->source != source)) {
686*2c2f96dcSApple OSS Distributions IOLockUnlock(vector->interruptLock);
687*2c2f96dcSApple OSS Distributions continue;
688*2c2f96dcSApple OSS Distributions }
689*2c2f96dcSApple OSS Distributions
690*2c2f96dcSApple OSS Distributions // Soft disable the source and the controller too.
691*2c2f96dcSApple OSS Distributions disableInterrupt(nub, source);
692*2c2f96dcSApple OSS Distributions
693*2c2f96dcSApple OSS Distributions // Free vectorData
694*2c2f96dcSApple OSS Distributions IOInterruptSource *interruptSources = nub->_interruptSources;
695*2c2f96dcSApple OSS Distributions OSSafeReleaseNULL(interruptSources[source].vectorData);
696*2c2f96dcSApple OSS Distributions
697*2c2f96dcSApple OSS Distributions // Clear all the storage for the vector except for interruptLock.
698*2c2f96dcSApple OSS Distributions vector->interruptActive = 0;
699*2c2f96dcSApple OSS Distributions vector->interruptDisabledSoft = 0;
700*2c2f96dcSApple OSS Distributions vector->interruptDisabledHard = 0;
701*2c2f96dcSApple OSS Distributions vector->interruptRegistered = 0;
702*2c2f96dcSApple OSS Distributions vector->nub = NULL;
703*2c2f96dcSApple OSS Distributions vector->source = 0;
704*2c2f96dcSApple OSS Distributions vector->handler = NULL;
705*2c2f96dcSApple OSS Distributions vector->target = NULL;
706*2c2f96dcSApple OSS Distributions vector->refCon = NULL;
707*2c2f96dcSApple OSS Distributions
708*2c2f96dcSApple OSS Distributions interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
709*2c2f96dcSApple OSS Distributions vectorsRegistered--;
710*2c2f96dcSApple OSS Distributions IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
711*2c2f96dcSApple OSS Distributions
712*2c2f96dcSApple OSS Distributions // Move along to the next one.
713*2c2f96dcSApple OSS Distributions IOLockUnlock(vector->interruptLock);
714*2c2f96dcSApple OSS Distributions }
715*2c2f96dcSApple OSS Distributions
716*2c2f96dcSApple OSS Distributions // Re-enable the controller if all vectors are enabled.
717*2c2f96dcSApple OSS Distributions if (vectorsEnabled == vectorsRegistered) {
718*2c2f96dcSApple OSS Distributions controllerDisabled = 0;
719*2c2f96dcSApple OSS Distributions provider->enableInterrupt(0);
720*2c2f96dcSApple OSS Distributions }
721*2c2f96dcSApple OSS Distributions
722*2c2f96dcSApple OSS Distributions return kIOReturnSuccess;
723*2c2f96dcSApple OSS Distributions }
724*2c2f96dcSApple OSS Distributions
725*2c2f96dcSApple OSS Distributions IOReturn
getInterruptType(IOService *,int,int * interruptType)726*2c2f96dcSApple OSS Distributions IOSharedInterruptController::getInterruptType(IOService */*nub*/,
727*2c2f96dcSApple OSS Distributions int /*source*/,
728*2c2f96dcSApple OSS Distributions int *interruptType)
729*2c2f96dcSApple OSS Distributions {
730*2c2f96dcSApple OSS Distributions return provider->getInterruptType(0, interruptType);
731*2c2f96dcSApple OSS Distributions }
732*2c2f96dcSApple OSS Distributions
733*2c2f96dcSApple OSS Distributions IOReturn
enableInterrupt(IOService * nub,int source)734*2c2f96dcSApple OSS Distributions IOSharedInterruptController::enableInterrupt(IOService *nub,
735*2c2f96dcSApple OSS Distributions int source)
736*2c2f96dcSApple OSS Distributions {
737*2c2f96dcSApple OSS Distributions IOInterruptSource *interruptSources;
738*2c2f96dcSApple OSS Distributions IOInterruptVectorNumber vectorNumber;
739*2c2f96dcSApple OSS Distributions IOInterruptVector *vector;
740*2c2f96dcSApple OSS Distributions OSData *vectorData;
741*2c2f96dcSApple OSS Distributions IOInterruptState interruptState;
742*2c2f96dcSApple OSS Distributions
743*2c2f96dcSApple OSS Distributions interruptSources = nub->_interruptSources;
744*2c2f96dcSApple OSS Distributions vectorData = interruptSources[source].vectorData;
745*2c2f96dcSApple OSS Distributions vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
746*2c2f96dcSApple OSS Distributions vector = &vectors[vectorNumber];
747*2c2f96dcSApple OSS Distributions
748*2c2f96dcSApple OSS Distributions interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
749*2c2f96dcSApple OSS Distributions if (!vector->interruptDisabledSoft) {
750*2c2f96dcSApple OSS Distributions IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
751*2c2f96dcSApple OSS Distributions return kIOReturnSuccess;
752*2c2f96dcSApple OSS Distributions }
753*2c2f96dcSApple OSS Distributions
754*2c2f96dcSApple OSS Distributions vector->interruptDisabledSoft = 0;
755*2c2f96dcSApple OSS Distributions vectorsEnabled++;
756*2c2f96dcSApple OSS Distributions IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
757*2c2f96dcSApple OSS Distributions
758*2c2f96dcSApple OSS Distributions if (controllerDisabled && (vectorsEnabled == vectorsRegistered)) {
759*2c2f96dcSApple OSS Distributions controllerDisabled = 0;
760*2c2f96dcSApple OSS Distributions provider->enableInterrupt(0);
761*2c2f96dcSApple OSS Distributions }
762*2c2f96dcSApple OSS Distributions
763*2c2f96dcSApple OSS Distributions return kIOReturnSuccess;
764*2c2f96dcSApple OSS Distributions }
765*2c2f96dcSApple OSS Distributions
766*2c2f96dcSApple OSS Distributions IOReturn
disableInterrupt(IOService * nub,int source)767*2c2f96dcSApple OSS Distributions IOSharedInterruptController::disableInterrupt(IOService *nub,
768*2c2f96dcSApple OSS Distributions int source)
769*2c2f96dcSApple OSS Distributions {
770*2c2f96dcSApple OSS Distributions IOInterruptSource *interruptSources;
771*2c2f96dcSApple OSS Distributions IOInterruptVectorNumber vectorNumber;
772*2c2f96dcSApple OSS Distributions IOInterruptVector *vector;
773*2c2f96dcSApple OSS Distributions OSData *vectorData;
774*2c2f96dcSApple OSS Distributions IOInterruptState interruptState;
775*2c2f96dcSApple OSS Distributions
776*2c2f96dcSApple OSS Distributions interruptSources = nub->_interruptSources;
777*2c2f96dcSApple OSS Distributions vectorData = interruptSources[source].vectorData;
778*2c2f96dcSApple OSS Distributions vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
779*2c2f96dcSApple OSS Distributions vector = &vectors[vectorNumber];
780*2c2f96dcSApple OSS Distributions
781*2c2f96dcSApple OSS Distributions interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
782*2c2f96dcSApple OSS Distributions if (!vector->interruptDisabledSoft) {
783*2c2f96dcSApple OSS Distributions vector->interruptDisabledSoft = 1;
784*2c2f96dcSApple OSS Distributions #if !defined(__i386__) && !defined(__x86_64__)
785*2c2f96dcSApple OSS Distributions OSMemoryBarrier();
786*2c2f96dcSApple OSS Distributions #endif
787*2c2f96dcSApple OSS Distributions
788*2c2f96dcSApple OSS Distributions vectorsEnabled--;
789*2c2f96dcSApple OSS Distributions }
790*2c2f96dcSApple OSS Distributions IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
791*2c2f96dcSApple OSS Distributions
792*2c2f96dcSApple OSS Distributions if (!getPlatform()->atInterruptLevel()) {
793*2c2f96dcSApple OSS Distributions while (vector->interruptActive) {
794*2c2f96dcSApple OSS Distributions }
795*2c2f96dcSApple OSS Distributions }
796*2c2f96dcSApple OSS Distributions
797*2c2f96dcSApple OSS Distributions return kIOReturnSuccess;
798*2c2f96dcSApple OSS Distributions }
799*2c2f96dcSApple OSS Distributions
800*2c2f96dcSApple OSS Distributions IOInterruptAction
getInterruptHandlerAddress(void)801*2c2f96dcSApple OSS Distributions IOSharedInterruptController::getInterruptHandlerAddress(void)
802*2c2f96dcSApple OSS Distributions {
803*2c2f96dcSApple OSS Distributions return OSMemberFunctionCast(IOInterruptAction,
804*2c2f96dcSApple OSS Distributions this, &IOSharedInterruptController::handleInterrupt);
805*2c2f96dcSApple OSS Distributions }
806*2c2f96dcSApple OSS Distributions
807*2c2f96dcSApple OSS Distributions IOReturn
handleInterrupt(void *,IOService * nub,int)808*2c2f96dcSApple OSS Distributions IOSharedInterruptController::handleInterrupt(void * /*refCon*/,
809*2c2f96dcSApple OSS Distributions IOService * nub,
810*2c2f96dcSApple OSS Distributions int /*source*/)
811*2c2f96dcSApple OSS Distributions {
812*2c2f96dcSApple OSS Distributions IOInterruptVectorNumber vectorNumber;
813*2c2f96dcSApple OSS Distributions IOInterruptVector *vector;
814*2c2f96dcSApple OSS Distributions
815*2c2f96dcSApple OSS Distributions for (vectorNumber = 0; vectorNumber < numVectors; vectorNumber++) {
816*2c2f96dcSApple OSS Distributions vector = &vectors[vectorNumber];
817*2c2f96dcSApple OSS Distributions
818*2c2f96dcSApple OSS Distributions vector->interruptActive = 1;
819*2c2f96dcSApple OSS Distributions #if !defined(__i386__) && !defined(__x86_64__)
820*2c2f96dcSApple OSS Distributions OSMemoryBarrier();
821*2c2f96dcSApple OSS Distributions #endif
822*2c2f96dcSApple OSS Distributions
823*2c2f96dcSApple OSS Distributions if (!vector->interruptDisabledSoft) {
824*2c2f96dcSApple OSS Distributions // Call the handler if it exists.
825*2c2f96dcSApple OSS Distributions if (vector->interruptRegistered) {
826*2c2f96dcSApple OSS Distributions bool trace = (gIOKitTrace & kIOTraceInterrupts) ? true : false;
827*2c2f96dcSApple OSS Distributions
828*2c2f96dcSApple OSS Distributions if (trace) {
829*2c2f96dcSApple OSS Distributions timeStampInterruptHandlerStart(vectorNumber, vector);
830*2c2f96dcSApple OSS Distributions }
831*2c2f96dcSApple OSS Distributions
832*2c2f96dcSApple OSS Distributions // Call handler.
833*2c2f96dcSApple OSS Distributions vector->handler(vector->target, vector->refCon, vector->nub, vector->source);
834*2c2f96dcSApple OSS Distributions
835*2c2f96dcSApple OSS Distributions if (trace) {
836*2c2f96dcSApple OSS Distributions timeStampInterruptHandlerEnd(vectorNumber, vector);
837*2c2f96dcSApple OSS Distributions }
838*2c2f96dcSApple OSS Distributions }
839*2c2f96dcSApple OSS Distributions }
840*2c2f96dcSApple OSS Distributions
841*2c2f96dcSApple OSS Distributions vector->interruptActive = 0;
842*2c2f96dcSApple OSS Distributions }
843*2c2f96dcSApple OSS Distributions
844*2c2f96dcSApple OSS Distributions // if any of the vectors are dissabled, then dissable this controller.
845*2c2f96dcSApple OSS Distributions IOSimpleLockLock(controllerLock);
846*2c2f96dcSApple OSS Distributions if (vectorsEnabled != vectorsRegistered) {
847*2c2f96dcSApple OSS Distributions nub->disableInterrupt(0);
848*2c2f96dcSApple OSS Distributions controllerDisabled = 1;
849*2c2f96dcSApple OSS Distributions }
850*2c2f96dcSApple OSS Distributions IOSimpleLockUnlock(controllerLock);
851*2c2f96dcSApple OSS Distributions
852*2c2f96dcSApple OSS Distributions return kIOReturnSuccess;
853*2c2f96dcSApple OSS Distributions }
854