2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
31 #include <ppc/proc_reg.h>
34 #include <IOKit/IOLib.h>
35 #include <IOKit/IOService.h>
36 #include <IOKit/IOPlatformExpert.h>
37 #include <IOKit/IOInterrupts.h>
38 #include <IOKit/IOInterruptController.h>
41 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
43 #define super IOService
45 OSDefineMetaClassAndAbstractStructors(IOInterruptController
, IOService
);
47 OSMetaClassDefineReservedUnused(IOInterruptController
, 0);
48 OSMetaClassDefineReservedUnused(IOInterruptController
, 1);
49 OSMetaClassDefineReservedUnused(IOInterruptController
, 2);
50 OSMetaClassDefineReservedUnused(IOInterruptController
, 3);
51 OSMetaClassDefineReservedUnused(IOInterruptController
, 4);
52 OSMetaClassDefineReservedUnused(IOInterruptController
, 5);
54 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
56 IOReturn
IOInterruptController::registerInterrupt(IOService
*nub
, int source
,
58 IOInterruptHandler handler
,
61 IOInterruptSource
*interruptSources
;
63 IOInterruptVector
*vector
;
67 IOService
*originalNub
;
70 interruptSources
= nub
->_interruptSources
;
71 vectorData
= interruptSources
[source
].vectorData
;
72 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
73 vector
= &vectors
[vectorNumber
];
75 // Get the lock for this vector.
76 IOTakeLock(vector
->interruptLock
);
78 // If this vector is already in use, and can be shared,
79 // register as a shared interrupt.
80 if (vector
->interruptRegistered
) {
81 if (!vectorCanBeShared(vectorNumber
, vector
)) {
82 IOUnlock(vector
->interruptLock
);
83 return kIOReturnNoResources
;
86 // If this vector is not already shared, break it out.
87 if (vector
->sharedController
== 0) {
88 // Make the IOShareInterruptController instance
89 vector
->sharedController
= new IOSharedInterruptController
;
90 if (vector
->sharedController
== 0) {
91 IOUnlock(vector
->interruptLock
);
92 return kIOReturnNoMemory
;
95 // Save the nub and source for the original consumer.
96 originalNub
= vector
->nub
;
97 originalSource
= vector
->source
;
99 // Physically disable the interrupt, but mark it as being enables in the hardware.
100 // The interruptDisabledSoft now indicates the driver's request for enablement.
101 disableVectorHard(vectorNumber
, vector
);
102 vector
->interruptDisabledHard
= 0;
104 // Initialize the new shared interrupt controller.
105 error
= vector
->sharedController
->initInterruptController(this,
107 // If the IOSharedInterruptController could not be initalized,
108 // put the original consumor's interrupt back to normal and
109 // get rid of whats left of the shared controller.
110 if (error
!= kIOReturnSuccess
) {
111 enableInterrupt(originalNub
, originalSource
);
112 vector
->sharedController
->release();
113 vector
->sharedController
= 0;
114 IOUnlock(vector
->interruptLock
);
118 // Try to register the original consumer on the shared controller.
119 error
= vector
->sharedController
->registerInterrupt(originalNub
,
124 // If the original consumer could not be moved to the shared controller,
125 // put the original consumor's interrupt back to normal and
126 // get rid of whats left of the shared controller.
127 if (error
!= kIOReturnSuccess
) {
128 // Save the driver's interrupt enablement state.
129 wasDisabledSoft
= vector
->interruptDisabledSoft
;
131 // Make the interrupt really hard disabled.
132 vector
->interruptDisabledSoft
= 1;
133 vector
->interruptDisabledHard
= 1;
135 // Enable the original consumer's interrupt if needed.
136 if (!wasDisabledSoft
) originalNub
->enableInterrupt(originalSource
);
137 enableInterrupt(originalNub
, originalSource
);
139 vector
->sharedController
->release();
140 vector
->sharedController
= 0;
141 IOUnlock(vector
->interruptLock
);
145 // Fill in vector with the shared controller's info.
146 vector
->handler
= (IOInterruptHandler
)vector
->sharedController
->getInterruptHandlerAddress();
147 vector
->nub
= vector
->sharedController
;
149 vector
->target
= vector
->sharedController
;
152 // Save the driver's interrupt enablement state.
153 wasDisabledSoft
= vector
->interruptDisabledSoft
;
155 // Make the interrupt really hard disabled.
156 vector
->interruptDisabledSoft
= 1;
157 vector
->interruptDisabledHard
= 1;
159 // Enable the original consumer's interrupt if needed.
160 if (!wasDisabledSoft
) originalNub
->enableInterrupt(originalSource
);
163 error
= vector
->sharedController
->registerInterrupt(nub
, source
, target
,
165 IOUnlock(vector
->interruptLock
);
169 // Fill in vector with the client's info.
170 vector
->handler
= handler
;
172 vector
->source
= source
;
173 vector
->target
= target
;
174 vector
->refCon
= refCon
;
176 // Do any specific initalization for this vector.
177 initVector(vectorNumber
, vector
);
179 // Get the vector ready. It starts hard disabled.
180 vector
->interruptDisabledHard
= 1;
181 vector
->interruptDisabledSoft
= 1;
182 vector
->interruptRegistered
= 1;
184 IOUnlock(vector
->interruptLock
);
185 return kIOReturnSuccess
;
188 IOReturn
IOInterruptController::unregisterInterrupt(IOService
*nub
, int source
)
190 IOInterruptSource
*interruptSources
;
192 IOInterruptVector
*vector
;
195 interruptSources
= nub
->_interruptSources
;
196 vectorData
= interruptSources
[source
].vectorData
;
197 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
198 vector
= &vectors
[vectorNumber
];
200 // Get the lock for this vector.
201 IOTakeLock(vector
->interruptLock
);
203 // Return success if it is not already registered
204 if (!vector
->interruptRegistered
) {
205 IOUnlock(vector
->interruptLock
);
206 return kIOReturnSuccess
;
209 // Soft disable the source.
210 disableInterrupt(nub
, source
);
212 // Turn the source off at hardware.
213 disableVectorHard(vectorNumber
, vector
);
215 // Clear all the storage for the vector except for interruptLock.
216 vector
->interruptActive
= 0;
217 vector
->interruptDisabledSoft
= 0;
218 vector
->interruptDisabledHard
= 0;
219 vector
->interruptRegistered
= 0;
226 IOUnlock(vector
->interruptLock
);
227 return kIOReturnSuccess
;
230 IOReturn
IOInterruptController::getInterruptType(IOService
*nub
, int source
,
233 IOInterruptSource
*interruptSources
;
235 IOInterruptVector
*vector
;
238 if (interruptType
== 0) return kIOReturnBadArgument
;
240 interruptSources
= nub
->_interruptSources
;
241 vectorData
= interruptSources
[source
].vectorData
;
242 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
243 vector
= &vectors
[vectorNumber
];
245 *interruptType
= getVectorType(vectorNumber
, vector
);
247 return kIOReturnSuccess
;
250 IOReturn
IOInterruptController::enableInterrupt(IOService
*nub
, int source
)
252 IOInterruptSource
*interruptSources
;
254 IOInterruptVector
*vector
;
257 interruptSources
= nub
->_interruptSources
;
258 vectorData
= interruptSources
[source
].vectorData
;
259 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
260 vector
= &vectors
[vectorNumber
];
262 if (vector
->interruptDisabledSoft
) {
263 vector
->interruptDisabledSoft
= 0;
269 if (!getPlatform()->atInterruptLevel()) {
270 while (vector
->interruptActive
);
275 if (vector
->interruptDisabledHard
) {
276 vector
->interruptDisabledHard
= 0;
278 enableVector(vectorNumber
, vector
);
282 return kIOReturnSuccess
;
285 IOReturn
IOInterruptController::disableInterrupt(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 vector
->interruptDisabledSoft
= 1;
303 if (!getPlatform()->atInterruptLevel()) {
304 while (vector
->interruptActive
);
310 return kIOReturnSuccess
;
313 IOReturn
IOInterruptController::causeInterrupt(IOService
*nub
, int source
)
315 IOInterruptSource
*interruptSources
;
317 IOInterruptVector
*vector
;
320 interruptSources
= nub
->_interruptSources
;
321 vectorData
= interruptSources
[source
].vectorData
;
322 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
323 vector
= &vectors
[vectorNumber
];
325 causeVector(vectorNumber
, vector
);
327 return kIOReturnSuccess
;
330 IOInterruptAction
IOInterruptController::getInterruptHandlerAddress(void)
335 IOReturn
IOInterruptController::handleInterrupt(void *refCon
, IOService
*nub
,
338 return kIOReturnInvalid
;
342 // Methods to be overridden for simplifed interrupt controller subclasses.
344 bool IOInterruptController::vectorCanBeShared(long /*vectorNumber*/,
345 IOInterruptVector */
*vector*/
)
350 void IOInterruptController::initVector(long /*vectorNumber*/,
351 IOInterruptVector */
*vector*/
)
355 int IOInterruptController::getVectorType(long /*vectorNumber*/,
356 IOInterruptVector */
*vector*/
)
358 return kIOInterruptTypeEdge
;
361 void IOInterruptController::disableVectorHard(long /*vectorNumber*/,
362 IOInterruptVector */
*vector*/
)
366 void IOInterruptController::enableVector(long /*vectorNumber*/,
367 IOInterruptVector */
*vector*/
)
371 void IOInterruptController::causeVector(long /*vectorNumber*/,
372 IOInterruptVector */
*vector*/
)
377 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
380 #define super IOInterruptController
382 OSDefineMetaClassAndStructors(IOSharedInterruptController
, IOInterruptController
);
384 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 0);
385 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 1);
386 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 2);
387 OSMetaClassDefineReservedUnused(IOSharedInterruptController
, 3);
389 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
391 IOReturn
IOSharedInterruptController::initInterruptController(IOInterruptController
*parentController
, OSData
*parentSource
)
393 int cnt
, interruptType
;
397 return kIOReturnNoResources
;
399 // Set provider to this so enable/disable nub stuff works.
402 // Allocate the IOInterruptSource so this can act like a nub.
403 _interruptSources
= (IOInterruptSource
*)IOMalloc(sizeof(IOInterruptSource
));
404 if (_interruptSources
== 0) return kIOReturnNoMemory
;
405 _numInterruptSources
= 1;
407 // Set up the IOInterruptSource to point at this.
408 _interruptSources
[0].interruptController
= parentController
;
409 _interruptSources
[0].vectorData
= parentSource
;
411 sourceIsLevel
= false;
412 error
= provider
->getInterruptType(0, &interruptType
);
413 if (error
== kIOReturnSuccess
) {
414 if (interruptType
& kIOInterruptTypeLevel
)
415 sourceIsLevel
= true;
418 // Allocate the memory for the vectors
419 numVectors
= 32; // For now a constant number.
420 vectors
= (IOInterruptVector
*)IOMalloc(numVectors
* sizeof(IOInterruptVector
));
421 if (vectors
== NULL
) {
422 IOFree(_interruptSources
, sizeof(IOInterruptSource
));
423 return kIOReturnNoMemory
;
425 bzero(vectors
, numVectors
* sizeof(IOInterruptVector
));
427 // Allocate the lock for the controller.
428 controllerLock
= IOSimpleLockAlloc();
429 if (controllerLock
== 0) return kIOReturnNoResources
;
431 // Allocate locks for the vectors.
432 for (cnt
= 0; cnt
< numVectors
; cnt
++) {
433 vectors
[cnt
].interruptLock
= IOLockAlloc();
434 if (vectors
[cnt
].interruptLock
== NULL
) {
435 for (cnt
= 0; cnt
< numVectors
; cnt
++) {
436 if (vectors
[cnt
].interruptLock
!= NULL
)
437 IOLockFree(vectors
[cnt
].interruptLock
);
439 return kIOReturnNoResources
;
443 vectorsRegistered
= 0;
445 controllerDisabled
= 1;
447 return kIOReturnSuccess
;
450 IOReturn
IOSharedInterruptController::registerInterrupt(IOService
*nub
,
453 IOInterruptHandler handler
,
456 IOInterruptSource
*interruptSources
;
458 IOInterruptVector
*vector
= 0;
460 IOInterruptState interruptState
;
462 interruptSources
= nub
->_interruptSources
;
464 // Find a free vector.
465 vectorNumber
= numVectors
;
466 while (vectorsRegistered
!= numVectors
) {
467 for (vectorNumber
= 0; vectorNumber
< numVectors
; vectorNumber
++) {
468 vector
= &vectors
[vectorNumber
];
470 // Get the lock for this vector.
471 IOTakeLock(vector
->interruptLock
);
473 // Is it unregistered?
474 if (!vector
->interruptRegistered
) break;
476 // Move along to the next one.
477 IOUnlock(vector
->interruptLock
);
480 if (vectorNumber
!= numVectors
) break;
483 // Could not find a free one, so give up.
484 if (vectorNumber
== numVectors
) {
485 return kIOReturnNoResources
;
488 // Create the vectorData for the IOInterruptSource.
489 vectorData
= OSData::withBytes(&vectorNumber
, sizeof(vectorNumber
));
490 if (vectorData
== 0) {
491 return kIOReturnNoMemory
;
494 // Fill in the IOInterruptSource with the controller's info.
495 interruptSources
[source
].interruptController
= this;
496 interruptSources
[source
].vectorData
= vectorData
;
498 // Fill in vector with the client's info.
499 vector
->handler
= handler
;
501 vector
->source
= source
;
502 vector
->target
= target
;
503 vector
->refCon
= refCon
;
505 // Get the vector ready. It start soft disabled.
506 vector
->interruptDisabledSoft
= 1;
507 vector
->interruptRegistered
= 1;
509 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
511 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
513 IOUnlock(vector
->interruptLock
);
514 return kIOReturnSuccess
;
517 IOReturn
IOSharedInterruptController::unregisterInterrupt(IOService
*nub
,
520 IOInterruptSource
*interruptSources
;
522 IOInterruptVector
*vector
;
524 IOInterruptState interruptState
;;
526 interruptSources
= nub
->_interruptSources
;
527 vectorData
= interruptSources
[source
].vectorData
;
528 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
529 vector
= &vectors
[vectorNumber
];
531 // Get the lock for this vector.
532 IOTakeLock(vector
->interruptLock
);
534 // Return success if it is not already registered
535 if (!vector
->interruptRegistered
) {
536 IOUnlock(vector
->interruptLock
);
537 return kIOReturnSuccess
;
540 // Soft disable the source.
541 disableInterrupt(nub
, source
);
543 // Clear all the storage for the vector except for interruptLock.
544 vector
->interruptActive
= 0;
545 vector
->interruptDisabledSoft
= 0;
546 vector
->interruptDisabledHard
= 0;
547 vector
->interruptRegistered
= 0;
554 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
556 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
558 IOUnlock(vector
->interruptLock
);
559 return kIOReturnSuccess
;
562 IOReturn
IOSharedInterruptController::getInterruptType(IOService */
*nub*/
,
566 return provider
->getInterruptType(0, interruptType
);
569 IOReturn
IOSharedInterruptController::enableInterrupt(IOService
*nub
,
572 IOInterruptSource
*interruptSources
;
574 IOInterruptVector
*vector
;
576 IOInterruptState interruptState
;
578 interruptSources
= nub
->_interruptSources
;
579 vectorData
= interruptSources
[source
].vectorData
;
580 vectorNumber
= *(long *)vectorData
->getBytesNoCopy();
581 vector
= &vectors
[vectorNumber
];
583 interruptState
= IOSimpleLockLockDisableInterrupt(controllerLock
);
584 if (!vector
->interruptDisabledSoft
) {
585 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
586 return kIOReturnSuccess
;
589 vector
->interruptDisabledSoft
= 0;
591 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
593 if (controllerDisabled
&& (vectorsEnabled
== vectorsRegistered
)) {
594 controllerDisabled
= 0;
595 provider
->enableInterrupt(0);
598 return kIOReturnSuccess
;
601 IOReturn
IOSharedInterruptController::disableInterrupt(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 vector
->interruptDisabledSoft
= 1;
624 IOSimpleLockUnlockEnableInterrupt(controllerLock
, interruptState
);
626 if (!getPlatform()->atInterruptLevel()) {
627 while (vector
->interruptActive
);
633 return kIOReturnSuccess
;
636 IOInterruptAction
IOSharedInterruptController::getInterruptHandlerAddress(void)
638 return (IOInterruptAction
)&IOSharedInterruptController::handleInterrupt
;
641 IOReturn
IOSharedInterruptController::handleInterrupt(void * /*refCon*/,
646 IOInterruptVector
*vector
;
648 for (vectorNumber
= 0; vectorNumber
< numVectors
; vectorNumber
++) {
649 vector
= &vectors
[vectorNumber
];
651 vector
->interruptActive
= 1;
656 if (!vector
->interruptDisabledSoft
) {
661 // Call the handler if it exists.
662 if (vector
->interruptRegistered
) {
663 vector
->handler(vector
->target
, vector
->refCon
,
664 vector
->nub
, vector
->source
);
668 vector
->interruptActive
= 0;
671 // if any of the vectors are dissabled, then dissable this controller.
672 IOSimpleLockLock(controllerLock
);
673 if (vectorsEnabled
!= vectorsRegistered
) {
674 nub
->disableInterrupt(0);
675 controllerDisabled
= 1;
677 IOSimpleLockUnlock(controllerLock
);
679 return kIOReturnSuccess
;