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