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