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
44OSDefineMetaClassAndAbstractStructors(IOInterruptController, IOService);
45
46OSMetaClassDefineReservedUnused(IOInterruptController, 0);
47OSMetaClassDefineReservedUnused(IOInterruptController, 1);
48OSMetaClassDefineReservedUnused(IOInterruptController, 2);
49OSMetaClassDefineReservedUnused(IOInterruptController, 3);
50OSMetaClassDefineReservedUnused(IOInterruptController, 4);
51OSMetaClassDefineReservedUnused(IOInterruptController, 5);
52
53/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
54
55IOReturn 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
218IOReturn 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
260IOReturn 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
280IOReturn 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
312IOReturn 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
337IOReturn 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
354IOInterruptAction IOInterruptController::getInterruptHandlerAddress(void)
355{
356  return 0;
357}
358
359IOReturn 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
368bool IOInterruptController::vectorCanBeShared(IOInterruptVectorNumber /*vectorNumber*/,
369					      IOInterruptVector */*vector*/)
370{
371  return false;
372}
373
374void IOInterruptController::initVector(IOInterruptVectorNumber /*vectorNumber*/,
375				       IOInterruptVector */*vector*/)
376{
377}
378
379int IOInterruptController::getVectorType(IOInterruptVectorNumber /*vectorNumber*/,
380					  IOInterruptVector */*vector*/)
381{
382  return kIOInterruptTypeEdge;
383}
384
385void IOInterruptController::disableVectorHard(IOInterruptVectorNumber /*vectorNumber*/,
386					      IOInterruptVector */*vector*/)
387{
388}
389
390void IOInterruptController::enableVector(IOInterruptVectorNumber /*vectorNumber*/,
391					 IOInterruptVector */*vector*/)
392{
393}
394
395void IOInterruptController::causeVector(IOInterruptVectorNumber /*vectorNumber*/,
396					IOInterruptVector */*vector*/)
397{
398}
399
400
401/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
402
403#undef  super
404#define super IOInterruptController
405
406OSDefineMetaClassAndStructors(IOSharedInterruptController, IOInterruptController);
407
408OSMetaClassDefineReservedUnused(IOSharedInterruptController, 0);
409OSMetaClassDefineReservedUnused(IOSharedInterruptController, 1);
410OSMetaClassDefineReservedUnused(IOSharedInterruptController, 2);
411OSMetaClassDefineReservedUnused(IOSharedInterruptController, 3);
412
413/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
414
415#define kIOSharedInterruptControllerDefaultVectors (128)
416
417IOReturn IOSharedInterruptController::initInterruptController(IOInterruptController *parentController, OSData *parentSource)
418{
419  int      cnt, interruptType;
420  IOReturn error;
421
422  reserved = NULL;
423
424  if (!super::init())
425    return kIOReturnNoResources;
426
427  // Set provider to this so enable/disable nub stuff works.
428  provider = this;
429
430  // Allocate the IOInterruptSource so this can act like a nub.
431  _interruptSources = (IOInterruptSource *)IOMalloc(sizeof(IOInterruptSource));
432  if (_interruptSources == 0) return kIOReturnNoMemory;
433  _numInterruptSources = 1;
434
435  // Set up the IOInterruptSource to point at this.
436  parentController->retain();
437  parentSource->retain();
438  _interruptSources[0].interruptController = parentController;
439  _interruptSources[0].vectorData = parentSource;
440
441  sourceIsLevel = false;
442  error = provider->getInterruptType(0, &interruptType);
443  if (error == kIOReturnSuccess) {
444    if (interruptType & kIOInterruptTypeLevel)
445      sourceIsLevel = true;
446  }
447
448  // Allocate the memory for the vectors
449  numVectors = kIOSharedInterruptControllerDefaultVectors; // For now a constant number.
450  vectors = (IOInterruptVector *)IOMalloc(numVectors * sizeof(IOInterruptVector));
451  if (vectors == NULL) {
452    IOFree(_interruptSources, sizeof(IOInterruptSource));
453    return kIOReturnNoMemory;
454  }
455  bzero(vectors, numVectors * sizeof(IOInterruptVector));
456
457  // Allocate the lock for the controller.
458  controllerLock = IOSimpleLockAlloc();
459  if (controllerLock == 0) return kIOReturnNoResources;
460
461  // Allocate locks for the vectors.
462  for (cnt = 0; cnt < numVectors; cnt++) {
463    vectors[cnt].interruptLock = IOLockAlloc();
464    if (vectors[cnt].interruptLock == NULL) {
465      for (cnt = 0; cnt < numVectors; cnt++) {
466	if (vectors[cnt].interruptLock != NULL)
467	  IOLockFree(vectors[cnt].interruptLock);
468      }
469      return kIOReturnNoResources;
470    }
471  }
472
473  numVectors = 0; // reset the high water mark for used vectors
474  vectorsRegistered = 0;
475  vectorsEnabled = 0;
476  controllerDisabled = 1;
477
478  return kIOReturnSuccess;
479}
480
481IOReturn IOSharedInterruptController::registerInterrupt(IOService *nub,
482							int source,
483							void *target,
484							IOInterruptHandler handler,
485							void *refCon)
486{
487  IOInterruptSource *interruptSources;
488  IOInterruptVectorNumber vectorNumber;
489  IOInterruptVector *vector = 0;
490  OSData            *vectorData;
491  IOInterruptState  interruptState;
492
493  interruptSources = nub->_interruptSources;
494
495  // Find a free vector.
496  vectorNumber = kIOSharedInterruptControllerDefaultVectors;
497  while (vectorsRegistered != kIOSharedInterruptControllerDefaultVectors) {
498    for (vectorNumber = 0; vectorNumber < kIOSharedInterruptControllerDefaultVectors; vectorNumber++) {
499      vector = &vectors[vectorNumber];
500
501      // Get the lock for this vector.
502      IOLockLock(vector->interruptLock);
503
504      // Is it unregistered?
505      if (!vector->interruptRegistered) break;
506
507      // Move along to the next one.
508      IOLockUnlock(vector->interruptLock);
509    }
510
511    if (vectorNumber != kIOSharedInterruptControllerDefaultVectors) break;
512  }
513
514  // Could not find a free one, so give up.
515  if (vectorNumber == kIOSharedInterruptControllerDefaultVectors) {
516    return kIOReturnNoResources;
517  }
518
519  // Create the vectorData for the IOInterruptSource.
520  vectorData = OSData::withBytes(&vectorNumber, sizeof(vectorNumber));
521  if (vectorData == 0) {
522    return kIOReturnNoMemory;
523  }
524
525  // Fill in the IOInterruptSource with the controller's info.
526  interruptSources[source].interruptController = this;
527  interruptSources[source].vectorData = vectorData;
528
529  // Fill in vector with the client's info.
530  vector->handler = handler;
531  vector->nub     = nub;
532  vector->source  = source;
533  vector->target  = target;
534  vector->refCon  = refCon;
535
536  // Get the vector ready.  It starts off soft disabled.
537  vector->interruptDisabledSoft = 1;
538  vector->interruptRegistered   = 1;
539
540  interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
541  // Move the high water mark if needed
542  if (++vectorsRegistered > numVectors) numVectors = vectorsRegistered;
543  IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
544
545  IOLockUnlock(vector->interruptLock);
546  return kIOReturnSuccess;
547}
548
549IOReturn IOSharedInterruptController::unregisterInterrupt(IOService *nub,
550							  int source)
551{
552  IOInterruptVectorNumber vectorNumber;
553  IOInterruptVector *vector;
554  IOInterruptState  interruptState;
555
556  for (vectorNumber = 0; vectorNumber < kIOSharedInterruptControllerDefaultVectors; vectorNumber++) {
557    vector = &vectors[vectorNumber];
558
559    // Get the lock for this vector.
560    IOLockLock(vector->interruptLock);
561
562    // Return success if it is not already registered
563    if (!vector->interruptRegistered
564     || (vector->nub != nub) || (vector->source != source)) {
565        IOLockUnlock(vector->interruptLock);
566        continue;
567    }
568
569    // Soft disable the source and the controller too.
570    disableInterrupt(nub, source);
571
572    // Clear all the storage for the vector except for interruptLock.
573    vector->interruptActive = 0;
574    vector->interruptDisabledSoft = 0;
575    vector->interruptDisabledHard = 0;
576    vector->interruptRegistered = 0;
577    vector->nub = 0;
578    vector->source = 0;
579    vector->handler = 0;
580    vector->target = 0;
581    vector->refCon = 0;
582
583    interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
584    vectorsRegistered--;
585    IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
586
587    // Move along to the next one.
588    IOLockUnlock(vector->interruptLock);
589  }
590
591  // Re-enable the controller if all vectors are enabled.
592  if (vectorsEnabled == vectorsRegistered) {
593    controllerDisabled = 0;
594    provider->enableInterrupt(0);
595  }
596
597  return kIOReturnSuccess;
598}
599
600IOReturn IOSharedInterruptController::getInterruptType(IOService */*nub*/,
601						       int /*source*/,
602						       int *interruptType)
603{
604  return provider->getInterruptType(0, interruptType);
605}
606
607IOReturn IOSharedInterruptController::enableInterrupt(IOService *nub,
608						      int source)
609{
610  IOInterruptSource *interruptSources;
611  IOInterruptVectorNumber vectorNumber;
612  IOInterruptVector *vector;
613  OSData            *vectorData;
614  IOInterruptState  interruptState;
615
616  interruptSources = nub->_interruptSources;
617  vectorData = interruptSources[source].vectorData;
618  vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
619  vector = &vectors[vectorNumber];
620
621  interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
622  if (!vector->interruptDisabledSoft) {
623    IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
624    return kIOReturnSuccess;
625  }
626
627  vector->interruptDisabledSoft = 0;
628  vectorsEnabled++;
629  IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
630
631  if (controllerDisabled && (vectorsEnabled == vectorsRegistered)) {
632    controllerDisabled = 0;
633    provider->enableInterrupt(0);
634  }
635
636  return kIOReturnSuccess;
637}
638
639IOReturn IOSharedInterruptController::disableInterrupt(IOService *nub,
640						       int source)
641{
642  IOInterruptSource *interruptSources;
643  IOInterruptVectorNumber vectorNumber;
644  IOInterruptVector *vector;
645  OSData            *vectorData;
646  IOInterruptState  interruptState;
647
648  interruptSources = nub->_interruptSources;
649  vectorData = interruptSources[source].vectorData;
650  vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
651  vector = &vectors[vectorNumber];
652
653  interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
654  if (!vector->interruptDisabledSoft) {
655    vector->interruptDisabledSoft = 1;
656#if !defined(__i386__) && !defined(__x86_64__)
657    OSMemoryBarrier();
658#endif
659
660    vectorsEnabled--;
661  }
662  IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
663
664  if (!getPlatform()->atInterruptLevel()) {
665    while (vector->interruptActive)
666	{}
667  }
668
669  return kIOReturnSuccess;
670}
671
672IOInterruptAction IOSharedInterruptController::getInterruptHandlerAddress(void)
673{
674    return OSMemberFunctionCast(IOInterruptAction,
675			this, &IOSharedInterruptController::handleInterrupt);
676}
677
678IOReturn IOSharedInterruptController::handleInterrupt(void * /*refCon*/,
679						      IOService * nub,
680						      int /*source*/)
681{
682  IOInterruptVectorNumber vectorNumber;
683  IOInterruptVector *vector;
684
685  for (vectorNumber = 0; vectorNumber < numVectors; vectorNumber++) {
686    vector = &vectors[vectorNumber];
687
688    vector->interruptActive = 1;
689#if !defined(__i386__) && !defined(__x86_64__)
690    OSMemoryBarrier();
691#endif
692
693	if (!vector->interruptDisabledSoft) {
694
695	  // Call the handler if it exists.
696	  if (vector->interruptRegistered) {
697
698		  bool	trace = (gIOKitTrace & kIOTraceInterrupts) ? true : false;
699
700		  if (trace)
701			  IOTimeStampStartConstant(IODBG_INTC(IOINTC_HANDLER),
702									   (uintptr_t) vectorNumber, (uintptr_t) vector->handler, (uintptr_t)vector->target);
703
704		  // Call handler.
705		  vector->handler(vector->target, vector->refCon, vector->nub, vector->source);
706
707		  if (trace)
708			  IOTimeStampEndConstant(IODBG_INTC(IOINTC_HANDLER),
709									 (uintptr_t) vectorNumber, (uintptr_t) vector->handler, (uintptr_t)vector->target);
710
711		}
712	}
713
714    vector->interruptActive = 0;
715  }
716
717  // if any of the vectors are dissabled, then dissable this controller.
718  IOSimpleLockLock(controllerLock);
719  if (vectorsEnabled != vectorsRegistered) {
720    nub->disableInterrupt(0);
721    controllerDisabled = 1;
722  }
723  IOSimpleLockUnlock(controllerLock);
724
725  return kIOReturnSuccess;
726}
727
728