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
43OSDefineMetaClassAndAbstractStructors(IOInterruptController, IOService);
44
45OSMetaClassDefineReservedUnused(IOInterruptController, 0);
46OSMetaClassDefineReservedUnused(IOInterruptController, 1);
47OSMetaClassDefineReservedUnused(IOInterruptController, 2);
48OSMetaClassDefineReservedUnused(IOInterruptController, 3);
49OSMetaClassDefineReservedUnused(IOInterruptController, 4);
50OSMetaClassDefineReservedUnused(IOInterruptController, 5);
51
52/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
53
54IOReturn 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
217IOReturn 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
259IOReturn 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
279IOReturn 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
308IOReturn 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
330IOReturn 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
347IOInterruptAction IOInterruptController::getInterruptHandlerAddress(void)
348{
349  return 0;
350}
351
352IOReturn 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
361bool IOInterruptController::vectorCanBeShared(IOInterruptVectorNumber /*vectorNumber*/,
362					      IOInterruptVector */*vector*/)
363{
364  return false;
365}
366
367void IOInterruptController::initVector(IOInterruptVectorNumber /*vectorNumber*/,
368				       IOInterruptVector */*vector*/)
369{
370}
371
372int IOInterruptController::getVectorType(IOInterruptVectorNumber /*vectorNumber*/,
373					  IOInterruptVector */*vector*/)
374{
375  return kIOInterruptTypeEdge;
376}
377
378void IOInterruptController::disableVectorHard(IOInterruptVectorNumber /*vectorNumber*/,
379					      IOInterruptVector */*vector*/)
380{
381}
382
383void IOInterruptController::enableVector(IOInterruptVectorNumber /*vectorNumber*/,
384					 IOInterruptVector */*vector*/)
385{
386}
387
388void IOInterruptController::causeVector(IOInterruptVectorNumber /*vectorNumber*/,
389					IOInterruptVector */*vector*/)
390{
391}
392
393
394/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
395
396#undef  super
397#define super IOInterruptController
398
399OSDefineMetaClassAndStructors(IOSharedInterruptController, IOInterruptController);
400
401OSMetaClassDefineReservedUnused(IOSharedInterruptController, 0);
402OSMetaClassDefineReservedUnused(IOSharedInterruptController, 1);
403OSMetaClassDefineReservedUnused(IOSharedInterruptController, 2);
404OSMetaClassDefineReservedUnused(IOSharedInterruptController, 3);
405
406/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
407
408#define kIOSharedInterruptControllerDefaultVectors (128)
409
410IOReturn 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
472IOReturn 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
540IOReturn 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
591IOReturn IOSharedInterruptController::getInterruptType(IOService */*nub*/,
592						       int /*source*/,
593						       int *interruptType)
594{
595  return provider->getInterruptType(0, interruptType);
596}
597
598IOReturn 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
630IOReturn 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
659IOInterruptAction IOSharedInterruptController::getInterruptHandlerAddress(void)
660{
661    return OSMemberFunctionCast(IOInterruptAction,
662			this, &IOSharedInterruptController::handleInterrupt);
663}
664
665IOReturn 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