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 
735