1 /*
2  * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3  *
4  * @APPLE_LICENSE_HEADER_START@
5  *
6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
7  *
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
13  * file.
14  *
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.
22  *
23  * @APPLE_LICENSE_HEADER_END@
24  */
25 /*
26  * Copyright (c) 1999 Apple Computer, Inc.  All rights reserved.
27  *
28  *  DRI: Josh de Cesare
29  */
30 
31 #include <IOKit/IOPlatformExpert.h>
32 
33 #include "GenericInterruptController.h"
34 
35 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
36 
37 #undef  super
38 #define super IOInterruptController
39 
40 IODefineMetaClassAndStructors(GenericInterruptController,
41 			      IOInterruptController);
42 
43 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
44 
45 
46 bool GenericInterruptController::start(IOService *provider)
47 {
48   IOInterruptAction    handler;
49   IOSymbol             *interruptControllerName;
50 
51   // If needed call the parents start.
52   if (!super::start(provider))
53     return false;
54 
55   // Map the device's memory and initalize its state.
56 
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.
60 #if 0
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));
66 
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);
74       }
75     }
76   }
77 #endif
78 
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);
83 
84   // register the interrupt handler so it can receive interrupts.
85   handler = getInterruptHandlerAddress();
86   provider->registerInterrupt(0, this, handler, 0);
87 
88   // Just like any interrupt source, you must enable it to receive interrupts.
89   provider->enableInterrupt(0);
90 
91   // Set interruptControllerName to the proper symbol.
92   //interruptControllerName = xxx;
93 
94   // Register this interrupt controller so clients can find it.
95   getPlatform()->registerInterruptController(interruptControllerName, this);
96 
97   // All done, so return true.
98   return true;
99 }
100 
101 IOReturn GenericInterruptController::getInterruptType(IOService *nub,
102 						      int source,
103 						      int *interruptType)
104 {
105   if (interruptType == 0) return kIOReturnBadArgument;
106 
107   // Given the nub and source, set interruptType to level or edge.
108 
109   return kIOReturnSuccess;
110 }
111 
112 // Sadly this just has to be replicated in every interrupt controller.
113 IOInterruptAction GenericInterruptController::getInterruptHandlerAddress(void)
114 {
115   return (IOInterruptAction)handleInterrupt;
116 }
117 
118 // Handle all current interrupts.
119 IOReturn GenericInterruptController::handleInterrupt(void * refCon,
120 						     IOService * nub,
121 						     int source)
122 {
123   IOInterruptVector *vector;
124   int               vectorNumber;
125 
126   while (1) {
127     // Get vectorNumber from hardware some how and clear the event.
128 
129     // Break if there are no more vectors to handle.
130     if (vectorNumber == 0/*kNoVector*/) break;
131 
132     // Get the vector's date from the controller's array.
133     vector = &vectors[vectorNumber];
134 
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;
139     //sync();
140     //isync();
141 
142     // If the vector is not disabled soft, handle it.
143     if (!vector->interruptDisabledSoft) {
144       // Prevent speculative exacution as needed on your processor.
145       //isync();
146 
147       // Call the handler if it exists.
148       if (vector->interruptRegistered) {
149 	vector->handler(vector->target, vector->refCon,
150 			vector->nub, vector->source);
151       }
152     } else {
153       // Hard disable the vector if is was only soft disabled.
154       vector->interruptDisabledHard = 1;
155       disableVectorHard(vectorNumber, vector);
156     }
157 
158     // Done with this vector so, set it back to inactive.
159     vector->interruptActive = 0;
160   }
161 
162   return kIOReturnSuccess;
163 }
164 
165 bool GenericInterruptController::vectorCanBeShared(long vectorNumber,
166 						   IOInterruptVector *vector)
167 {
168   // Given the vector number and the vector data, return if it can be shared.
169   return true;
170 }
171 
172 void GenericInterruptController::initVector(long vectorNumber,
173 					    IOInterruptVector *vector)
174 {
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.
178 }
179 
180 void GenericInterruptController::disableVectorHard(long vectorNumber,
181 						   IOInterruptVector *vector)
182 {
183   // Given the vector number and the vector data,
184   // disable the vector at the hardware.
185 }
186 
187 void GenericInterruptController::enableVector(long vectorNumber,
188 					      IOInterruptVector *vector)
189 {
190   // Given the vector number and the vector data,
191   // enable the vector at the hardware.
192 }
193 
194 void GenericInterruptController::causeVector(long vectorNumber,
195 					     IOInterruptVector *vector)
196 {
197   // Given the vector number and the vector data,
198   // Set the vector pending and cause an interrupt at the parent controller.
199 
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);
203 }
204