2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
37 #include <ppc/proc_reg.h>
40 #include <IOKit/IOLib.h>
41 #include <IOKit/IOService.h>
42 #include <IOKit/IOPlatformExpert.h>
43 #include <IOKit/IODeviceTreeSupport.h>
44 #include <IOKit/IOInterrupts.h>
45 #include <IOKit/IOInterruptController.h>
48 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
50 #define super IOService
52 OSDefineMetaClassAndAbstractStructors(IOInterruptController
, IOService
);
54 OSMetaClassDefineReservedUnused(IOInterruptController
, 0);
55 OSMetaClassDefineReservedUnused(IOInterruptController
, 1);
56 OSMetaClassDefineReservedUnused(IOInterruptController
, 2);
57 OSMetaClassDefineReservedUnused(IOInterruptController
, 3);
58 OSMetaClassDefineReservedUnused(IOInterruptController
, 4);
59 OSMetaClassDefineReservedUnused(IOInterruptController
, 5);
61 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
63 IOReturn
IOInterruptController::registerInterrupt(IOService
*nub
, int source
,
65 IOInterruptHandler handler
,
68 IOInterruptSource
*interruptSources
;
70 IOInterruptVector
*vector
;
74 IOService
*originalNub
;
77 bool canBeShared
, shouldBeShared
, wasAlreadyRegisterd
;
79 interruptSources
= nub
->_interruptSources
;
80 vectorData
= interruptSources
[source
].vectorData
;
81 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
82 vector
= &vectors
[vectorNumber
];
84 // Get the lock for this vector.
85 IOTakeLock(vector
->interruptLock
);
87 // Check if the interrupt source can/should be shared.
88 canBeShared
= vectorCanBeShared(vectorNumber
, vector
);
89 IODTGetInterruptOptions(nub
, source
, &options
);
90 #if defined(__i386__) || defined(__x86_64__)
92 if (OSDynamicCast(IOPlatformDevice
, getProvider()) &&
93 (getInterruptType(nub
, source
, &interruptType
) == kIOReturnSuccess
) &&
94 (kIOInterruptTypeLevel
& interruptType
))
96 options
|= kIODTInterruptShared
;
99 shouldBeShared
= canBeShared
&& (options
& kIODTInterruptShared
);
100 wasAlreadyRegisterd
= vector
->interruptRegistered
;
102 // If the vector is registered and can not be shared return error.
103 if (wasAlreadyRegisterd
&& !canBeShared
) {
104 IOUnlock(vector
->interruptLock
);
105 return kIOReturnNoResources
;
108 // If this vector is already in use, and can be shared (implied),
109 // or it is not registered and should be shared,
110 // register as a shared interrupt.
111 if (wasAlreadyRegisterd
|| shouldBeShared
) {
112 // If this vector is not already shared, break it out.
113 if (vector
->sharedController
== 0) {
114 // Make the IOShareInterruptController instance
115 vector
->sharedController
= new IOSharedInterruptController
;
116 if (vector
->sharedController
== 0) {
117 IOUnlock(vector
->interruptLock
);
118 return kIOReturnNoMemory
;
121 if (wasAlreadyRegisterd
) {
122 // Save the nub and source for the original consumer.
123 originalNub
= vector
->nub
;
124 originalSource
= vector
->source
;
126 // Physically disable the interrupt, but mark it as being enabled in the hardware.
127 // The interruptDisabledSoft now indicates the driver's request for enablement.
128 disableVectorHard(vectorNumber
, vector
);
129 vector
->interruptDisabledHard
= 0;
132 // Initialize the new shared interrupt controller.
133 error
= vector
->sharedController
->initInterruptController(this, vectorData
);
134 // If the IOSharedInterruptController could not be initalized,
135 // if needed, put the original consumer's interrupt back to normal and
136 // get rid of whats left of the shared controller.
137 if (error
!= kIOReturnSuccess
) {
138 if (wasAlreadyRegisterd
) enableInterrupt(originalNub
, originalSource
);
139 vector
->sharedController
->release();
140 vector
->sharedController
= 0;
141 IOUnlock(vector
->interruptLock
);
145 // If there was an original consumer try to register it on the shared controller.
146 if (wasAlreadyRegisterd
) {
147 error
= vector
->sharedController
->registerInterrupt(originalNub
,
152 // If the original consumer could not be moved to the shared controller,
153 // put the original consumor's interrupt back to normal and
154 // get rid of whats left of the shared controller.
155 if (error
!= kIOReturnSuccess
) {
156 // Save the driver's interrupt enablement state.
157 wasDisabledSoft
= vector
->interruptDisabledSoft
;
159 // Make the interrupt really hard disabled.
160 vector
->interruptDisabledSoft
= 1;
161 vector
->interruptDisabledHard
= 1;
163 // Enable the original consumer's interrupt if needed.
164 if (!wasDisabledSoft
) originalNub
->enableInterrupt(originalSource
);
165 enableInterrupt(originalNub
, originalSource
);
167 vector
->sharedController
->release();
168 vector
->sharedController
= 0;
169 IOUnlock(vector
->interruptLock
);
174 // Fill in vector with the shared controller's info.
175 vector
->handler
= (IOInterruptHandler
)vector
->sharedController
->getInterruptHandlerAddress();
176 vector
->nub
= vector
->sharedController
;
178 vector
->target
= vector
->sharedController
;
181 // If the interrupt was already registered,
182 // save the driver's interrupt enablement state.
183 if (wasAlreadyRegisterd
) wasDisabledSoft
= vector
->interruptDisabledSoft
;
184 else wasDisabledSoft
= true;
186 // Do any specific initalization for this vector if it has not yet been used.
187 if (!wasAlreadyRegisterd
) initVector(vectorNumber
, vector
);
189 // Make the interrupt really hard disabled.
190 vector
->interruptDisabledSoft
= 1;
191 vector
->interruptDisabledHard
= 1;
192 vector
->interruptRegistered
= 1;
194 // Enable the original consumer's interrupt if needed.
195 if (!wasDisabledSoft
) originalNub
->enableInterrupt(originalSource
);
198 error
= vector
->sharedController
->registerInterrupt(nub
, source
, target
,
200 IOUnlock(vector
->interruptLock
);
204 // Fill in vector with the client's info.
205 vector
->handler
= handler
;
207 vector
->source
= source
;
208 vector
->target
= target
;
209 vector
->refCon
= refCon
;
211 // Do any specific initalization for this vector.
212 initVector(vectorNumber
, vector
);
214 // Get the vector ready. It starts hard disabled.
215 vector
->interruptDisabledHard
= 1;
216 vector
->interruptDisabledSoft
= 1;
217 vector
->interruptRegistered
= 1;
219 IOUnlock(vector
->interruptLock
);
220 return kIOReturnSuccess
;
223 IOReturn
IOInterruptController::unregisterInterrupt(IOService
*nub
, int source
)
225 IOInterruptSource
*interruptSources
;
227 IOInterruptVector
*vector
;
230 interruptSources
= nub
->_interruptSources
;
231 vectorData
= interruptSources
[source
].vectorData
;
232 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
233 vector
= &vectors
[vectorNumber
];
235 // Get the lock for this vector.
236 IOTakeLock(vector
->interruptLock
);
238 // Return success if it is not already registered
239 if (!vector
->interruptRegistered
) {
240 IOUnlock(vector
->interruptLock
);
241 return kIOReturnSuccess
;
244 // Soft disable the source.
245 disableInterrupt(nub
, source
);
247 // Turn the source off at hardware.
248 disableVectorHard(vectorNumber
, vector
);
250 // Clear all the storage for the vector except for interruptLock.
251 vector
->interruptActive
= 0;
252 vector
->interruptDisabledSoft
= 0;
253 vector
->interruptDisabledHard
= 0;
254 vector
->interruptRegistered
= 0;
261 IOUnlock(vector
->interruptLock
);
262 return kIOReturnSuccess
;
265 IOReturn
IOInterruptController::getInterruptType(IOService
*nub
, int source
,
268 IOInterruptSource
*interruptSources
;
270 IOInterruptVector
*vector
;
273 if (interruptType
== 0) return kIOReturnBadArgument
;
275 interruptSources
= nub
->_interruptSources
;
276 vectorData
= interruptSources
[source
].vectorData
;
277 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
278 vector
= &vectors
[vectorNumber
];
280 *interruptType
= getVectorType(vectorNumber
, vector
);
282 return kIOReturnSuccess
;
285 IOReturn
IOInterruptController::enableInterrupt(IOService
*nub
, int source
)
287 IOInterruptSource
*interruptSources
;
289 IOInterruptVector
*vector
;
292 interruptSources
= nub
->_interruptSources
;
293 vectorData
= interruptSources
[source
].vectorData
;
294 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
295 vector
= &vectors
[vectorNumber
];
297 if (vector
->interruptDisabledSoft
) {
298 vector
->interruptDisabledSoft
= 0;
304 if (!getPlatform()->atInterruptLevel()) {
305 while (vector
->interruptActive
);
310 if (vector
->interruptDisabledHard
) {
311 vector
->interruptDisabledHard
= 0;
313 enableVector(vectorNumber
, vector
);
317 return kIOReturnSuccess
;
320 IOReturn
IOInterruptController::disableInterrupt(IOService
*nub
, int source
)
322 IOInterruptSource
*interruptSources
;
324 IOInterruptVector
*vector
;
327 interruptSources
= nub
->_interruptSources
;
328 vectorData
= interruptSources
[source
].vectorData
;
329 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
330 vector
= &vectors
[vectorNumber
];
332 vector
->interruptDisabledSoft
= 1;
338 if (!getPlatform()->atInterruptLevel()) {
339 while (vector
->interruptActive
);
345 return kIOReturnSuccess
;
348 IOReturn
IOInterruptController::causeInterrupt(IOService
*nub
, int source
)
350 IOInterruptSource
*interruptSources
;
352 IOInterruptVector
*vector
;
355 interruptSources
= nub
->_interruptSources
;
356 vectorData
= interruptSources
[source
].vectorData
;
357 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
358 vector
= &vectors
[vectorNumber
];
360 causeVector(vectorNumber
, vector
);
362 return kIOReturnSuccess
;
365 IOInterruptAction
IOInterruptController::getInterruptHandlerAddress(void)
370 IOReturn
IOInterruptController::handleInterrupt(void *refCon
, IOService
*nub
,
373 return kIOReturnInvalid
;
377 // Methods to be overridden for simplifed interrupt controller subclasses.
379 bool IOInterruptController::vectorCanBeShared(long /*vectorNumber*/,
380 IOInterruptVector */
*vector*/
)
385 void IOInterruptController::initVector(long /*vectorNumber*/,
386 IOInterruptVector */
*vector*/
)
390 int IOInterruptController::getVectorType(long /*vectorNumber*/,
391 IOInterruptVector */
*vector*/
)
393 return kIOInterruptTypeEdge
;
396 void IOInterruptController::disableVectorHard(long /*vectorNumber*/,
397 IOInterruptVector */
*vector*/
)
401 void IOInterruptController::enableVector(long /*vectorNumber*/,
402 IOInterruptVector */
*vector*/
)
406 void IOInterruptController::causeVector(long /*vectorNumber*/,
407 IOInterruptVector */
*vector*/
)
412 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
415 #define super IOInterruptController
417 OSDefineMetaClassAndStructors(IOSharedInterruptController
, IOInterruptController
);
419 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 0);
420 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 1);
421 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 2);
422 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 3);
424 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
426 #define kIOSharedInterruptControllerDefaultVectors (128)
428 IOReturn
IOSharedInterruptController::initInterruptController(IOInterruptController
*parentController
, OSData
*parentSource
)
430 int cnt
, interruptType
;
434 return kIOReturnNoResources
;
436 // Set provider to this so enable/disable nub stuff works.
439 // Allocate the IOInterruptSource so this can act like a nub.
440 _interruptSources
= (IOInterruptSource
*)IOMalloc(sizeof(IOInterruptSource
));
441 if (_interruptSources
== 0) return kIOReturnNoMemory
;
442 _numInterruptSources
= 1;
444 // Set up the IOInterruptSource to point at this.
445 parentController
->retain();
446 parentSource
->retain();
447 _interruptSources
[0].interruptController
= parentController
;
448 _interruptSources
[0].vectorData
= parentSource
;
450 sourceIsLevel
= false;
451 error
= provider
->getInterruptType(0, &interruptType
);
452 if (error
== kIOReturnSuccess
) {
453 if (interruptType
& kIOInterruptTypeLevel
)
454 sourceIsLevel
= true;
457 // Allocate the memory for the vectors
458 numVectors
= kIOSharedInterruptControllerDefaultVectors
; // For now a constant number.
459 vectors
= (IOInterruptVector
*)IOMalloc(numVectors
* sizeof(IOInterruptVector
));
460 if (vectors
== NULL
) {
461 IOFree(_interruptSources
, sizeof(IOInterruptSource
));
462 return kIOReturnNoMemory
;
464 bzero(vectors
, numVectors
* sizeof(IOInterruptVector
));
466 // Allocate the lock for the controller.
467 controllerLock
= IOSimpleLockAlloc();
468 if (controllerLock
== 0) return kIOReturnNoResources
;
470 // Allocate locks for the vectors.
471 for (cnt
= 0; cnt
< numVectors
; cnt
++) {
472 vectors
[cnt
].interruptLock
= IOLockAlloc();
473 if (vectors
[cnt
].interruptLock
== NULL
) {
474 for (cnt
= 0; cnt
< numVectors
; cnt
++) {
475 if (vectors
[cnt
].interruptLock
!= NULL
)
476 IOLockFree(vectors
[cnt
].interruptLock
);
478 return kIOReturnNoResources
;
482 numVectors
= 0; // reset the high water mark for used vectors
483 vectorsRegistered
= 0;
485 controllerDisabled
= 1;
487 return kIOReturnSuccess
;
490 IOReturn
IOSharedInterruptController::registerInterrupt(IOService
*nub
,
493 IOInterruptHandler handler
,
496 IOInterruptSource
*interruptSources
;
498 IOInterruptVector
*vector
= 0;
500 IOInterruptState interruptState
;
502 interruptSources
= nub
->_interruptSources
;
504 // Find a free vector.
505 vectorNumber
= kIOSharedInterruptControllerDefaultVectors
;
506 while (vectorsRegistered
!= kIOSharedInterruptControllerDefaultVectors
) {
507 for (vectorNumber
= 0; vectorNumber
< kIOSharedInterruptControllerDefaultVectors
; vectorNumber
++) {
508 vector
= &vectors
[vectorNumber
];
510 // Get the lock for this vector.
511 IOTakeLock(vector
->interruptLock
);
513 // Is it unregistered?
514 if (!vector
->interruptRegistered
) break;
516 // Move along to the next one.
517 IOUnlock(vector
->interruptLock
);
520 if (vectorNumber
!= kIOSharedInterruptControllerDefaultVectors
) break;
523 // Could not find a free one, so give up.
524 if (vectorNumber
== kIOSharedInterruptControllerDefaultVectors
) {
525 return kIOReturnNoResources
;
528 // Create the vectorData for the IOInterruptSource.
529 vectorData
= OSData::withBytes(&vectorNumber
, sizeof(vectorNumber
));
530 if (vectorData
== 0) {
531 return kIOReturnNoMemory
;
534 // Fill in the IOInterruptSource with the controller's info.
535 interruptSources
[source
].interruptController
= this;
536 interruptSources
[source
].vectorData
= vectorData
;
538 // Fill in vector with the client's info.
539 vector
->handler
= handler
;
541 vector
->source
= source
;
542 vector
->target
= target
;
543 vector
->refCon
= refCon
;
545 // Get the vector ready. It starts off soft disabled.
546 vector
->interruptDisabledSoft
= 1;
547 vector
->interruptRegistered
= 1;
549 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
550 // Move the high water mark if needed
551 if (++vectorsRegistered
> numVectors
) numVectors
= vectorsRegistered
;
552 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
554 IOUnlock(vector
->interruptLock
);
555 return kIOReturnSuccess
;
558 IOReturn
IOSharedInterruptController::unregisterInterrupt(IOService
*nub
,
561 IOInterruptSource
*interruptSources
;
563 IOInterruptVector
*vector
;
565 IOInterruptState interruptState
;
567 interruptSources
= nub
->_interruptSources
;
568 vectorData
= interruptSources
[source
].vectorData
;
569 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
570 vector
= &vectors
[vectorNumber
];
572 // Get the lock for this vector.
573 IOTakeLock(vector
->interruptLock
);
575 // Return success if it is not already registered
576 if (!vector
->interruptRegistered
) {
577 IOUnlock(vector
->interruptLock
);
578 return kIOReturnSuccess
;
581 // Soft disable the source and the controller too.
582 disableInterrupt(nub
, source
);
584 // Clear all the storage for the vector except for interruptLock.
585 vector
->interruptActive
= 0;
586 vector
->interruptDisabledSoft
= 0;
587 vector
->interruptDisabledHard
= 0;
588 vector
->interruptRegistered
= 0;
595 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
597 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
599 IOUnlock(vector
->interruptLock
);
601 // Re-enable the controller if all vectors are enabled.
602 if (vectorsEnabled
== vectorsRegistered
) {
603 controllerDisabled
= 0;
604 provider
->enableInterrupt(0);
607 return kIOReturnSuccess
;
610 IOReturn
IOSharedInterruptController::getInterruptType(IOService */
*nub*/
,
614 return provider
->getInterruptType(0, interruptType
);
617 IOReturn
IOSharedInterruptController::enableInterrupt(IOService
*nub
,
620 IOInterruptSource
*interruptSources
;
622 IOInterruptVector
*vector
;
624 IOInterruptState interruptState
;
626 interruptSources
= nub
->_interruptSources
;
627 vectorData
= interruptSources
[source
].vectorData
;
628 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
629 vector
= &vectors
[vectorNumber
];
631 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
632 if (!vector
->interruptDisabledSoft
) {
633 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
634 return kIOReturnSuccess
;
637 vector
->interruptDisabledSoft
= 0;
639 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
641 if (controllerDisabled
&& (vectorsEnabled
== vectorsRegistered
)) {
642 controllerDisabled
= 0;
643 provider
->enableInterrupt(0);
646 return kIOReturnSuccess
;
649 IOReturn
IOSharedInterruptController::disableInterrupt(IOService
*nub
,
652 IOInterruptSource
*interruptSources
;
654 IOInterruptVector
*vector
;
656 IOInterruptState interruptState
;
658 interruptSources
= nub
->_interruptSources
;
659 vectorData
= interruptSources
[source
].vectorData
;
660 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
661 vector
= &vectors
[vectorNumber
];
663 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
664 if (!vector
->interruptDisabledSoft
) {
665 vector
->interruptDisabledSoft
= 1;
672 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
674 if (!getPlatform()->atInterruptLevel()) {
675 while (vector
->interruptActive
);
681 return kIOReturnSuccess
;
684 IOInterruptAction
IOSharedInterruptController::getInterruptHandlerAddress(void)
686 return OSMemberFunctionCast(IOInterruptAction
,
687 this, &IOSharedInterruptController::handleInterrupt
);
690 IOReturn
IOSharedInterruptController::handleInterrupt(void * /*refCon*/,
695 IOInterruptVector
*vector
;
697 for (vectorNumber
= 0; vectorNumber
< numVectors
; vectorNumber
++) {
698 vector
= &vectors
[vectorNumber
];
700 vector
->interruptActive
= 1;
705 if (!vector
->interruptDisabledSoft
) {
710 // Call the handler if it exists.
711 if (vector
->interruptRegistered
) {
712 vector
->handler(vector
->target
, vector
->refCon
,
713 vector
->nub
, vector
->source
);
717 vector
->interruptActive
= 0;
720 // if any of the vectors are dissabled, then dissable this controller.
721 IOSimpleLockLock(controllerLock
);
722 if (vectorsEnabled
!= vectorsRegistered
) {
723 nub
->disableInterrupt(0);
724 controllerDisabled
= 1;
726 IOSimpleLockUnlock(controllerLock
);
728 return kIOReturnSuccess
;