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