2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
32 #include <ppc/proc_reg.h>
35 #include <IOKit/IOLib.h>
36 #include <IOKit/IOService.h>
37 #include <IOKit/IOPlatformExpert.h>
38 #include <IOKit/IODeviceTreeSupport.h>
39 #include <IOKit/IOInterrupts.h>
40 #include <IOKit/IOInterruptController.h>
43 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
45 #define super IOService
47 OSDefineMetaClassAndAbstractStructors(IOInterruptController
, IOService
);
49 OSMetaClassDefineReservedUnused(IOInterruptController
, 0);
50 OSMetaClassDefineReservedUnused(IOInterruptController
, 1);
51 OSMetaClassDefineReservedUnused(IOInterruptController
, 2);
52 OSMetaClassDefineReservedUnused(IOInterruptController
, 3);
53 OSMetaClassDefineReservedUnused(IOInterruptController
, 4);
54 OSMetaClassDefineReservedUnused(IOInterruptController
, 5);
56 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
58 IOReturn
IOInterruptController::registerInterrupt(IOService
*nub
, int source
,
60 IOInterruptHandler handler
,
63 IOInterruptSource
*interruptSources
;
65 IOInterruptVector
*vector
;
69 IOService
*originalNub
;
72 bool canBeShared
, shouldBeShared
, wasAlreadyRegisterd
;
74 interruptSources
= nub
->_interruptSources
;
75 vectorData
= interruptSources
[source
].vectorData
;
76 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
77 vector
= &vectors
[vectorNumber
];
79 // Get the lock for this vector.
80 IOTakeLock(vector
->interruptLock
);
82 // Check if the interrupt source can/should be shared.
83 canBeShared
= vectorCanBeShared(vectorNumber
, vector
);
84 IODTGetInterruptOptions(nub
, source
, &options
);
85 shouldBeShared
= canBeShared
&& (options
& kIODTInterruptShared
);
86 wasAlreadyRegisterd
= vector
->interruptRegistered
;
88 // If the vector is registered and can not be shared return error.
89 if (wasAlreadyRegisterd
&& !canBeShared
) {
90 IOUnlock(vector
->interruptLock
);
91 return kIOReturnNoResources
;
94 // If this vector is already in use, and can be shared (implied),
95 // or it is not registered and should be shared,
96 // register as a shared interrupt.
97 if (wasAlreadyRegisterd
|| shouldBeShared
) {
98 // If this vector is not already shared, break it out.
99 if (vector
->sharedController
== 0) {
100 // Make the IOShareInterruptController instance
101 vector
->sharedController
= new IOSharedInterruptController
;
102 if (vector
->sharedController
== 0) {
103 IOUnlock(vector
->interruptLock
);
104 return kIOReturnNoMemory
;
107 if (wasAlreadyRegisterd
) {
108 // Save the nub and source for the original consumer.
109 originalNub
= vector
->nub
;
110 originalSource
= vector
->source
;
112 // Physically disable the interrupt, but mark it as being enabled in the hardware.
113 // The interruptDisabledSoft now indicates the driver's request for enablement.
114 disableVectorHard(vectorNumber
, vector
);
115 vector
->interruptDisabledHard
= 0;
118 // Initialize the new shared interrupt controller.
119 error
= vector
->sharedController
->initInterruptController(this, vectorData
);
120 // If the IOSharedInterruptController could not be initalized,
121 // if needed, put the original consumer's interrupt back to normal and
122 // get rid of whats left of the shared controller.
123 if (error
!= kIOReturnSuccess
) {
124 if (wasAlreadyRegisterd
) enableInterrupt(originalNub
, originalSource
);
125 vector
->sharedController
->release();
126 vector
->sharedController
= 0;
127 IOUnlock(vector
->interruptLock
);
131 // If there was an original consumer try to register it on the shared controller.
132 if (wasAlreadyRegisterd
) {
133 error
= vector
->sharedController
->registerInterrupt(originalNub
,
138 // If the original consumer could not be moved to the shared controller,
139 // put the original consumor's interrupt back to normal and
140 // get rid of whats left of the shared controller.
141 if (error
!= kIOReturnSuccess
) {
142 // Save the driver's interrupt enablement state.
143 wasDisabledSoft
= vector
->interruptDisabledSoft
;
145 // Make the interrupt really hard disabled.
146 vector
->interruptDisabledSoft
= 1;
147 vector
->interruptDisabledHard
= 1;
149 // Enable the original consumer's interrupt if needed.
150 if (!wasDisabledSoft
) originalNub
->enableInterrupt(originalSource
);
151 enableInterrupt(originalNub
, originalSource
);
153 vector
->sharedController
->release();
154 vector
->sharedController
= 0;
155 IOUnlock(vector
->interruptLock
);
160 // Fill in vector with the shared controller's info.
161 vector
->handler
= (IOInterruptHandler
)vector
->sharedController
->getInterruptHandlerAddress();
162 vector
->nub
= vector
->sharedController
;
164 vector
->target
= vector
->sharedController
;
167 // If the interrupt was already registered,
168 // save the driver's interrupt enablement state.
169 if (wasAlreadyRegisterd
) wasDisabledSoft
= vector
->interruptDisabledSoft
;
170 else wasDisabledSoft
= true;
172 // Do any specific initalization for this vector if it has not yet been used.
173 if (!wasAlreadyRegisterd
) initVector(vectorNumber
, vector
);
175 // Make the interrupt really hard disabled.
176 vector
->interruptDisabledSoft
= 1;
177 vector
->interruptDisabledHard
= 1;
178 vector
->interruptRegistered
= 1;
180 // Enable the original consumer's interrupt if needed.
181 if (!wasDisabledSoft
) originalNub
->enableInterrupt(originalSource
);
184 error
= vector
->sharedController
->registerInterrupt(nub
, source
, target
,
186 IOUnlock(vector
->interruptLock
);
190 // Fill in vector with the client's info.
191 vector
->handler
= handler
;
193 vector
->source
= source
;
194 vector
->target
= target
;
195 vector
->refCon
= refCon
;
197 // Do any specific initalization for this vector.
198 initVector(vectorNumber
, vector
);
200 // Get the vector ready. It starts hard disabled.
201 vector
->interruptDisabledHard
= 1;
202 vector
->interruptDisabledSoft
= 1;
203 vector
->interruptRegistered
= 1;
205 IOUnlock(vector
->interruptLock
);
206 return kIOReturnSuccess
;
209 IOReturn
IOInterruptController::unregisterInterrupt(IOService
*nub
, int source
)
211 IOInterruptSource
*interruptSources
;
213 IOInterruptVector
*vector
;
216 interruptSources
= nub
->_interruptSources
;
217 vectorData
= interruptSources
[source
].vectorData
;
218 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
219 vector
= &vectors
[vectorNumber
];
221 // Get the lock for this vector.
222 IOTakeLock(vector
->interruptLock
);
224 // Return success if it is not already registered
225 if (!vector
->interruptRegistered
) {
226 IOUnlock(vector
->interruptLock
);
227 return kIOReturnSuccess
;
230 // Soft disable the source.
231 disableInterrupt(nub
, source
);
233 // Turn the source off at hardware.
234 disableVectorHard(vectorNumber
, vector
);
236 // Clear all the storage for the vector except for interruptLock.
237 vector
->interruptActive
= 0;
238 vector
->interruptDisabledSoft
= 0;
239 vector
->interruptDisabledHard
= 0;
240 vector
->interruptRegistered
= 0;
247 IOUnlock(vector
->interruptLock
);
248 return kIOReturnSuccess
;
251 IOReturn
IOInterruptController::getInterruptType(IOService
*nub
, int source
,
254 IOInterruptSource
*interruptSources
;
256 IOInterruptVector
*vector
;
259 if (interruptType
== 0) return kIOReturnBadArgument
;
261 interruptSources
= nub
->_interruptSources
;
262 vectorData
= interruptSources
[source
].vectorData
;
263 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
264 vector
= &vectors
[vectorNumber
];
266 *interruptType
= getVectorType(vectorNumber
, vector
);
268 return kIOReturnSuccess
;
271 IOReturn
IOInterruptController::enableInterrupt(IOService
*nub
, int source
)
273 IOInterruptSource
*interruptSources
;
275 IOInterruptVector
*vector
;
278 interruptSources
= nub
->_interruptSources
;
279 vectorData
= interruptSources
[source
].vectorData
;
280 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
281 vector
= &vectors
[vectorNumber
];
283 if (vector
->interruptDisabledSoft
) {
284 vector
->interruptDisabledSoft
= 0;
290 if (!getPlatform()->atInterruptLevel()) {
291 while (vector
->interruptActive
);
296 if (vector
->interruptDisabledHard
) {
297 vector
->interruptDisabledHard
= 0;
299 enableVector(vectorNumber
, vector
);
303 return kIOReturnSuccess
;
306 IOReturn
IOInterruptController::disableInterrupt(IOService
*nub
, int source
)
308 IOInterruptSource
*interruptSources
;
310 IOInterruptVector
*vector
;
313 interruptSources
= nub
->_interruptSources
;
314 vectorData
= interruptSources
[source
].vectorData
;
315 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
316 vector
= &vectors
[vectorNumber
];
318 vector
->interruptDisabledSoft
= 1;
324 if (!getPlatform()->atInterruptLevel()) {
325 while (vector
->interruptActive
);
331 return kIOReturnSuccess
;
334 IOReturn
IOInterruptController::causeInterrupt(IOService
*nub
, int source
)
336 IOInterruptSource
*interruptSources
;
338 IOInterruptVector
*vector
;
341 interruptSources
= nub
->_interruptSources
;
342 vectorData
= interruptSources
[source
].vectorData
;
343 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
344 vector
= &vectors
[vectorNumber
];
346 causeVector(vectorNumber
, vector
);
348 return kIOReturnSuccess
;
351 IOInterruptAction
IOInterruptController::getInterruptHandlerAddress(void)
356 IOReturn
IOInterruptController::handleInterrupt(void *refCon
, IOService
*nub
,
359 return kIOReturnInvalid
;
363 // Methods to be overridden for simplifed interrupt controller subclasses.
365 bool IOInterruptController::vectorCanBeShared(long /*vectorNumber*/,
366 IOInterruptVector */
*vector*/
)
371 void IOInterruptController::initVector(long /*vectorNumber*/,
372 IOInterruptVector */
*vector*/
)
376 int IOInterruptController::getVectorType(long /*vectorNumber*/,
377 IOInterruptVector */
*vector*/
)
379 return kIOInterruptTypeEdge
;
382 void IOInterruptController::disableVectorHard(long /*vectorNumber*/,
383 IOInterruptVector */
*vector*/
)
387 void IOInterruptController::enableVector(long /*vectorNumber*/,
388 IOInterruptVector */
*vector*/
)
392 void IOInterruptController::causeVector(long /*vectorNumber*/,
393 IOInterruptVector */
*vector*/
)
398 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
401 #define super IOInterruptController
403 OSDefineMetaClassAndStructors(IOSharedInterruptController
, IOInterruptController
);
405 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 0);
406 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 1);
407 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 2);
408 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 3);
410 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
412 #define kIOSharedInterruptControllerDefaultVectors (128)
414 IOReturn
IOSharedInterruptController::initInterruptController(IOInterruptController
*parentController
, OSData
*parentSource
)
416 int cnt
, interruptType
;
420 return kIOReturnNoResources
;
422 // Set provider to this so enable/disable nub stuff works.
425 // Allocate the IOInterruptSource so this can act like a nub.
426 _interruptSources
= (IOInterruptSource
*)IOMalloc(sizeof(IOInterruptSource
));
427 if (_interruptSources
== 0) return kIOReturnNoMemory
;
428 _numInterruptSources
= 1;
430 // Set up the IOInterruptSource to point at this.
431 _interruptSources
[0].interruptController
= parentController
;
432 _interruptSources
[0].vectorData
= parentSource
;
434 sourceIsLevel
= false;
435 error
= provider
->getInterruptType(0, &interruptType
);
436 if (error
== kIOReturnSuccess
) {
437 if (interruptType
& kIOInterruptTypeLevel
)
438 sourceIsLevel
= true;
441 // Allocate the memory for the vectors
442 numVectors
= kIOSharedInterruptControllerDefaultVectors
; // For now a constant number.
443 vectors
= (IOInterruptVector
*)IOMalloc(numVectors
* sizeof(IOInterruptVector
));
444 if (vectors
== NULL
) {
445 IOFree(_interruptSources
, sizeof(IOInterruptSource
));
446 return kIOReturnNoMemory
;
448 bzero(vectors
, numVectors
* sizeof(IOInterruptVector
));
450 // Allocate the lock for the controller.
451 controllerLock
= IOSimpleLockAlloc();
452 if (controllerLock
== 0) return kIOReturnNoResources
;
454 // Allocate locks for the vectors.
455 for (cnt
= 0; cnt
< numVectors
; cnt
++) {
456 vectors
[cnt
].interruptLock
= IOLockAlloc();
457 if (vectors
[cnt
].interruptLock
== NULL
) {
458 for (cnt
= 0; cnt
< numVectors
; cnt
++) {
459 if (vectors
[cnt
].interruptLock
!= NULL
)
460 IOLockFree(vectors
[cnt
].interruptLock
);
462 return kIOReturnNoResources
;
466 numVectors
= 0; // reset the high water mark for used vectors
467 vectorsRegistered
= 0;
469 controllerDisabled
= 1;
471 return kIOReturnSuccess
;
474 IOReturn
IOSharedInterruptController::registerInterrupt(IOService
*nub
,
477 IOInterruptHandler handler
,
480 IOInterruptSource
*interruptSources
;
482 IOInterruptVector
*vector
= 0;
484 IOInterruptState interruptState
;
486 interruptSources
= nub
->_interruptSources
;
488 // Find a free vector.
489 vectorNumber
= kIOSharedInterruptControllerDefaultVectors
;
490 while (vectorsRegistered
!= kIOSharedInterruptControllerDefaultVectors
) {
491 for (vectorNumber
= 0; vectorNumber
< kIOSharedInterruptControllerDefaultVectors
; vectorNumber
++) {
492 vector
= &vectors
[vectorNumber
];
494 // Get the lock for this vector.
495 IOTakeLock(vector
->interruptLock
);
497 // Is it unregistered?
498 if (!vector
->interruptRegistered
) break;
500 // Move along to the next one.
501 IOUnlock(vector
->interruptLock
);
504 if (vectorNumber
!= kIOSharedInterruptControllerDefaultVectors
) break;
507 // Could not find a free one, so give up.
508 if (vectorNumber
== kIOSharedInterruptControllerDefaultVectors
) {
509 return kIOReturnNoResources
;
512 // Create the vectorData for the IOInterruptSource.
513 vectorData
= OSData::withBytes(&vectorNumber
, sizeof(vectorNumber
));
514 if (vectorData
== 0) {
515 return kIOReturnNoMemory
;
518 // Fill in the IOInterruptSource with the controller's info.
519 interruptSources
[source
].interruptController
= this;
520 interruptSources
[source
].vectorData
= vectorData
;
522 // Fill in vector with the client's info.
523 vector
->handler
= handler
;
525 vector
->source
= source
;
526 vector
->target
= target
;
527 vector
->refCon
= refCon
;
529 // Get the vector ready. It starts off soft disabled.
530 vector
->interruptDisabledSoft
= 1;
531 vector
->interruptRegistered
= 1;
533 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
534 // Move the high water mark if needed
535 if (++vectorsRegistered
> numVectors
) numVectors
= vectorsRegistered
;
536 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
538 IOUnlock(vector
->interruptLock
);
539 return kIOReturnSuccess
;
542 IOReturn
IOSharedInterruptController::unregisterInterrupt(IOService
*nub
,
545 IOInterruptSource
*interruptSources
;
547 IOInterruptVector
*vector
;
549 IOInterruptState interruptState
;
551 interruptSources
= nub
->_interruptSources
;
552 vectorData
= interruptSources
[source
].vectorData
;
553 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
554 vector
= &vectors
[vectorNumber
];
556 // Get the lock for this vector.
557 IOTakeLock(vector
->interruptLock
);
559 // Return success if it is not already registered
560 if (!vector
->interruptRegistered
) {
561 IOUnlock(vector
->interruptLock
);
562 return kIOReturnSuccess
;
565 // Soft disable the source and the controller too.
566 disableInterrupt(nub
, source
);
568 // Clear all the storage for the vector except for interruptLock.
569 vector
->interruptActive
= 0;
570 vector
->interruptDisabledSoft
= 0;
571 vector
->interruptDisabledHard
= 0;
572 vector
->interruptRegistered
= 0;
579 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
581 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
583 IOUnlock(vector
->interruptLock
);
585 // Re-enable the controller if all vectors are enabled.
586 if (vectorsEnabled
== vectorsRegistered
) {
587 controllerDisabled
= 0;
588 provider
->enableInterrupt(0);
591 return kIOReturnSuccess
;
594 IOReturn
IOSharedInterruptController::getInterruptType(IOService */
*nub*/
,
598 return provider
->getInterruptType(0, interruptType
);
601 IOReturn
IOSharedInterruptController::enableInterrupt(IOService
*nub
,
604 IOInterruptSource
*interruptSources
;
606 IOInterruptVector
*vector
;
608 IOInterruptState interruptState
;
610 interruptSources
= nub
->_interruptSources
;
611 vectorData
= interruptSources
[source
].vectorData
;
612 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
613 vector
= &vectors
[vectorNumber
];
615 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
616 if (!vector
->interruptDisabledSoft
) {
617 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
618 return kIOReturnSuccess
;
621 vector
->interruptDisabledSoft
= 0;
623 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
625 if (controllerDisabled
&& (vectorsEnabled
== vectorsRegistered
)) {
626 controllerDisabled
= 0;
627 provider
->enableInterrupt(0);
630 return kIOReturnSuccess
;
633 IOReturn
IOSharedInterruptController::disableInterrupt(IOService
*nub
,
636 IOInterruptSource
*interruptSources
;
638 IOInterruptVector
*vector
;
640 IOInterruptState interruptState
;
642 interruptSources
= nub
->_interruptSources
;
643 vectorData
= interruptSources
[source
].vectorData
;
644 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
645 vector
= &vectors
[vectorNumber
];
647 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
648 if (!vector
->interruptDisabledSoft
) {
649 vector
->interruptDisabledSoft
= 1;
656 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
658 if (!getPlatform()->atInterruptLevel()) {
659 while (vector
->interruptActive
);
665 return kIOReturnSuccess
;
668 IOInterruptAction
IOSharedInterruptController::getInterruptHandlerAddress(void)
670 return (IOInterruptAction
)&IOSharedInterruptController::handleInterrupt
;
673 IOReturn
IOSharedInterruptController::handleInterrupt(void * /*refCon*/,
678 IOInterruptVector
*vector
;
680 for (vectorNumber
= 0; vectorNumber
< numVectors
; vectorNumber
++) {
681 vector
= &vectors
[vectorNumber
];
683 vector
->interruptActive
= 1;
688 if (!vector
->interruptDisabledSoft
) {
693 // Call the handler if it exists.
694 if (vector
->interruptRegistered
) {
695 vector
->handler(vector
->target
, vector
->refCon
,
696 vector
->nub
, vector
->source
);
700 vector
->interruptActive
= 0;
703 // if any of the vectors are dissabled, then dissable this controller.
704 IOSimpleLockLock(controllerLock
);
705 if (vectorsEnabled
!= vectorsRegistered
) {
706 nub
->disableInterrupt(0);
707 controllerDisabled
= 1;
709 IOSimpleLockUnlock(controllerLock
);
711 return kIOReturnSuccess
;