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