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.
31 #include <IOKit/IOPlatformExpert.h>
33 #include "GenericInterruptController.h"
35 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
38 #define super IOInterruptController
40 IODefineMetaClassAndStructors(GenericInterruptController
,
41 IOInterruptController
);
43 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
46 bool GenericInterruptController::start(IOService
*provider
)
48 IOInterruptAction handler
;
49 IOSymbol
*interruptControllerName
;
51 // If needed call the parents start.
52 if (!super::start(provider
))
55 // Map the device's memory and initalize its state.
57 // For now you must allocate storage for the vectors.
58 // This will probably changed to something like: initVectors(numVectors).
59 // In the mean time something like this works well.
61 // Allocate the memory for the vectors.
62 vectors
= (IOInterruptVector
*)IOMalloc(numVectors
*
63 sizeof(IOInterruptVector
));
64 if (vectors
== NULL
) return false;
65 bzero(vectors
, numVectors
* sizeof(IOInterruptVector
));
67 // Allocate locks for the vectors.
68 for (cnt
= 0; cnt
< numVectors
; cnt
++) {
69 vectors
[cnt
].interruptLock
= IOLockAlloc();
70 if (vectors
[cnt
].interruptLock
== NULL
) {
71 for (cnt
= 0; cnt
< numVectors
; cnt
++) {
72 if (vectors
[cnt
].interruptLock
!= NULL
)
73 IOLockFree(vectors
[cnt
].interruptLock
);
79 // If you know that this interrupt controller is the primary
80 // interrupt controller, use this to set it nub properties properly.
81 // This may be done by the nub's creator.
82 getPlatform()->setCPUInterruptProperties(provider
);
84 // register the interrupt handler so it can receive interrupts.
85 handler
= getInterruptHandlerAddress();
86 provider
->registerInterrupt(0, this, handler
, 0);
88 // Just like any interrupt source, you must enable it to receive interrupts.
89 provider
->enableInterrupt(0);
91 // Set interruptControllerName to the proper symbol.
92 //interruptControllerName = xxx;
94 // Register this interrupt controller so clients can find it.
95 getPlatform()->registerInterruptController(interruptControllerName
, this);
97 // All done, so return true.
101 IOReturn
GenericInterruptController::getInterruptType(IOService
*nub
,
105 if (interruptType
== 0) return kIOReturnBadArgument
;
107 // Given the nub and source, set interruptType to level or edge.
109 return kIOReturnSuccess
;
112 // Sadly this just has to be replicated in every interrupt controller.
113 IOInterruptAction
GenericInterruptController::getInterruptHandlerAddress(void)
115 return (IOInterruptAction
)handleInterrupt
;
118 // Handle all current interrupts.
119 IOReturn
GenericInterruptController::handleInterrupt(void * refCon
,
123 IOInterruptVector
*vector
;
127 // Get vectorNumber from hardware some how and clear the event.
129 // Break if there are no more vectors to handle.
130 if (vectorNumber
== 0/*kNoVector*/) break;
132 // Get the vector's date from the controller's array.
133 vector
= &vectors
[vectorNumber
];
135 // Set the vector as active. This store must compleat before
136 // moving on to prevent the disableInterrupt fuction from
137 // geting out of sync.
138 vector
->interruptActive
= 1;
142 // If the vector is not disabled soft, handle it.
143 if (!vector
->interruptDisabledSoft
) {
144 // Prevent speculative exacution as needed on your processor.
147 // Call the handler if it exists.
148 if (vector
->interruptRegistered
) {
149 vector
->handler(vector
->target
, vector
->refCon
,
150 vector
->nub
, vector
->source
);
153 // Hard disable the vector if is was only soft disabled.
154 vector
->interruptDisabledHard
= 1;
155 disableVectorHard(vectorNumber
, vector
);
158 // Done with this vector so, set it back to inactive.
159 vector
->interruptActive
= 0;
162 return kIOReturnSuccess
;
165 bool GenericInterruptController::vectorCanBeShared(long vectorNumber
,
166 IOInterruptVector
*vector
)
168 // Given the vector number and the vector data, return if it can be shared.
172 void GenericInterruptController::initVector(long vectorNumber
,
173 IOInterruptVector
*vector
)
175 // Given the vector number and the vector data,
176 // get the hardware ready for the vector to generate interrupts.
177 // Make sure the vector is left disabled.
180 void GenericInterruptController::disableVectorHard(long vectorNumber
,
181 IOInterruptVector
*vector
)
183 // Given the vector number and the vector data,
184 // disable the vector at the hardware.
187 void GenericInterruptController::enableVector(long vectorNumber
,
188 IOInterruptVector
*vector
)
190 // Given the vector number and the vector data,
191 // enable the vector at the hardware.
194 void GenericInterruptController::causeVector(long vectorNumber
,
195 IOInterruptVector
*vector
)
197 // Given the vector number and the vector data,
198 // Set the vector pending and cause an interrupt at the parent controller.
200 // cause the interrupt at the parent controller. Source is usually zero,
201 // but it could be different for your controller.
202 getPlatform()->causeInterrupt(0);