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 OSMetaClassDefineReservedUsedX86(IOInterruptController, 0);
47 OSMetaClassDefineReservedUsedX86(IOInterruptController, 1);
48 OSMetaClassDefineReservedUsedX86(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 			// A DSB ISH on ARM is needed to make sure the vector data are
322 			// properly initialized before the MMIO enabling the interrupts
323 			// in hardware. OSMemoryBarrier(), which maps to DMB, is not
324 			// sufficient here as the CPUs are not consumers of the device
325 			// write. Hence, the DMB does not guarantee the CPUs won't see an
326 			// interrupt before it initalizes the vector data properly.
327 			OSSynchronizeIO();
328 
329 			enableVector(vectorNumber, vector);
330 		}
331 	}
332 
333 	return kIOReturnSuccess;
334 }
335 
336 IOReturn
337 IOInterruptController::disableInterrupt(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 	vector->interruptDisabledSoft = 1;
350 #if !defined(__i386__) && !defined(__x86_64__)
351 	OSMemoryBarrier();
352 #endif
353 
354 	if (!getPlatform()->atInterruptLevel()) {
355 		while (vector->interruptActive) {
356 		}
357 	}
358 
359 	return kIOReturnSuccess;
360 }
361 
362 IOReturn
363 IOInterruptController::causeInterrupt(IOService *nub, int source)
364 {
365 	IOInterruptSource *interruptSources;
366 	IOInterruptVectorNumber vectorNumber;
367 	IOInterruptVector *vector;
368 	OSData            *vectorData;
369 
370 	interruptSources = nub->_interruptSources;
371 	vectorData = interruptSources[source].vectorData;
372 	vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
373 	vector = &vectors[vectorNumber];
374 
375 	causeVector(vectorNumber, vector);
376 
377 	return kIOReturnSuccess;
378 }
379 
380 IOInterruptAction
381 IOInterruptController::getInterruptHandlerAddress(void)
382 {
383 	return NULL;
384 }
385 
386 IOReturn
387 IOInterruptController::handleInterrupt(void *refCon, IOService *nub,
388     int source)
389 {
390 	return kIOReturnInvalid;
391 }
392 
393 
394 // Methods to be overridden for simplifed interrupt controller subclasses.
395 
396 bool
397 IOInterruptController::vectorCanBeShared(IOInterruptVectorNumber /*vectorNumber*/,
398     IOInterruptVector */*vector*/)
399 {
400 	return false;
401 }
402 
403 void
404 IOInterruptController::initVector(IOInterruptVectorNumber /*vectorNumber*/,
405     IOInterruptVector */*vector*/)
406 {
407 }
408 
409 int
410 IOInterruptController::getVectorType(IOInterruptVectorNumber /*vectorNumber*/,
411     IOInterruptVector */*vector*/)
412 {
413 	return kIOInterruptTypeEdge;
414 }
415 
416 void
417 IOInterruptController::disableVectorHard(IOInterruptVectorNumber /*vectorNumber*/,
418     IOInterruptVector */*vector*/)
419 {
420 }
421 
422 void
423 IOInterruptController::enableVector(IOInterruptVectorNumber /*vectorNumber*/,
424     IOInterruptVector */*vector*/)
425 {
426 }
427 
428 void
429 IOInterruptController::causeVector(IOInterruptVectorNumber /*vectorNumber*/,
430     IOInterruptVector */*vector*/)
431 {
432 }
433 
434 void
435 IOInterruptController::setCPUInterruptProperties(IOService */*service*/)
436 {
437 }
438 
439 void
440 IOInterruptController::sendIPI(unsigned int /*cpu_id*/, bool /*deferred*/)
441 {
442 }
443 
444 void
445 IOInterruptController::cancelDeferredIPI(unsigned int /*cpu_id*/)
446 {
447 }
448 
449 void
450 IOInterruptController::timeStampSpuriousInterrupt(void)
451 {
452 	uint64_t providerID = 0;
453 	IOService * provider = getProvider();
454 
455 	if (provider) {
456 		providerID = provider->getRegistryEntryID();
457 	}
458 
459 	IOTimeStampConstant(IODBG_INTC(IOINTC_SPURIOUS), providerID);
460 }
461 
462 void
463 IOInterruptController::timeStampInterruptHandlerInternal(bool isStart, IOInterruptVectorNumber vectorNumber, IOInterruptVector *vector)
464 {
465 	uint64_t providerID = 0;
466 	vm_offset_t unslidHandler = 0;
467 	vm_offset_t unslidTarget = 0;
468 
469 	IOService * provider = getProvider();
470 
471 	if (provider) {
472 		providerID = provider->getRegistryEntryID();
473 	}
474 
475 	if (vector) {
476 		unslidHandler = VM_KERNEL_UNSLIDE((vm_offset_t)vector->handler);
477 		unslidTarget = VM_KERNEL_UNSLIDE_OR_PERM((vm_offset_t)vector->target);
478 	}
479 
480 
481 	if (isStart) {
482 #if INTERRUPT_MASKED_DEBUG
483 		ml_irq_debug_start((uintptr_t)vector->handler, (uintptr_t)vector);
484 #endif
485 		IOTimeStampStartConstant(IODBG_INTC(IOINTC_HANDLER), (uintptr_t)vectorNumber, (uintptr_t)unslidHandler,
486 		    (uintptr_t)unslidTarget, (uintptr_t)providerID);
487 	} else {
488 		IOTimeStampEndConstant(IODBG_INTC(IOINTC_HANDLER), (uintptr_t)vectorNumber, (uintptr_t)unslidHandler,
489 		    (uintptr_t)unslidTarget, (uintptr_t)providerID);
490 #if INTERRUPT_MASKED_DEBUG
491 		ml_irq_debug_end();
492 #endif
493 	}
494 }
495 
496 void
497 IOInterruptController::timeStampInterruptHandlerStart(IOInterruptVectorNumber vectorNumber, IOInterruptVector *vector)
498 {
499 	timeStampInterruptHandlerInternal(true, vectorNumber, vector);
500 }
501 
502 void
503 IOInterruptController::timeStampInterruptHandlerEnd(IOInterruptVectorNumber vectorNumber, IOInterruptVector *vector)
504 {
505 	timeStampInterruptHandlerInternal(false, vectorNumber, vector);
506 }
507 
508 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
509 
510 #undef  super
511 #define super IOInterruptController
512 
513 OSDefineMetaClassAndStructors(IOSharedInterruptController, IOInterruptController);
514 
515 OSMetaClassDefineReservedUnused(IOSharedInterruptController, 0);
516 OSMetaClassDefineReservedUnused(IOSharedInterruptController, 1);
517 OSMetaClassDefineReservedUnused(IOSharedInterruptController, 2);
518 OSMetaClassDefineReservedUnused(IOSharedInterruptController, 3);
519 
520 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
521 
522 #define kIOSharedInterruptControllerDefaultVectors (128)
523 
524 IOReturn
525 IOSharedInterruptController::initInterruptController(IOInterruptController *parentController, OSData *parentSource)
526 {
527 	int      cnt, interruptType;
528 	IOReturn error;
529 
530 	if (!super::init()) {
531 		return kIOReturnNoResources;
532 	}
533 
534 	// Set provider to this so enable/disable nub stuff works.
535 	provider = this;
536 
537 	// Allocate the IOInterruptSource so this can act like a nub.
538 	_interruptSources = IONew(IOInterruptSource, 1);
539 	if (_interruptSources == NULL) {
540 		return kIOReturnNoMemory;
541 	}
542 	_numInterruptSources = 1;
543 
544 	// Set up the IOInterruptSource to point at this.
545 	parentController->retain();
546 	parentSource->retain();
547 	_interruptSources[0].interruptController = parentController;
548 	_interruptSources[0].vectorData = parentSource;
549 
550 	sourceIsLevel = false;
551 	error = provider->getInterruptType(0, &interruptType);
552 	if (error == kIOReturnSuccess) {
553 		if (interruptType & kIOInterruptTypeLevel) {
554 			sourceIsLevel = true;
555 		}
556 	}
557 
558 	// Allocate the memory for the vectors
559 	numVectors = kIOSharedInterruptControllerDefaultVectors; // For now a constant number.
560 	vectors = IONewZero(IOInterruptVector, numVectors);
561 	if (vectors == NULL) {
562 		IODelete(_interruptSources, IOInterruptSource, 1);
563 		return kIOReturnNoMemory;
564 	}
565 
566 	// Allocate the lock for the controller.
567 	controllerLock = IOSimpleLockAlloc();
568 	if (controllerLock == NULL) {
569 		return kIOReturnNoResources;
570 	}
571 
572 	// Allocate locks for the vectors.
573 	for (cnt = 0; cnt < numVectors; cnt++) {
574 		vectors[cnt].interruptLock = IOLockAlloc();
575 		if (vectors[cnt].interruptLock == NULL) {
576 			for (cnt = 0; cnt < numVectors; cnt++) {
577 				if (vectors[cnt].interruptLock != NULL) {
578 					IOLockFree(vectors[cnt].interruptLock);
579 				}
580 			}
581 			return kIOReturnNoResources;
582 		}
583 	}
584 
585 	numVectors = 0; // reset the high water mark for used vectors
586 	vectorsRegistered = 0;
587 	vectorsEnabled = 0;
588 	controllerDisabled = 1;
589 
590 	return kIOReturnSuccess;
591 }
592 
593 IOReturn
594 IOSharedInterruptController::registerInterrupt(IOService *nub,
595     int source,
596     void *target,
597     IOInterruptHandler handler,
598     void *refCon)
599 {
600 	IOInterruptSource *interruptSources;
601 	IOInterruptVectorNumber vectorNumber;
602 	IOInterruptVector *vector = NULL;
603 	OSData            *vectorData;
604 	IOInterruptState  interruptState;
605 
606 	interruptSources = nub->_interruptSources;
607 
608 	// Find a free vector.
609 	vectorNumber = kIOSharedInterruptControllerDefaultVectors;
610 	while (vectorsRegistered != kIOSharedInterruptControllerDefaultVectors) {
611 		for (vectorNumber = 0; vectorNumber < kIOSharedInterruptControllerDefaultVectors; vectorNumber++) {
612 			vector = &vectors[vectorNumber];
613 
614 			// Get the lock for this vector.
615 			IOLockLock(vector->interruptLock);
616 
617 			// Is it unregistered?
618 			if (!vector->interruptRegistered) {
619 				break;
620 			}
621 
622 			// Move along to the next one.
623 			IOLockUnlock(vector->interruptLock);
624 		}
625 
626 		if (vectorNumber != kIOSharedInterruptControllerDefaultVectors) {
627 			break;
628 		}
629 	}
630 
631 	// Could not find a free one, so give up.
632 	if (vectorNumber == kIOSharedInterruptControllerDefaultVectors) {
633 		return kIOReturnNoResources;
634 	}
635 
636 	// Create the vectorData for the IOInterruptSource.
637 	vectorData = OSData::withValue(vectorNumber);
638 	if (vectorData == NULL) {
639 		IOLockUnlock(vector->interruptLock);
640 		return kIOReturnNoMemory;
641 	}
642 
643 	// Fill in the IOInterruptSource with the controller's info.
644 	interruptSources[source].interruptController = this;
645 	interruptSources[source].vectorData = vectorData;
646 
647 	// Fill in vector with the client's info.
648 	vector->handler = handler;
649 	vector->nub     = nub;
650 	vector->source  = source;
651 	vector->target  = target;
652 	vector->refCon  = refCon;
653 
654 	// Get the vector ready.  It starts off soft disabled.
655 	vector->interruptDisabledSoft = 1;
656 	vector->interruptRegistered   = 1;
657 
658 	interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
659 	// Move the high water mark if needed
660 	if (++vectorsRegistered > numVectors) {
661 		numVectors = vectorsRegistered;
662 	}
663 	IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
664 
665 	IOLockUnlock(vector->interruptLock);
666 	return kIOReturnSuccess;
667 }
668 
669 IOReturn
670 IOSharedInterruptController::unregisterInterrupt(IOService *nub,
671     int source)
672 {
673 	IOInterruptVectorNumber vectorNumber;
674 	IOInterruptVector *vector;
675 	IOInterruptState  interruptState;
676 
677 	for (vectorNumber = 0; vectorNumber < kIOSharedInterruptControllerDefaultVectors; vectorNumber++) {
678 		vector = &vectors[vectorNumber];
679 
680 		// Get the lock for this vector.
681 		IOLockLock(vector->interruptLock);
682 
683 		// Return success if it is not already registered
684 		if (!vector->interruptRegistered
685 		    || (vector->nub != nub) || (vector->source != source)) {
686 			IOLockUnlock(vector->interruptLock);
687 			continue;
688 		}
689 
690 		// Soft disable the source and the controller too.
691 		disableInterrupt(nub, source);
692 
693 		// Clear all the storage for the vector except for interruptLock.
694 		vector->interruptActive = 0;
695 		vector->interruptDisabledSoft = 0;
696 		vector->interruptDisabledHard = 0;
697 		vector->interruptRegistered = 0;
698 		vector->nub = NULL;
699 		vector->source = 0;
700 		vector->handler = NULL;
701 		vector->target = NULL;
702 		vector->refCon = NULL;
703 
704 		interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
705 		vectorsRegistered--;
706 		IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
707 
708 		// Move along to the next one.
709 		IOLockUnlock(vector->interruptLock);
710 	}
711 
712 	// Re-enable the controller if all vectors are enabled.
713 	if (vectorsEnabled == vectorsRegistered) {
714 		controllerDisabled = 0;
715 		provider->enableInterrupt(0);
716 	}
717 
718 	return kIOReturnSuccess;
719 }
720 
721 IOReturn
722 IOSharedInterruptController::getInterruptType(IOService */*nub*/,
723     int /*source*/,
724     int *interruptType)
725 {
726 	return provider->getInterruptType(0, interruptType);
727 }
728 
729 IOReturn
730 IOSharedInterruptController::enableInterrupt(IOService *nub,
731     int source)
732 {
733 	IOInterruptSource *interruptSources;
734 	IOInterruptVectorNumber vectorNumber;
735 	IOInterruptVector *vector;
736 	OSData            *vectorData;
737 	IOInterruptState  interruptState;
738 
739 	interruptSources = nub->_interruptSources;
740 	vectorData = interruptSources[source].vectorData;
741 	vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
742 	vector = &vectors[vectorNumber];
743 
744 	interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
745 	if (!vector->interruptDisabledSoft) {
746 		IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
747 		return kIOReturnSuccess;
748 	}
749 
750 	vector->interruptDisabledSoft = 0;
751 	vectorsEnabled++;
752 	IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
753 
754 	if (controllerDisabled && (vectorsEnabled == vectorsRegistered)) {
755 		controllerDisabled = 0;
756 		provider->enableInterrupt(0);
757 	}
758 
759 	return kIOReturnSuccess;
760 }
761 
762 IOReturn
763 IOSharedInterruptController::disableInterrupt(IOService *nub,
764     int source)
765 {
766 	IOInterruptSource *interruptSources;
767 	IOInterruptVectorNumber vectorNumber;
768 	IOInterruptVector *vector;
769 	OSData            *vectorData;
770 	IOInterruptState  interruptState;
771 
772 	interruptSources = nub->_interruptSources;
773 	vectorData = interruptSources[source].vectorData;
774 	vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
775 	vector = &vectors[vectorNumber];
776 
777 	interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
778 	if (!vector->interruptDisabledSoft) {
779 		vector->interruptDisabledSoft = 1;
780 #if !defined(__i386__) && !defined(__x86_64__)
781 		OSMemoryBarrier();
782 #endif
783 
784 		vectorsEnabled--;
785 	}
786 	IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
787 
788 	if (!getPlatform()->atInterruptLevel()) {
789 		while (vector->interruptActive) {
790 		}
791 	}
792 
793 	return kIOReturnSuccess;
794 }
795 
796 IOInterruptAction
797 IOSharedInterruptController::getInterruptHandlerAddress(void)
798 {
799 	return OSMemberFunctionCast(IOInterruptAction,
800 	           this, &IOSharedInterruptController::handleInterrupt);
801 }
802 
803 IOReturn
804 IOSharedInterruptController::handleInterrupt(void * /*refCon*/,
805     IOService * nub,
806     int /*source*/)
807 {
808 	IOInterruptVectorNumber vectorNumber;
809 	IOInterruptVector *vector;
810 
811 	for (vectorNumber = 0; vectorNumber < numVectors; vectorNumber++) {
812 		vector = &vectors[vectorNumber];
813 
814 		vector->interruptActive = 1;
815 #if !defined(__i386__) && !defined(__x86_64__)
816 		OSMemoryBarrier();
817 #endif
818 
819 		if (!vector->interruptDisabledSoft) {
820 			// Call the handler if it exists.
821 			if (vector->interruptRegistered) {
822 				bool trace = (gIOKitTrace & kIOTraceInterrupts) ? true : false;
823 
824 				if (trace) {
825 					timeStampInterruptHandlerStart(vectorNumber, vector);
826 				}
827 
828 				// Call handler.
829 				vector->handler(vector->target, vector->refCon, vector->nub, vector->source);
830 
831 				if (trace) {
832 					timeStampInterruptHandlerEnd(vectorNumber, vector);
833 				}
834 			}
835 		}
836 
837 		vector->interruptActive = 0;
838 	}
839 
840 	// if any of the vectors are dissabled, then dissable this controller.
841 	IOSimpleLockLock(controllerLock);
842 	if (vectorsEnabled != vectorsRegistered) {
843 		nub->disableInterrupt(0);
844 		controllerDisabled = 1;
845 	}
846 	IOSimpleLockUnlock(controllerLock);
847 
848 	return kIOReturnSuccess;
849 }
850