2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
34 #include <ppc/proc_reg.h>
37 #include <IOKit/IOLib.h>
38 #include <IOKit/IOService.h>
39 #include <IOKit/IOPlatformExpert.h>
40 #include <IOKit/IOInterrupts.h>
41 #include <IOKit/IOInterruptController.h>
44 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
46 #define super IOService
48 OSDefineMetaClassAndAbstractStructors(IOInterruptController
, IOService
);
50 OSMetaClassDefineReservedUnused(IOInterruptController
, 0);
51 OSMetaClassDefineReservedUnused(IOInterruptController
, 1);
52 OSMetaClassDefineReservedUnused(IOInterruptController
, 2);
53 OSMetaClassDefineReservedUnused(IOInterruptController
, 3);
54 OSMetaClassDefineReservedUnused(IOInterruptController
, 4);
55 OSMetaClassDefineReservedUnused(IOInterruptController
, 5);
57 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
59 IOReturn
IOInterruptController::registerInterrupt(IOService
*nub
, int source
,
61 IOInterruptHandler handler
,
64 IOInterruptSource
*interruptSources
;
66 IOInterruptVector
*vector
;
70 IOService
*originalNub
;
73 interruptSources
= nub
->_interruptSources
;
74 vectorData
= interruptSources
[source
].vectorData
;
75 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
76 vector
= &vectors
[vectorNumber
];
78 // Get the lock for this vector.
79 IOTakeLock(vector
->interruptLock
);
81 // If this vector is already in use, and can be shared,
82 // register as a shared interrupt.
83 if (vector
->interruptRegistered
) {
84 if (!vectorCanBeShared(vectorNumber
, vector
)) {
85 IOUnlock(vector
->interruptLock
);
86 return kIOReturnNoResources
;
89 // If this vector is not already shared, break it out.
90 if (vector
->sharedController
== 0) {
91 // Make the IOShareInterruptController instance
92 vector
->sharedController
= new IOSharedInterruptController
;
93 if (vector
->sharedController
== 0) {
94 IOUnlock(vector
->interruptLock
);
95 return kIOReturnNoMemory
;
98 // Save the nub and source for the original consumer.
99 originalNub
= vector
->nub
;
100 originalSource
= vector
->source
;
102 // Physically disable the interrupt, but mark it as being enables in the hardware.
103 // The interruptDisabledSoft now indicates the driver's request for enablement.
104 disableVectorHard(vectorNumber
, vector
);
105 vector
->interruptDisabledHard
= 0;
107 // Initialize the new shared interrupt controller.
108 error
= vector
->sharedController
->initInterruptController(this,
110 // If the IOSharedInterruptController could not be initalized,
111 // put the original consumor's interrupt back to normal and
112 // get rid of whats left of the shared controller.
113 if (error
!= kIOReturnSuccess
) {
114 enableInterrupt(originalNub
, originalSource
);
115 vector
->sharedController
->release();
116 vector
->sharedController
= 0;
117 IOUnlock(vector
->interruptLock
);
121 // Try to register the original consumer on the shared controller.
122 error
= vector
->sharedController
->registerInterrupt(originalNub
,
127 // If the original consumer could not be moved to the shared controller,
128 // put the original consumor's interrupt back to normal and
129 // get rid of whats left of the shared controller.
130 if (error
!= kIOReturnSuccess
) {
131 // Save the driver's interrupt enablement state.
132 wasDisabledSoft
= vector
->interruptDisabledSoft
;
134 // Make the interrupt really hard disabled.
135 vector
->interruptDisabledSoft
= 1;
136 vector
->interruptDisabledHard
= 1;
138 // Enable the original consumer's interrupt if needed.
139 if (!wasDisabledSoft
) originalNub
->enableInterrupt(originalSource
);
140 enableInterrupt(originalNub
, originalSource
);
142 vector
->sharedController
->release();
143 vector
->sharedController
= 0;
144 IOUnlock(vector
->interruptLock
);
148 // Fill in vector with the shared controller's info.
149 vector
->handler
= (IOInterruptHandler
)vector
->sharedController
->getInterruptHandlerAddress();
150 vector
->nub
= vector
->sharedController
;
152 vector
->target
= vector
->sharedController
;
155 // Save the driver's interrupt enablement state.
156 wasDisabledSoft
= vector
->interruptDisabledSoft
;
158 // Make the interrupt really hard disabled.
159 vector
->interruptDisabledSoft
= 1;
160 vector
->interruptDisabledHard
= 1;
162 // Enable the original consumer's interrupt if needed.
163 if (!wasDisabledSoft
) originalNub
->enableInterrupt(originalSource
);
166 error
= vector
->sharedController
->registerInterrupt(nub
, source
, target
,
168 IOUnlock(vector
->interruptLock
);
172 // Fill in vector with the client's info.
173 vector
->handler
= handler
;
175 vector
->source
= source
;
176 vector
->target
= target
;
177 vector
->refCon
= refCon
;
179 // Do any specific initalization for this vector.
180 initVector(vectorNumber
, vector
);
182 // Get the vector ready. It starts hard disabled.
183 vector
->interruptDisabledHard
= 1;
184 vector
->interruptDisabledSoft
= 1;
185 vector
->interruptRegistered
= 1;
187 IOUnlock(vector
->interruptLock
);
188 return kIOReturnSuccess
;
191 IOReturn
IOInterruptController::unregisterInterrupt(IOService
*nub
, int source
)
193 IOInterruptSource
*interruptSources
;
195 IOInterruptVector
*vector
;
198 interruptSources
= nub
->_interruptSources
;
199 vectorData
= interruptSources
[source
].vectorData
;
200 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
201 vector
= &vectors
[vectorNumber
];
203 // Get the lock for this vector.
204 IOTakeLock(vector
->interruptLock
);
206 // Return success if it is not already registered
207 if (!vector
->interruptRegistered
) {
208 IOUnlock(vector
->interruptLock
);
209 return kIOReturnSuccess
;
212 // Soft disable the source.
213 disableInterrupt(nub
, source
);
215 // Turn the source off at hardware.
216 disableVectorHard(vectorNumber
, vector
);
218 // Clear all the storage for the vector except for interruptLock.
219 vector
->interruptActive
= 0;
220 vector
->interruptDisabledSoft
= 0;
221 vector
->interruptDisabledHard
= 0;
222 vector
->interruptRegistered
= 0;
229 IOUnlock(vector
->interruptLock
);
230 return kIOReturnSuccess
;
233 IOReturn
IOInterruptController::getInterruptType(IOService
*nub
, int source
,
236 IOInterruptSource
*interruptSources
;
238 IOInterruptVector
*vector
;
241 if (interruptType
== 0) return kIOReturnBadArgument
;
243 interruptSources
= nub
->_interruptSources
;
244 vectorData
= interruptSources
[source
].vectorData
;
245 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
246 vector
= &vectors
[vectorNumber
];
248 *interruptType
= getVectorType(vectorNumber
, vector
);
250 return kIOReturnSuccess
;
253 IOReturn
IOInterruptController::enableInterrupt(IOService
*nub
, int source
)
255 IOInterruptSource
*interruptSources
;
257 IOInterruptVector
*vector
;
260 interruptSources
= nub
->_interruptSources
;
261 vectorData
= interruptSources
[source
].vectorData
;
262 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
263 vector
= &vectors
[vectorNumber
];
265 if (vector
->interruptDisabledSoft
) {
266 vector
->interruptDisabledSoft
= 0;
272 if (!getPlatform()->atInterruptLevel()) {
273 while (vector
->interruptActive
);
278 if (vector
->interruptDisabledHard
) {
279 vector
->interruptDisabledHard
= 0;
281 enableVector(vectorNumber
, vector
);
285 return kIOReturnSuccess
;
288 IOReturn
IOInterruptController::disableInterrupt(IOService
*nub
, int source
)
290 IOInterruptSource
*interruptSources
;
292 IOInterruptVector
*vector
;
295 interruptSources
= nub
->_interruptSources
;
296 vectorData
= interruptSources
[source
].vectorData
;
297 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
298 vector
= &vectors
[vectorNumber
];
300 vector
->interruptDisabledSoft
= 1;
306 if (!getPlatform()->atInterruptLevel()) {
307 while (vector
->interruptActive
);
313 return kIOReturnSuccess
;
316 IOReturn
IOInterruptController::causeInterrupt(IOService
*nub
, int source
)
318 IOInterruptSource
*interruptSources
;
320 IOInterruptVector
*vector
;
323 interruptSources
= nub
->_interruptSources
;
324 vectorData
= interruptSources
[source
].vectorData
;
325 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
326 vector
= &vectors
[vectorNumber
];
328 causeVector(vectorNumber
, vector
);
330 return kIOReturnSuccess
;
333 IOInterruptAction
IOInterruptController::getInterruptHandlerAddress(void)
338 IOReturn
IOInterruptController::handleInterrupt(void *refCon
, IOService
*nub
,
341 return kIOReturnInvalid
;
345 // Methods to be overridden for simplifed interrupt controller subclasses.
347 bool IOInterruptController::vectorCanBeShared(long /*vectorNumber*/,
348 IOInterruptVector */
*vector*/
)
353 void IOInterruptController::initVector(long /*vectorNumber*/,
354 IOInterruptVector */
*vector*/
)
358 int IOInterruptController::getVectorType(long /*vectorNumber*/,
359 IOInterruptVector */
*vector*/
)
361 return kIOInterruptTypeEdge
;
364 void IOInterruptController::disableVectorHard(long /*vectorNumber*/,
365 IOInterruptVector */
*vector*/
)
369 void IOInterruptController::enableVector(long /*vectorNumber*/,
370 IOInterruptVector */
*vector*/
)
374 void IOInterruptController::causeVector(long /*vectorNumber*/,
375 IOInterruptVector */
*vector*/
)
380 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
383 #define super IOInterruptController
385 OSDefineMetaClassAndStructors(IOSharedInterruptController
, IOInterruptController
);
387 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 0);
388 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 1);
389 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 2);
390 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 3);
392 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
394 IOReturn
IOSharedInterruptController::initInterruptController(IOInterruptController
*parentController
, OSData
*parentSource
)
396 int cnt
, interruptType
;
400 return kIOReturnNoResources
;
402 // Set provider to this so enable/disable nub stuff works.
405 // Allocate the IOInterruptSource so this can act like a nub.
406 _interruptSources
= (IOInterruptSource
*)IOMalloc(sizeof(IOInterruptSource
));
407 if (_interruptSources
== 0) return kIOReturnNoMemory
;
408 _numInterruptSources
= 1;
410 // Set up the IOInterruptSource to point at this.
411 _interruptSources
[0].interruptController
= parentController
;
412 _interruptSources
[0].vectorData
= parentSource
;
414 sourceIsLevel
= false;
415 error
= provider
->getInterruptType(0, &interruptType
);
416 if (error
== kIOReturnSuccess
) {
417 if (interruptType
& kIOInterruptTypeLevel
)
418 sourceIsLevel
= true;
421 // Allocate the memory for the vectors
422 numVectors
= 32; // For now a constant number.
423 vectors
= (IOInterruptVector
*)IOMalloc(numVectors
* sizeof(IOInterruptVector
));
424 if (vectors
== NULL
) {
425 IOFree(_interruptSources
, sizeof(IOInterruptSource
));
426 return kIOReturnNoMemory
;
428 bzero(vectors
, numVectors
* sizeof(IOInterruptVector
));
430 // Allocate the lock for the controller.
431 controllerLock
= IOSimpleLockAlloc();
432 if (controllerLock
== 0) return kIOReturnNoResources
;
434 // Allocate locks for the vectors.
435 for (cnt
= 0; cnt
< numVectors
; cnt
++) {
436 vectors
[cnt
].interruptLock
= IOLockAlloc();
437 if (vectors
[cnt
].interruptLock
== NULL
) {
438 for (cnt
= 0; cnt
< numVectors
; cnt
++) {
439 if (vectors
[cnt
].interruptLock
!= NULL
)
440 IOLockFree(vectors
[cnt
].interruptLock
);
442 return kIOReturnNoResources
;
446 vectorsRegistered
= 0;
448 controllerDisabled
= 1;
450 return kIOReturnSuccess
;
453 IOReturn
IOSharedInterruptController::registerInterrupt(IOService
*nub
,
456 IOInterruptHandler handler
,
459 IOInterruptSource
*interruptSources
;
461 IOInterruptVector
*vector
= 0;
463 IOInterruptState interruptState
;
465 interruptSources
= nub
->_interruptSources
;
467 // Find a free vector.
468 vectorNumber
= numVectors
;
469 while (vectorsRegistered
!= numVectors
) {
470 for (vectorNumber
= 0; vectorNumber
< numVectors
; vectorNumber
++) {
471 vector
= &vectors
[vectorNumber
];
473 // Get the lock for this vector.
474 IOTakeLock(vector
->interruptLock
);
476 // Is it unregistered?
477 if (!vector
->interruptRegistered
) break;
479 // Move along to the next one.
480 IOUnlock(vector
->interruptLock
);
483 if (vectorNumber
!= numVectors
) break;
486 // Could not find a free one, so give up.
487 if (vectorNumber
== numVectors
) {
488 return kIOReturnNoResources
;
491 // Create the vectorData for the IOInterruptSource.
492 vectorData
= OSData::withBytes(&vectorNumber
, sizeof(vectorNumber
));
493 if (vectorData
== 0) {
494 return kIOReturnNoMemory
;
497 // Fill in the IOInterruptSource with the controller's info.
498 interruptSources
[source
].interruptController
= this;
499 interruptSources
[source
].vectorData
= vectorData
;
501 // Fill in vector with the client's info.
502 vector
->handler
= handler
;
504 vector
->source
= source
;
505 vector
->target
= target
;
506 vector
->refCon
= refCon
;
508 // Get the vector ready. It start soft disabled.
509 vector
->interruptDisabledSoft
= 1;
510 vector
->interruptRegistered
= 1;
512 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
514 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
516 IOUnlock(vector
->interruptLock
);
517 return kIOReturnSuccess
;
520 IOReturn
IOSharedInterruptController::unregisterInterrupt(IOService
*nub
,
523 IOInterruptSource
*interruptSources
;
525 IOInterruptVector
*vector
;
527 IOInterruptState interruptState
;;
529 interruptSources
= nub
->_interruptSources
;
530 vectorData
= interruptSources
[source
].vectorData
;
531 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
532 vector
= &vectors
[vectorNumber
];
534 // Get the lock for this vector.
535 IOTakeLock(vector
->interruptLock
);
537 // Return success if it is not already registered
538 if (!vector
->interruptRegistered
) {
539 IOUnlock(vector
->interruptLock
);
540 return kIOReturnSuccess
;
543 // Soft disable the source.
544 disableInterrupt(nub
, source
);
546 // Clear all the storage for the vector except for interruptLock.
547 vector
->interruptActive
= 0;
548 vector
->interruptDisabledSoft
= 0;
549 vector
->interruptDisabledHard
= 0;
550 vector
->interruptRegistered
= 0;
557 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
559 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
561 IOUnlock(vector
->interruptLock
);
562 return kIOReturnSuccess
;
565 IOReturn
IOSharedInterruptController::getInterruptType(IOService */
*nub*/
,
569 return provider
->getInterruptType(0, interruptType
);
572 IOReturn
IOSharedInterruptController::enableInterrupt(IOService
*nub
,
575 IOInterruptSource
*interruptSources
;
577 IOInterruptVector
*vector
;
579 IOInterruptState interruptState
;
581 interruptSources
= nub
->_interruptSources
;
582 vectorData
= interruptSources
[source
].vectorData
;
583 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
584 vector
= &vectors
[vectorNumber
];
586 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
587 if (!vector
->interruptDisabledSoft
) {
588 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
589 return kIOReturnSuccess
;
592 vector
->interruptDisabledSoft
= 0;
594 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
596 if (controllerDisabled
&& (vectorsEnabled
== vectorsRegistered
)) {
597 controllerDisabled
= 0;
598 provider
->enableInterrupt(0);
601 return kIOReturnSuccess
;
604 IOReturn
IOSharedInterruptController::disableInterrupt(IOService
*nub
,
607 IOInterruptSource
*interruptSources
;
609 IOInterruptVector
*vector
;
611 IOInterruptState interruptState
;
613 interruptSources
= nub
->_interruptSources
;
614 vectorData
= interruptSources
[source
].vectorData
;
615 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
616 vector
= &vectors
[vectorNumber
];
618 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
619 if (!vector
->interruptDisabledSoft
) {
620 vector
->interruptDisabledSoft
= 1;
627 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
629 if (!getPlatform()->atInterruptLevel()) {
630 while (vector
->interruptActive
);
636 return kIOReturnSuccess
;
639 IOInterruptAction
IOSharedInterruptController::getInterruptHandlerAddress(void)
641 return (IOInterruptAction
)&IOSharedInterruptController::handleInterrupt
;
644 IOReturn
IOSharedInterruptController::handleInterrupt(void * /*refCon*/,
649 IOInterruptVector
*vector
;
651 for (vectorNumber
= 0; vectorNumber
< numVectors
; vectorNumber
++) {
652 vector
= &vectors
[vectorNumber
];
654 vector
->interruptActive
= 1;
659 if (!vector
->interruptDisabledSoft
) {
664 // Call the handler if it exists.
665 if (vector
->interruptRegistered
) {
666 vector
->handler(vector
->target
, vector
->refCon
,
667 vector
->nub
, vector
->source
);
671 vector
->interruptActive
= 0;
674 // if any of the vectors are dissabled, then dissable this controller.
675 IOSimpleLockLock(controllerLock
);
676 if (vectorsEnabled
!= vectorsRegistered
) {
677 nub
->disableInterrupt(0);
678 controllerDisabled
= 1;
680 IOSimpleLockUnlock(controllerLock
);
682 return kIOReturnSuccess
;