1 /*
2  * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
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.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
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.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 /*
29  * Copyright (c) 1999 Apple Computer, Inc.  All rights reserved.
30  *
31  *  DRI: Josh de Cesare
32  */
33 
34 #include <IOKit/IOPlatformExpert.h>
35 
36 #include "GenericInterruptController.h"
37 
38 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
39 
40 #undef  super
41 #define super IOInterruptController
42 
43 IODefineMetaClassAndStructors(GenericInterruptController,
44 			      IOInterruptController);
45 
46 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
47 
48 
49 bool GenericInterruptController::start(IOService *provider)
50 {
51   IOInterruptAction    handler;
52   IOSymbol             *interruptControllerName;
53 
54   // If needed call the parents start.
55   if (!super::start(provider))
56     return false;
57 
58   // Map the device's memory and initalize its state.
59 
60   // For now you must allocate storage for the vectors.
61   // This will probably changed to something like: initVectors(numVectors).
62   // In the mean time something like this works well.
63 #if 0
64   // Allocate the memory for the vectors.
65   vectors = (IOInterruptVector *)IOMalloc(numVectors *
66 					  sizeof(IOInterruptVector));
67   if (vectors == NULL) return false;
68   bzero(vectors, numVectors * sizeof(IOInterruptVector));
69 
70   // Allocate locks for the vectors.
71   for (cnt = 0; cnt < numVectors; cnt++) {
72     vectors[cnt].interruptLock = IOLockAlloc();
73     if (vectors[cnt].interruptLock == NULL) {
74       for (cnt = 0; cnt < numVectors; cnt++) {
75 	if (vectors[cnt].interruptLock != NULL)
76 	  IOLockFree(vectors[cnt].interruptLock);
77       }
78     }
79   }
80 #endif
81 
82   // If you know that this interrupt controller is the primary
83   // interrupt controller, use this to set it nub properties properly.
84   // This may be done by the nub's creator.
85   getPlatform()->setCPUInterruptProperties(provider);
86 
87   // register the interrupt handler so it can receive interrupts.
88   handler = getInterruptHandlerAddress();
89   provider->registerInterrupt(0, this, handler, 0);
90 
91   // Just like any interrupt source, you must enable it to receive interrupts.
92   provider->enableInterrupt(0);
93 
94   // Set interruptControllerName to the proper symbol.
95   //interruptControllerName = xxx;
96 
97   // Register this interrupt controller so clients can find it.
98   getPlatform()->registerInterruptController(interruptControllerName, this);
99 
100   // All done, so return true.
101   return true;
102 }
103 
104 IOReturn GenericInterruptController::getInterruptType(IOService *nub,
105 						      int source,
106 						      int *interruptType)
107 {
108   if (interruptType == 0) return kIOReturnBadArgument;
109 
110   // Given the nub and source, set interruptType to level or edge.
111 
112   return kIOReturnSuccess;
113 }
114 
115 // Sadly this just has to be replicated in every interrupt controller.
116 IOInterruptAction GenericInterruptController::getInterruptHandlerAddress(void)
117 {
118   return (IOInterruptAction)handleInterrupt;
119 }
120 
121 // Handle all current interrupts.
122 IOReturn GenericInterruptController::handleInterrupt(void * refCon,
123 						     IOService * nub,
124 						     int source)
125 {
126   IOInterruptVector *vector;
127   int               vectorNumber;
128 
129   while (1) {
130     // Get vectorNumber from hardware some how and clear the event.
131 
132     // Break if there are no more vectors to handle.
133     if (vectorNumber == 0/*kNoVector*/) break;
134 
135     // Get the vector's date from the controller's array.
136     vector = &vectors[vectorNumber];
137 
138     // Set the vector as active. This store must compleat before
139     // moving on to prevent the disableInterrupt fuction from
140     // geting out of sync.
141     vector->interruptActive = 1;
142     //sync();
143     //isync();
144 
145     // If the vector is not disabled soft, handle it.
146     if (!vector->interruptDisabledSoft) {
147       // Prevent speculative exacution as needed on your processor.
148       //isync();
149 
150       // Call the handler if it exists.
151       if (vector->interruptRegistered) {
152 	vector->handler(vector->target, vector->refCon,
153 			vector->nub, vector->source);
154       }
155     } else {
156       // Hard disable the vector if is was only soft disabled.
157       vector->interruptDisabledHard = 1;
158       disableVectorHard(vectorNumber, vector);
159     }
160 
161     // Done with this vector so, set it back to inactive.
162     vector->interruptActive = 0;
163   }
164 
165   return kIOReturnSuccess;
166 }
167 
168 bool GenericInterruptController::vectorCanBeShared(long vectorNumber,
169 						   IOInterruptVector *vector)
170 {
171   // Given the vector number and the vector data, return if it can be shared.
172   return true;
173 }
174 
175 void GenericInterruptController::initVector(long vectorNumber,
176 					    IOInterruptVector *vector)
177 {
178   // Given the vector number and the vector data,
179   // get the hardware ready for the vector to generate interrupts.
180   // Make sure the vector is left disabled.
181 }
182 
183 void GenericInterruptController::disableVectorHard(long vectorNumber,
184 						   IOInterruptVector *vector)
185 {
186   // Given the vector number and the vector data,
187   // disable the vector at the hardware.
188 }
189 
190 void GenericInterruptController::enableVector(long vectorNumber,
191 					      IOInterruptVector *vector)
192 {
193   // Given the vector number and the vector data,
194   // enable the vector at the hardware.
195 }
196 
197 void GenericInterruptController::causeVector(long vectorNumber,
198 					     IOInterruptVector *vector)
199 {
200   // Given the vector number and the vector data,
201   // Set the vector pending and cause an interrupt at the parent controller.
202 
203   // cause the interrupt at the parent controller.  Source is usually zero,
204   // but it could be different for your controller.
205   getPlatform()->causeInterrupt(0);
206 }
207