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