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