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
registerInterrupt(IOService * nub,int source,void * target,IOInterruptHandler handler,void * refCon)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
unregisterInterrupt(IOService * nub,int source)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
getInterruptType(IOService * nub,int source,int * interruptType)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
enableInterrupt(IOService * nub,int source)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
disableInterrupt(IOService * nub,int source)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
causeInterrupt(IOService * nub,int source)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
getInterruptHandlerAddress(void)381 IOInterruptController::getInterruptHandlerAddress(void)
382 {
383 	return NULL;
384 }
385 
386 IOReturn
handleInterrupt(void * refCon,IOService * nub,int source)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
vectorCanBeShared(IOInterruptVectorNumber,IOInterruptVector *)397 IOInterruptController::vectorCanBeShared(IOInterruptVectorNumber /*vectorNumber*/,
398     IOInterruptVector */*vector*/)
399 {
400 	return false;
401 }
402 
403 void
initVector(IOInterruptVectorNumber,IOInterruptVector *)404 IOInterruptController::initVector(IOInterruptVectorNumber /*vectorNumber*/,
405     IOInterruptVector */*vector*/)
406 {
407 }
408 
409 int
getVectorType(IOInterruptVectorNumber,IOInterruptVector *)410 IOInterruptController::getVectorType(IOInterruptVectorNumber /*vectorNumber*/,
411     IOInterruptVector */*vector*/)
412 {
413 	return kIOInterruptTypeEdge;
414 }
415 
416 void
disableVectorHard(IOInterruptVectorNumber,IOInterruptVector *)417 IOInterruptController::disableVectorHard(IOInterruptVectorNumber /*vectorNumber*/,
418     IOInterruptVector */*vector*/)
419 {
420 }
421 
422 void
enableVector(IOInterruptVectorNumber,IOInterruptVector *)423 IOInterruptController::enableVector(IOInterruptVectorNumber /*vectorNumber*/,
424     IOInterruptVector */*vector*/)
425 {
426 }
427 
428 void
causeVector(IOInterruptVectorNumber,IOInterruptVector *)429 IOInterruptController::causeVector(IOInterruptVectorNumber /*vectorNumber*/,
430     IOInterruptVector */*vector*/)
431 {
432 }
433 
434 void
setCPUInterruptProperties(IOService *)435 IOInterruptController::setCPUInterruptProperties(IOService */*service*/)
436 {
437 }
438 
439 void
sendIPI(unsigned int,bool)440 IOInterruptController::sendIPI(unsigned int /*cpu_id*/, bool /*deferred*/)
441 {
442 }
443 
444 void
cancelDeferredIPI(unsigned int)445 IOInterruptController::cancelDeferredIPI(unsigned int /*cpu_id*/)
446 {
447 }
448 
449 void
timeStampSpuriousInterrupt(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
timeStampInterruptHandlerInternal(bool isStart,IOInterruptVectorNumber vectorNumber,IOInterruptVector * vector)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 SCHED_HYGIENE_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 SCHED_HYGIENE_DEBUG
491 		ml_irq_debug_end();
492 #endif
493 	}
494 }
495 
496 void
timeStampInterruptHandlerStart(IOInterruptVectorNumber vectorNumber,IOInterruptVector * vector)497 IOInterruptController::timeStampInterruptHandlerStart(IOInterruptVectorNumber vectorNumber, IOInterruptVector *vector)
498 {
499 	timeStampInterruptHandlerInternal(true, vectorNumber, vector);
500 }
501 
502 void
timeStampInterruptHandlerEnd(IOInterruptVectorNumber vectorNumber,IOInterruptVector * vector)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
initInterruptController(IOInterruptController * parentController,OSData * parentSource)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
registerInterrupt(IOService * nub,int source,void * target,IOInterruptHandler handler,void * refCon)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
unregisterInterrupt(IOService * nub,int source)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 		// Free vectorData
694 		IOInterruptSource *interruptSources = nub->_interruptSources;
695 		OSSafeReleaseNULL(interruptSources[source].vectorData);
696 
697 		// Clear all the storage for the vector except for interruptLock.
698 		vector->interruptActive = 0;
699 		vector->interruptDisabledSoft = 0;
700 		vector->interruptDisabledHard = 0;
701 		vector->interruptRegistered = 0;
702 		vector->nub = NULL;
703 		vector->source = 0;
704 		vector->handler = NULL;
705 		vector->target = NULL;
706 		vector->refCon = NULL;
707 
708 		interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
709 		vectorsRegistered--;
710 		IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
711 
712 		// Move along to the next one.
713 		IOLockUnlock(vector->interruptLock);
714 	}
715 
716 	// Re-enable the controller if all vectors are enabled.
717 	if (vectorsEnabled == vectorsRegistered) {
718 		controllerDisabled = 0;
719 		provider->enableInterrupt(0);
720 	}
721 
722 	return kIOReturnSuccess;
723 }
724 
725 IOReturn
getInterruptType(IOService *,int,int * interruptType)726 IOSharedInterruptController::getInterruptType(IOService */*nub*/,
727     int /*source*/,
728     int *interruptType)
729 {
730 	return provider->getInterruptType(0, interruptType);
731 }
732 
733 IOReturn
enableInterrupt(IOService * nub,int source)734 IOSharedInterruptController::enableInterrupt(IOService *nub,
735     int source)
736 {
737 	IOInterruptSource *interruptSources;
738 	IOInterruptVectorNumber vectorNumber;
739 	IOInterruptVector *vector;
740 	OSData            *vectorData;
741 	IOInterruptState  interruptState;
742 
743 	interruptSources = nub->_interruptSources;
744 	vectorData = interruptSources[source].vectorData;
745 	vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
746 	vector = &vectors[vectorNumber];
747 
748 	interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
749 	if (!vector->interruptDisabledSoft) {
750 		IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
751 		return kIOReturnSuccess;
752 	}
753 
754 	vector->interruptDisabledSoft = 0;
755 	vectorsEnabled++;
756 	IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
757 
758 	if (controllerDisabled && (vectorsEnabled == vectorsRegistered)) {
759 		controllerDisabled = 0;
760 		provider->enableInterrupt(0);
761 	}
762 
763 	return kIOReturnSuccess;
764 }
765 
766 IOReturn
disableInterrupt(IOService * nub,int source)767 IOSharedInterruptController::disableInterrupt(IOService *nub,
768     int source)
769 {
770 	IOInterruptSource *interruptSources;
771 	IOInterruptVectorNumber vectorNumber;
772 	IOInterruptVector *vector;
773 	OSData            *vectorData;
774 	IOInterruptState  interruptState;
775 
776 	interruptSources = nub->_interruptSources;
777 	vectorData = interruptSources[source].vectorData;
778 	vectorNumber = *(IOInterruptVectorNumber *)vectorData->getBytesNoCopy();
779 	vector = &vectors[vectorNumber];
780 
781 	interruptState = IOSimpleLockLockDisableInterrupt(controllerLock);
782 	if (!vector->interruptDisabledSoft) {
783 		vector->interruptDisabledSoft = 1;
784 #if !defined(__i386__) && !defined(__x86_64__)
785 		OSMemoryBarrier();
786 #endif
787 
788 		vectorsEnabled--;
789 	}
790 	IOSimpleLockUnlockEnableInterrupt(controllerLock, interruptState);
791 
792 	if (!getPlatform()->atInterruptLevel()) {
793 		while (vector->interruptActive) {
794 		}
795 	}
796 
797 	return kIOReturnSuccess;
798 }
799 
800 IOInterruptAction
getInterruptHandlerAddress(void)801 IOSharedInterruptController::getInterruptHandlerAddress(void)
802 {
803 	return OSMemberFunctionCast(IOInterruptAction,
804 	           this, &IOSharedInterruptController::handleInterrupt);
805 }
806 
807 IOReturn
handleInterrupt(void *,IOService * nub,int)808 IOSharedInterruptController::handleInterrupt(void * /*refCon*/,
809     IOService * nub,
810     int /*source*/)
811 {
812 	IOInterruptVectorNumber vectorNumber;
813 	IOInterruptVector *vector;
814 
815 	for (vectorNumber = 0; vectorNumber < numVectors; vectorNumber++) {
816 		vector = &vectors[vectorNumber];
817 
818 		vector->interruptActive = 1;
819 #if !defined(__i386__) && !defined(__x86_64__)
820 		OSMemoryBarrier();
821 #endif
822 
823 		if (!vector->interruptDisabledSoft) {
824 			// Call the handler if it exists.
825 			if (vector->interruptRegistered) {
826 				bool trace = (gIOKitTrace & kIOTraceInterrupts) ? true : false;
827 
828 				if (trace) {
829 					timeStampInterruptHandlerStart(vectorNumber, vector);
830 				}
831 
832 				// Call handler.
833 				vector->handler(vector->target, vector->refCon, vector->nub, vector->source);
834 
835 				if (trace) {
836 					timeStampInterruptHandlerEnd(vectorNumber, vector);
837 				}
838 			}
839 		}
840 
841 		vector->interruptActive = 0;
842 	}
843 
844 	// if any of the vectors are dissabled, then dissable this controller.
845 	IOSimpleLockLock(controllerLock);
846 	if (vectorsEnabled != vectorsRegistered) {
847 		nub->disableInterrupt(0);
848 		controllerDisabled = 1;
849 	}
850 	IOSimpleLockUnlock(controllerLock);
851 
852 	return kIOReturnSuccess;
853 }
854