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 shouldBeShared
= canBeShared
&& (options
& kIODTInterruptShared
);
91 wasAlreadyRegisterd
= vector
->interruptRegistered
;
93 // If the vector is registered and can not be shared return error.
94 if (wasAlreadyRegisterd
&& !canBeShared
) {
95 IOUnlock(vector
->interruptLock
);
96 return kIOReturnNoResources
;
99 // If this vector is already in use, and can be shared (implied),
100 // or it is not registered and should be shared,
101 // register as a shared interrupt.
102 if (wasAlreadyRegisterd
|| shouldBeShared
) {
103 // If this vector is not already shared, break it out.
104 if (vector
->sharedController
== 0) {
105 // Make the IOShareInterruptController instance
106 vector
->sharedController
= new IOSharedInterruptController
;
107 if (vector
->sharedController
== 0) {
108 IOUnlock(vector
->interruptLock
);
109 return kIOReturnNoMemory
;
112 if (wasAlreadyRegisterd
) {
113 // Save the nub and source for the original consumer.
114 originalNub
= vector
->nub
;
115 originalSource
= vector
->source
;
117 // Physically disable the interrupt, but mark it as being enabled in the hardware.
118 // The interruptDisabledSoft now indicates the driver's request for enablement.
119 disableVectorHard(vectorNumber
, vector
);
120 vector
->interruptDisabledHard
= 0;
123 // Initialize the new shared interrupt controller.
124 error
= vector
->sharedController
->initInterruptController(this, vectorData
);
125 // If the IOSharedInterruptController could not be initalized,
126 // if needed, put the original consumer's interrupt back to normal and
127 // get rid of whats left of the shared controller.
128 if (error
!= kIOReturnSuccess
) {
129 if (wasAlreadyRegisterd
) enableInterrupt(originalNub
, originalSource
);
130 vector
->sharedController
->release();
131 vector
->sharedController
= 0;
132 IOUnlock(vector
->interruptLock
);
136 // If there was an original consumer try to register it on the shared controller.
137 if (wasAlreadyRegisterd
) {
138 error
= vector
->sharedController
->registerInterrupt(originalNub
,
143 // If the original consumer could not be moved to the shared controller,
144 // put the original consumor's interrupt back to normal and
145 // get rid of whats left of the shared controller.
146 if (error
!= kIOReturnSuccess
) {
147 // Save the driver's interrupt enablement state.
148 wasDisabledSoft
= vector
->interruptDisabledSoft
;
150 // Make the interrupt really hard disabled.
151 vector
->interruptDisabledSoft
= 1;
152 vector
->interruptDisabledHard
= 1;
154 // Enable the original consumer's interrupt if needed.
155 if (!wasDisabledSoft
) originalNub
->enableInterrupt(originalSource
);
156 enableInterrupt(originalNub
, originalSource
);
158 vector
->sharedController
->release();
159 vector
->sharedController
= 0;
160 IOUnlock(vector
->interruptLock
);
165 // Fill in vector with the shared controller's info.
166 vector
->handler
= (IOInterruptHandler
)vector
->sharedController
->getInterruptHandlerAddress();
167 vector
->nub
= vector
->sharedController
;
169 vector
->target
= vector
->sharedController
;
172 // If the interrupt was already registered,
173 // save the driver's interrupt enablement state.
174 if (wasAlreadyRegisterd
) wasDisabledSoft
= vector
->interruptDisabledSoft
;
175 else wasDisabledSoft
= true;
177 // Do any specific initalization for this vector if it has not yet been used.
178 if (!wasAlreadyRegisterd
) initVector(vectorNumber
, vector
);
180 // Make the interrupt really hard disabled.
181 vector
->interruptDisabledSoft
= 1;
182 vector
->interruptDisabledHard
= 1;
183 vector
->interruptRegistered
= 1;
185 // Enable the original consumer's interrupt if needed.
186 if (!wasDisabledSoft
) originalNub
->enableInterrupt(originalSource
);
189 error
= vector
->sharedController
->registerInterrupt(nub
, source
, target
,
191 IOUnlock(vector
->interruptLock
);
195 // Fill in vector with the client's info.
196 vector
->handler
= handler
;
198 vector
->source
= source
;
199 vector
->target
= target
;
200 vector
->refCon
= refCon
;
202 // Do any specific initalization for this vector.
203 initVector(vectorNumber
, vector
);
205 // Get the vector ready. It starts hard disabled.
206 vector
->interruptDisabledHard
= 1;
207 vector
->interruptDisabledSoft
= 1;
208 vector
->interruptRegistered
= 1;
210 IOUnlock(vector
->interruptLock
);
211 return kIOReturnSuccess
;
214 IOReturn
IOInterruptController::unregisterInterrupt(IOService
*nub
, int source
)
216 IOInterruptSource
*interruptSources
;
218 IOInterruptVector
*vector
;
221 interruptSources
= nub
->_interruptSources
;
222 vectorData
= interruptSources
[source
].vectorData
;
223 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
224 vector
= &vectors
[vectorNumber
];
226 // Get the lock for this vector.
227 IOTakeLock(vector
->interruptLock
);
229 // Return success if it is not already registered
230 if (!vector
->interruptRegistered
) {
231 IOUnlock(vector
->interruptLock
);
232 return kIOReturnSuccess
;
235 // Soft disable the source.
236 disableInterrupt(nub
, source
);
238 // Turn the source off at hardware.
239 disableVectorHard(vectorNumber
, vector
);
241 // Clear all the storage for the vector except for interruptLock.
242 vector
->interruptActive
= 0;
243 vector
->interruptDisabledSoft
= 0;
244 vector
->interruptDisabledHard
= 0;
245 vector
->interruptRegistered
= 0;
252 IOUnlock(vector
->interruptLock
);
253 return kIOReturnSuccess
;
256 IOReturn
IOInterruptController::getInterruptType(IOService
*nub
, int source
,
259 IOInterruptSource
*interruptSources
;
261 IOInterruptVector
*vector
;
264 if (interruptType
== 0) return kIOReturnBadArgument
;
266 interruptSources
= nub
->_interruptSources
;
267 vectorData
= interruptSources
[source
].vectorData
;
268 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
269 vector
= &vectors
[vectorNumber
];
271 *interruptType
= getVectorType(vectorNumber
, vector
);
273 return kIOReturnSuccess
;
276 IOReturn
IOInterruptController::enableInterrupt(IOService
*nub
, int source
)
278 IOInterruptSource
*interruptSources
;
280 IOInterruptVector
*vector
;
283 interruptSources
= nub
->_interruptSources
;
284 vectorData
= interruptSources
[source
].vectorData
;
285 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
286 vector
= &vectors
[vectorNumber
];
288 if (vector
->interruptDisabledSoft
) {
289 vector
->interruptDisabledSoft
= 0;
295 if (!getPlatform()->atInterruptLevel()) {
296 while (vector
->interruptActive
);
301 if (vector
->interruptDisabledHard
) {
302 vector
->interruptDisabledHard
= 0;
304 enableVector(vectorNumber
, vector
);
308 return kIOReturnSuccess
;
311 IOReturn
IOInterruptController::disableInterrupt(IOService
*nub
, int source
)
313 IOInterruptSource
*interruptSources
;
315 IOInterruptVector
*vector
;
318 interruptSources
= nub
->_interruptSources
;
319 vectorData
= interruptSources
[source
].vectorData
;
320 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
321 vector
= &vectors
[vectorNumber
];
323 vector
->interruptDisabledSoft
= 1;
329 if (!getPlatform()->atInterruptLevel()) {
330 while (vector
->interruptActive
);
336 return kIOReturnSuccess
;
339 IOReturn
IOInterruptController::causeInterrupt(IOService
*nub
, int source
)
341 IOInterruptSource
*interruptSources
;
343 IOInterruptVector
*vector
;
346 interruptSources
= nub
->_interruptSources
;
347 vectorData
= interruptSources
[source
].vectorData
;
348 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
349 vector
= &vectors
[vectorNumber
];
351 causeVector(vectorNumber
, vector
);
353 return kIOReturnSuccess
;
356 IOInterruptAction
IOInterruptController::getInterruptHandlerAddress(void)
361 IOReturn
IOInterruptController::handleInterrupt(void *refCon
, IOService
*nub
,
364 return kIOReturnInvalid
;
368 // Methods to be overridden for simplifed interrupt controller subclasses.
370 bool IOInterruptController::vectorCanBeShared(long /*vectorNumber*/,
371 IOInterruptVector */
*vector*/
)
376 void IOInterruptController::initVector(long /*vectorNumber*/,
377 IOInterruptVector */
*vector*/
)
381 int IOInterruptController::getVectorType(long /*vectorNumber*/,
382 IOInterruptVector */
*vector*/
)
384 return kIOInterruptTypeEdge
;
387 void IOInterruptController::disableVectorHard(long /*vectorNumber*/,
388 IOInterruptVector */
*vector*/
)
392 void IOInterruptController::enableVector(long /*vectorNumber*/,
393 IOInterruptVector */
*vector*/
)
397 void IOInterruptController::causeVector(long /*vectorNumber*/,
398 IOInterruptVector */
*vector*/
)
403 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
406 #define super IOInterruptController
408 OSDefineMetaClassAndStructors(IOSharedInterruptController
, IOInterruptController
);
410 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 0);
411 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 1);
412 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 2);
413 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 3);
415 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
417 #define kIOSharedInterruptControllerDefaultVectors (128)
419 IOReturn
IOSharedInterruptController::initInterruptController(IOInterruptController
*parentController
, OSData
*parentSource
)
421 int cnt
, interruptType
;
425 return kIOReturnNoResources
;
427 // Set provider to this so enable/disable nub stuff works.
430 // Allocate the IOInterruptSource so this can act like a nub.
431 _interruptSources
= (IOInterruptSource
*)IOMalloc(sizeof(IOInterruptSource
));
432 if (_interruptSources
== 0) return kIOReturnNoMemory
;
433 _numInterruptSources
= 1;
435 // Set up the IOInterruptSource to point at this.
436 _interruptSources
[0].interruptController
= parentController
;
437 _interruptSources
[0].vectorData
= parentSource
;
439 sourceIsLevel
= false;
440 error
= provider
->getInterruptType(0, &interruptType
);
441 if (error
== kIOReturnSuccess
) {
442 if (interruptType
& kIOInterruptTypeLevel
)
443 sourceIsLevel
= true;
446 // Allocate the memory for the vectors
447 numVectors
= kIOSharedInterruptControllerDefaultVectors
; // For now a constant number.
448 vectors
= (IOInterruptVector
*)IOMalloc(numVectors
* sizeof(IOInterruptVector
));
449 if (vectors
== NULL
) {
450 IOFree(_interruptSources
, sizeof(IOInterruptSource
));
451 return kIOReturnNoMemory
;
453 bzero(vectors
, numVectors
* sizeof(IOInterruptVector
));
455 // Allocate the lock for the controller.
456 controllerLock
= IOSimpleLockAlloc();
457 if (controllerLock
== 0) return kIOReturnNoResources
;
459 // Allocate locks for the vectors.
460 for (cnt
= 0; cnt
< numVectors
; cnt
++) {
461 vectors
[cnt
].interruptLock
= IOLockAlloc();
462 if (vectors
[cnt
].interruptLock
== NULL
) {
463 for (cnt
= 0; cnt
< numVectors
; cnt
++) {
464 if (vectors
[cnt
].interruptLock
!= NULL
)
465 IOLockFree(vectors
[cnt
].interruptLock
);
467 return kIOReturnNoResources
;
471 numVectors
= 0; // reset the high water mark for used vectors
472 vectorsRegistered
= 0;
474 controllerDisabled
= 1;
476 return kIOReturnSuccess
;
479 IOReturn
IOSharedInterruptController::registerInterrupt(IOService
*nub
,
482 IOInterruptHandler handler
,
485 IOInterruptSource
*interruptSources
;
487 IOInterruptVector
*vector
= 0;
489 IOInterruptState interruptState
;
491 interruptSources
= nub
->_interruptSources
;
493 // Find a free vector.
494 vectorNumber
= kIOSharedInterruptControllerDefaultVectors
;
495 while (vectorsRegistered
!= kIOSharedInterruptControllerDefaultVectors
) {
496 for (vectorNumber
= 0; vectorNumber
< kIOSharedInterruptControllerDefaultVectors
; vectorNumber
++) {
497 vector
= &vectors
[vectorNumber
];
499 // Get the lock for this vector.
500 IOTakeLock(vector
->interruptLock
);
502 // Is it unregistered?
503 if (!vector
->interruptRegistered
) break;
505 // Move along to the next one.
506 IOUnlock(vector
->interruptLock
);
509 if (vectorNumber
!= kIOSharedInterruptControllerDefaultVectors
) break;
512 // Could not find a free one, so give up.
513 if (vectorNumber
== kIOSharedInterruptControllerDefaultVectors
) {
514 return kIOReturnNoResources
;
517 // Create the vectorData for the IOInterruptSource.
518 vectorData
= OSData::withBytes(&vectorNumber
, sizeof(vectorNumber
));
519 if (vectorData
== 0) {
520 return kIOReturnNoMemory
;
523 // Fill in the IOInterruptSource with the controller's info.
524 interruptSources
[source
].interruptController
= this;
525 interruptSources
[source
].vectorData
= vectorData
;
527 // Fill in vector with the client's info.
528 vector
->handler
= handler
;
530 vector
->source
= source
;
531 vector
->target
= target
;
532 vector
->refCon
= refCon
;
534 // Get the vector ready. It starts off soft disabled.
535 vector
->interruptDisabledSoft
= 1;
536 vector
->interruptRegistered
= 1;
538 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
539 // Move the high water mark if needed
540 if (++vectorsRegistered
> numVectors
) numVectors
= vectorsRegistered
;
541 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
543 IOUnlock(vector
->interruptLock
);
544 return kIOReturnSuccess
;
547 IOReturn
IOSharedInterruptController::unregisterInterrupt(IOService
*nub
,
550 IOInterruptSource
*interruptSources
;
552 IOInterruptVector
*vector
;
554 IOInterruptState interruptState
;
556 interruptSources
= nub
->_interruptSources
;
557 vectorData
= interruptSources
[source
].vectorData
;
558 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
559 vector
= &vectors
[vectorNumber
];
561 // Get the lock for this vector.
562 IOTakeLock(vector
->interruptLock
);
564 // Return success if it is not already registered
565 if (!vector
->interruptRegistered
) {
566 IOUnlock(vector
->interruptLock
);
567 return kIOReturnSuccess
;
570 // Soft disable the source and the controller too.
571 disableInterrupt(nub
, source
);
573 // Clear all the storage for the vector except for interruptLock.
574 vector
->interruptActive
= 0;
575 vector
->interruptDisabledSoft
= 0;
576 vector
->interruptDisabledHard
= 0;
577 vector
->interruptRegistered
= 0;
584 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
586 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
588 IOUnlock(vector
->interruptLock
);
590 // Re-enable the controller if all vectors are enabled.
591 if (vectorsEnabled
== vectorsRegistered
) {
592 controllerDisabled
= 0;
593 provider
->enableInterrupt(0);
596 return kIOReturnSuccess
;
599 IOReturn
IOSharedInterruptController::getInterruptType(IOService */
*nub*/
,
603 return provider
->getInterruptType(0, interruptType
);
606 IOReturn
IOSharedInterruptController::enableInterrupt(IOService
*nub
,
609 IOInterruptSource
*interruptSources
;
611 IOInterruptVector
*vector
;
613 IOInterruptState interruptState
;
615 interruptSources
= nub
->_interruptSources
;
616 vectorData
= interruptSources
[source
].vectorData
;
617 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
618 vector
= &vectors
[vectorNumber
];
620 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
621 if (!vector
->interruptDisabledSoft
) {
622 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
623 return kIOReturnSuccess
;
626 vector
->interruptDisabledSoft
= 0;
628 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
630 if (controllerDisabled
&& (vectorsEnabled
== vectorsRegistered
)) {
631 controllerDisabled
= 0;
632 provider
->enableInterrupt(0);
635 return kIOReturnSuccess
;
638 IOReturn
IOSharedInterruptController::disableInterrupt(IOService
*nub
,
641 IOInterruptSource
*interruptSources
;
643 IOInterruptVector
*vector
;
645 IOInterruptState interruptState
;
647 interruptSources
= nub
->_interruptSources
;
648 vectorData
= interruptSources
[source
].vectorData
;
649 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
650 vector
= &vectors
[vectorNumber
];
652 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
653 if (!vector
->interruptDisabledSoft
) {
654 vector
->interruptDisabledSoft
= 1;
661 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
663 if (!getPlatform()->atInterruptLevel()) {
664 while (vector
->interruptActive
);
670 return kIOReturnSuccess
;
673 IOInterruptAction
IOSharedInterruptController::getInterruptHandlerAddress(void)
675 return (IOInterruptAction
)&IOSharedInterruptController::handleInterrupt
;
678 IOReturn
IOSharedInterruptController::handleInterrupt(void * /*refCon*/,
683 IOInterruptVector
*vector
;
685 for (vectorNumber
= 0; vectorNumber
< numVectors
; vectorNumber
++) {
686 vector
= &vectors
[vectorNumber
];
688 vector
->interruptActive
= 1;
693 if (!vector
->interruptDisabledSoft
) {
698 // Call the handler if it exists.
699 if (vector
->interruptRegistered
) {
700 vector
->handler(vector
->target
, vector
->refCon
,
701 vector
->nub
, vector
->source
);
705 vector
->interruptActive
= 0;
708 // if any of the vectors are dissabled, then dissable this controller.
709 IOSimpleLockLock(controllerLock
);
710 if (vectorsEnabled
!= vectorsRegistered
) {
711 nub
->disableInterrupt(0);
712 controllerDisabled
= 1;
714 IOSimpleLockUnlock(controllerLock
);
716 return kIOReturnSuccess
;