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