|
|
1.1 root 1: /*
2: * Copyright (c) 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-2000 Apple Computer, Inc. All rights reserved.
24: *
25: * DRI: Josh de Cesare
26: */
27:
28:
29: #include <ppc/proc_reg.h>
30:
31: #include <IOKit/IOLib.h>
32: #include <IOKit/IOService.h>
33: #include <IOKit/IODeviceTreeSupport.h>
34: #include <IOKit/IODeviceMemory.h>
35: #include <IOKit/IOPlatformExpert.h>
36:
37: #include "AppleMPIC.h"
38:
39: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
40:
41: #undef super
42: #define super IOInterruptController
43:
44: OSDefineMetaClassAndStructors(AppleMPICInterruptController, IOInterruptController);
45:
46: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
47:
48: bool AppleMPICInterruptController::start(IOService *provider)
49: {
50: long cnt, regTemp;
51: IOInterruptAction handler;
52:
53: if (!super::start(provider))
54: return false;
55:
56: // If this is a PowerExpress get a different name.
57: if (getPlatform()->getFamily() == 3) {
58: interruptControllerName = gIODTDefaultInterruptController;
59: } else {
60: interruptControllerName = IODTInterruptControllerName(provider);
61: }
62:
63: // Map the MPIC's memory.
64: mpicMemoryMap = provider->mapDeviceMemoryWithIndex(0);
65:
66: if (mpicMemoryMap == 0) return false;
67:
68: // get the base address of the MPIC.
69: mpicBaseAddress = mpicMemoryMap->getVirtualAddress();
70:
71: // Read the Feature Reporting Register
72: regTemp = lwbrx(mpicBaseAddress + kFeatureOffset);
73: numCPUs = ((regTemp & kFRRNumCPUMask) >> kFRRNumCPUShift) + 1;
74: numVectors = ((regTemp & kFRRNumIRQsMask) >> kFRRNumIRQsShift) + 1;
75:
76: // Allocate the memory for the senses.
77: senses = (long *)IOMalloc(((numVectors + numCPUs + 31) / 32)*sizeof(long));
78: if (senses == NULL) return false;
79: for (cnt = 0; cnt < ((numVectors + numCPUs + 31) / 32); cnt++)
80: senses[cnt] = 0;
81:
82: // Allocate the memory for the vectors.
83: vectors = (IOInterruptVector *)IOMalloc((numVectors + numCPUs) *
84: sizeof(IOInterruptVector));
85: if (vectors == NULL) return false;
86: bzero(vectors, (numVectors + numCPUs) * sizeof(IOInterruptVector));
87:
88: // Allocate locks for the vectors.
89: for (cnt = 0; cnt < (numVectors + numCPUs) ; cnt++) {
90: vectors[cnt].interruptLock = IOLockAlloc();
91: if (vectors[cnt].interruptLock == NULL) {
92: for (cnt = 0; cnt < (numVectors + numCPUs); cnt++) {
93: if (vectors[cnt].interruptLock != NULL)
94: IOLockFree(vectors[cnt].interruptLock);
95: }
96: return false;
97: }
98: }
99:
100: // Reset the MPIC.
101: stwbrx(kGCR0Reset, mpicBaseAddress + kGlobal0Offset);
102: eieio();
103:
104: // Wait for the reset to complete.
105: do {
106: regTemp = lwbrx(mpicBaseAddress + kGlobal0Offset);
107: eieio();
108: } while (regTemp & kGCR0Reset);
109:
110: // Clear and mask all the interrupt vectors.
111: for (cnt = 0; cnt < (numVectors + numCPUs); cnt++) {
112: stwbrx(kIntnVPRMask, mpicBaseAddress+kIntnVecPriOffset+kIntnStride*cnt);
113: }
114: eieio();
115:
116: // Set the Spurious Vector Register.
117: stwbrx(kSpuriousVectorNumber, mpicBaseAddress + kSpurVectOffset);
118:
119: // Set 8259 Cascade Mode.
120: stwbrx(kGCR0Cascade, mpicBaseAddress + kGlobal0Offset);
121:
122: // Set the all CPUs Current Task Priority to zero.
123: for(cnt = 0; cnt < numCPUs; cnt++) { /* Do 'em all */
124: stwbrx(0, mpicBaseAddress + kPnCurrTskPriOffset + (kPnStride * cnt));
125: eieio();
126: }
127:
128: registerService();
129:
130: getPlatform()->setCPUInterruptProperties(provider);
131:
132: // register the interrupt handler so it can receive interrupts.
133: handler = getInterruptHandlerAddress();
134: for (cnt = 0; cnt < numCPUs; cnt++) {
135: provider->registerInterrupt(cnt, this, handler, 0);
136: provider->enableInterrupt(cnt);
137: }
138:
139: // Register this interrupt controller so clients can find it.
140: getPlatform()->registerInterruptController(interruptControllerName, this);
141:
142: return true;
143: }
144:
145: IOReturn AppleMPICInterruptController::getInterruptType(IOService *nub,
146: int source,
147: int *interruptType)
148: {
149: IOInterruptSource *interruptSources;
150: OSData *vectorData;
151: long vectorNumber;
152:
153: if (interruptType == 0) return kIOReturnBadArgument;
154:
155: interruptSources = nub->_interruptSources;
156: vectorData = interruptSources[source].vectorData;
157: vectorNumber = *(long *)vectorData->getBytesNoCopy();
158: *interruptType = ((long *)vectorData->getBytesNoCopy())[1];
159:
160: return kIOReturnSuccess;
161: }
162:
163: IOInterruptAction AppleMPICInterruptController::getInterruptHandlerAddress(void)
164: {
165: return (IOInterruptAction)&AppleMPICInterruptController::handleInterrupt;
166: }
167:
168: IOReturn AppleMPICInterruptController::handleInterrupt(void */*refCon*/,
169: IOService */*nub*/,
170: int source)
171: {
172: long vectorNumber, level;
173: IOInterruptVector *vector;
174:
175: do {
176: vectorNumber = lwbrx(mpicBaseAddress + source*kPnStride + kPnIntAckOffset);
177: eieio();
178:
179: if (vectorNumber == kSpuriousVectorNumber) break;
180:
181: level = senses[vectorNumber / 32] & (1 << (vectorNumber & 31));
182:
183: if (!level) {
184: stwbrx(0, mpicBaseAddress + source * kPnStride + kPnEOIOffset);
185: eieio();
186: }
187:
188: vector = &vectors[vectorNumber];
189:
190: vector->interruptActive = 1;
191: sync();
192: isync();
193: if (!vector->interruptDisabledSoft) {
194: isync();
195:
196: // Call the handler if it exists.
197: if (vector->interruptRegistered) {
198: vector->handler(vector->target, vector->refCon,
199: vector->nub, vector->source);
200:
201: if (level && vector->interruptDisabledSoft) {
202: // Hard disable the source.
203: vector->interruptDisabledHard = 1;
204: disableVectorHard(vectorNumber, vector);
205: }
206: }
207: } else {
208: // Hard disable the source.
209: vector->interruptDisabledHard = 1;
210: disableVectorHard(vectorNumber, vector);
211: }
212:
213: if (level) {
214: stwbrx(0, mpicBaseAddress + source * kPnStride + kPnEOIOffset);
215: eieio();
216: }
217:
218: vector->interruptActive = 0;
219:
220: } while (1);
221:
222: return kIOReturnSuccess;
223: }
224:
225: bool AppleMPICInterruptController::vectorCanBeShared(long /*vectorNumber*/, IOInterruptVector */*vector*/)
226: {
227: return true;
228: }
229:
230: void AppleMPICInterruptController::initVector(long vectorNumber, IOInterruptVector *vector)
231: {
232: IOInterruptSource *interruptSources;
233: long vectorType;
234: OSData *vectorData;
235: long regTemp, vectorBase;
236:
237: // Get the vector's type.
238: interruptSources = vector->nub->_interruptSources;
239: vectorData = interruptSources[vector->source].vectorData;
240: vectorType = ((long *)vectorData->getBytesNoCopy())[1];
241:
242: if (vectorType == kIOInterruptTypeEdge) {
243: senses[vectorNumber / 32] &= ~(1 << (vectorNumber & 31));
244: } else {
245: senses[vectorNumber / 32] |= (1 << (vectorNumber & 31));
246: }
247:
248: // Set the Vector/Priority and Destination Registers
249: if (vectorNumber < numVectors) {
250: vectorBase = mpicBaseAddress + kIntnStride * vectorNumber;
251:
252: regTemp = 0x1; // CPU 0 only.
253: stwbrx(regTemp, vectorBase + kIntnDestOffset);
254: eieio();
255:
256: // Vectors start masked with priority 8.
257: regTemp = kIntnVPRMask | (8 << kIntnVPRPriorityShift);
258: regTemp |= (vectorType == kIOInterruptTypeLevel) ? kIntnVPRSense : 0;
259: regTemp |= vectorNumber << kIntnVPRVectorShift;
260: stwbrx(regTemp, vectorBase + kIntnVecPriOffset);
261: eieio();
262: } else {
263: vectorBase = mpicBaseAddress + kIPInVecPriStride*(vectorNumber-numVectors);
264:
265: // IPI Vectors start masked with priority 14.
266: regTemp = kIntnVPRMask | (14 << kIntnVPRPriorityShift);
267: regTemp |= vectorNumber << kIntnVPRVectorShift;
268: stwbrx(regTemp, vectorBase + kIPInVecPriOffset);
269: eieio();
270: }
271: }
272:
273: void AppleMPICInterruptController::disableVectorHard(long vectorNumber, IOInterruptVector */*vector*/)
274: {
275: long regTemp, vectorBase;
276:
277: if (vectorNumber < numVectors) {
278: vectorBase = mpicBaseAddress + kIntnVecPriOffset +
279: kIntnStride * vectorNumber;
280: } else {
281: vectorBase = mpicBaseAddress + kIPInVecPriOffset +
282: kIPInVecPriStride * (vectorNumber - numVectors);
283: }
284:
285: regTemp = lwbrx(vectorBase);
286: regTemp |= kIntnVPRMask;
287: stwbrx(regTemp, vectorBase);
288: eieio();
289: }
290:
291: void AppleMPICInterruptController::enableVector(long vectorNumber,
292: IOInterruptVector */*vector*/)
293: {
294: long regTemp, vectorBase;
295:
296: if (vectorNumber < numVectors) {
297: vectorBase = mpicBaseAddress + kIntnVecPriOffset +
298: kIntnStride * vectorNumber;
299: } else {
300: vectorBase = mpicBaseAddress + kIPInVecPriOffset +
301: kIPInVecPriStride * (vectorNumber - numVectors);
302: }
303:
304: regTemp = lwbrx(vectorBase);
305: regTemp &= ~kIntnVPRMask;
306: stwbrx(regTemp, vectorBase);
307: eieio();
308: }
309:
310: OSData *AppleMPICInterruptController::getIPIVector(long physCPU)
311: {
312: long tmpLongs[2];
313: OSData *tmpData;
314:
315: if ((physCPU < 0) && (physCPU >= numCPUs)) return 0;
316:
317: tmpLongs[0] = numVectors + physCPU;
318: tmpLongs[1] = kIOInterruptTypeEdge;
319:
320: tmpData = OSData::withBytes(tmpLongs, 2 * sizeof(long));
321:
322: return tmpData;
323: }
324:
325: void AppleMPICInterruptController::dispatchIPI(long source, long targetMask)
326: {
327: long ipiBase, cnt;
328:
329: ipiBase = mpicBaseAddress + kPnIPImDispOffset + kPnStride * source;
330:
331: for (cnt = 0; cnt < numCPUs; cnt++) {
332: if (targetMask & (1 << cnt)) {
333: stwbrx((1 << cnt), ipiBase + kPnIPImDispStride * cnt);
334: eieio();
335: }
336: }
337: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.