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