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