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