1 /*
2  * Copyright (c) 1998-2000 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 
50 #define super IOService
51 
52 OSDefineMetaClassAndAbstractStructors(IOInterruptController, IOService);
53 
54 OSMetaClassDefineReservedUnused(IOInterruptController, 0);
55 OSMetaClassDefineReservedUnused(IOInterruptController, 1);
56 OSMetaClassDefineReservedUnused(IOInterruptController, 2);
57 OSMetaClassDefineReservedUnused(IOInterruptController, 3);
58 OSMetaClassDefineReservedUnused(IOInterruptController, 4);
59 OSMetaClassDefineReservedUnused(IOInterruptController, 5);
60 
61 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
62 
63 IOReturn 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;
76   IOOptionBits      options;
77   bool              canBeShared, shouldBeShared, wasAlreadyRegisterd;
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 
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,
101   // register as a shared interrupt.
102   if (wasAlreadyRegisterd || shouldBeShared) {
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 
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       }
122 
123       // Initialize the new shared interrupt controller.
124       error = vector->sharedController->initInterruptController(this, vectorData);
125       // If the IOSharedInterruptController could not be initalized,
126       // if needed, put the original consumer's interrupt back to normal and
127       // get rid of whats left of the shared controller.
128       if (error != kIOReturnSuccess) {
129 	if (wasAlreadyRegisterd) enableInterrupt(originalNub, originalSource);
130         vector->sharedController->release();
131         vector->sharedController = 0;
132         IOUnlock(vector->interruptLock);
133         return error;
134       }
135 
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 	}
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 
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);
179 
180       // Make the interrupt really hard disabled.
181       vector->interruptDisabledSoft = 1;
182       vector->interruptDisabledHard = 1;
183       vector->interruptRegistered   = 1;
184 
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 
214 IOReturn 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 
256 IOReturn 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 
276 IOReturn 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;
290 #if __ppc__
291     sync();
292     isync();
293 #endif
294 
295     if (!getPlatform()->atInterruptLevel()) {
296       while (vector->interruptActive);
297 #if __ppc__
298       isync();
299 #endif
300     }
301     if (vector->interruptDisabledHard) {
302       vector->interruptDisabledHard = 0;
303 
304       enableVector(vectorNumber, vector);
305     }
306   }
307 
308   return kIOReturnSuccess;
309 }
310 
311 IOReturn 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 
339 IOReturn 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 
356 IOInterruptAction IOInterruptController::getInterruptHandlerAddress(void)
357 {
358   return 0;
359 }
360 
361 IOReturn 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 
370 bool IOInterruptController::vectorCanBeShared(long /*vectorNumber*/,
371 					      IOInterruptVector */*vector*/)
372 {
373   return false;
374 }
375 
376 void IOInterruptController::initVector(long /*vectorNumber*/,
377 				       IOInterruptVector */*vector*/)
378 {
379 }
380 
381 int IOInterruptController::getVectorType(long /*vectorNumber*/,
382 					  IOInterruptVector */*vector*/)
383 {
384   return kIOInterruptTypeEdge;
385 }
386 
387 void IOInterruptController::disableVectorHard(long /*vectorNumber*/,
388 					      IOInterruptVector */*vector*/)
389 {
390 }
391 
392 void IOInterruptController::enableVector(long /*vectorNumber*/,
393 					 IOInterruptVector */*vector*/)
394 {
395 }
396 
397 void IOInterruptController::causeVector(long /*vectorNumber*/,
398 					IOInterruptVector */*vector*/)
399 {
400 }
401 
402 
403 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
404 
405 #undef  super
406 #define super IOInterruptController
407 
408 OSDefineMetaClassAndStructors(IOSharedInterruptController, IOInterruptController);
409 
410 OSMetaClassDefineReservedUnused(IOSharedInterruptController, 0);
411 OSMetaClassDefineReservedUnused(IOSharedInterruptController, 1);
412 OSMetaClassDefineReservedUnused(IOSharedInterruptController, 2);
413 OSMetaClassDefineReservedUnused(IOSharedInterruptController, 3);
414 
415 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
416 
417 #define kIOSharedInterruptControllerDefaultVectors (128)
418 
419 IOReturn 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.
436   parentController->retain();
437   parentSource->retain();
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
449   numVectors = kIOSharedInterruptControllerDefaultVectors; // For now a constant number.
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 
473   numVectors = 0; // reset the high water mark for used vectors
474   vectorsRegistered = 0;
475   vectorsEnabled = 0;
476   controllerDisabled = 1;
477 
478   return kIOReturnSuccess;
479 }
480 
481 IOReturn 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.
496   vectorNumber = kIOSharedInterruptControllerDefaultVectors;
497   while (vectorsRegistered != kIOSharedInterruptControllerDefaultVectors) {
498     for (vectorNumber = 0; vectorNumber < kIOSharedInterruptControllerDefaultVectors; vectorNumber++) {
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 
511     if (vectorNumber != kIOSharedInterruptControllerDefaultVectors) break;
512   }
513 
514   // Could not find a free one, so give up.
515   if (vectorNumber == kIOSharedInterruptControllerDefaultVectors) {
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 
536   // Get the vector ready.  It starts off soft disabled.
537   vector->interruptDisabledSoft = 1;
538   vector->interruptRegistered   = 1;
539 
540   interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
541   // Move the high water mark if needed
542   if (++vectorsRegistered > numVectors) numVectors = vectorsRegistered;
543   IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
544 
545   IOUnlock(vector->interruptLock);
546   return kIOReturnSuccess;
547 }
548 
549 IOReturn IOSharedInterruptController::unregisterInterrupt(IOService *nub,
550 							  int source)
551 {
552   IOInterruptSource *interruptSources;
553   long              vectorNumber;
554   IOInterruptVector *vector;
555   OSData            *vectorData;
556   IOInterruptState  interruptState;
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 
572   // Soft disable the source and the controller too.
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);
591 
592   // Re-enable the controller if all vectors are enabled.
593   if (vectorsEnabled == vectorsRegistered) {
594     controllerDisabled = 0;
595     provider->enableInterrupt(0);
596   }
597 
598   return kIOReturnSuccess;
599 }
600 
601 IOReturn IOSharedInterruptController::getInterruptType(IOService */*nub*/,
602 						       int /*source*/,
603 						       int *interruptType)
604 {
605   return provider->getInterruptType(0, interruptType);
606 }
607 
608 IOReturn IOSharedInterruptController::enableInterrupt(IOService *nub,
609 						      int source)
610 {
611   IOInterruptSource *interruptSources;
612   long              vectorNumber;
613   IOInterruptVector *vector;
614   OSData            *vectorData;
615   IOInterruptState  interruptState;
616 
617   interruptSources = nub->_interruptSources;
618   vectorData = interruptSources[source].vectorData;
619   vectorNumber = *(long *)vectorData->getBytesNoCopy();
620   vector = &vectors[vectorNumber];
621 
622   interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
623   if (!vector->interruptDisabledSoft) {
624     IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
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);
635   }
636 
637   return kIOReturnSuccess;
638 }
639 
640 IOReturn IOSharedInterruptController::disableInterrupt(IOService *nub,
641 						       int source)
642 {
643   IOInterruptSource *interruptSources;
644   long              vectorNumber;
645   IOInterruptVector *vector;
646   OSData            *vectorData;
647   IOInterruptState  interruptState;
648 
649   interruptSources = nub->_interruptSources;
650   vectorData = interruptSources[source].vectorData;
651   vectorNumber = *(long *)vectorData->getBytesNoCopy();
652   vector = &vectors[vectorNumber];
653 
654   interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
655   if (!vector->interruptDisabledSoft) {
656     vector->interruptDisabledSoft = 1;
657 #if __ppc__
658     sync();
659     isync();
660 #endif
661     vectorsEnabled--;
662   }
663   IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
664 
665   if (!getPlatform()->atInterruptLevel()) {
666     while (vector->interruptActive);
667 #if __ppc__
668     isync();
669 #endif
670   }
671 
672   return kIOReturnSuccess;
673 }
674 
675 IOInterruptAction IOSharedInterruptController::getInterruptHandlerAddress(void)
676 {
677     return OSMemberFunctionCast(IOInterruptAction,
678 			this, &IOSharedInterruptController::handleInterrupt);
679 }
680 
681 IOReturn 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 
722