|
|
1.1 root 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:
29:
30: #include <ppc/proc_reg.h>
31:
32: #include <IOKit/IOLib.h>
33: #include <IOKit/IODeviceTreeSupport.h>
34: #include <IOKit/IODeviceMemory.h>
35: #include <IOKit/IOPlatformExpert.h>
36:
37: #include "../drvAppleNMI/AppleNMI.h"
38:
39: #include "OHare.h"
40:
41: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
42:
43: #define super AppleMacIO
44:
45: OSDefineMetaClassAndStructors(OHare, AppleMacIO);
46:
47: bool OHare::start(IOService *provider)
48: {
49: IOInterruptAction handler;
50: OSSymbol *interruptControllerName;
51: AppleNMI *appleNMI;
52: long nmiSource;
53: OSData *nmiData;
54: IOReturn error;
55:
56: // Call MacIO's start.
57: if (!super::start(provider))
58: return false;
59:
60: // Figure out which ohare this is.
61: if (IODTMatchNubWithKeys(provider, "ohare"))
62: ohareNum = kPrimaryOHare;
63: else if (IODTMatchNubWithKeys(provider, "'pci106b,7'"))
64: ohareNum = kSecondaryOHare;
65: else return false; // This should not happen.
66:
67: if (ohareNum == kPrimaryOHare) {
68: getPlatform()->setCPUInterruptProperties(provider);
69: }
70:
71: // Make nubs for the children.
72: publishBelow( provider );
73:
74: // get the base address of the this OHare.
75: ohareBaseAddress = fMemory->getVirtualAddress();
76:
77: // get the name of the interrupt controller
78: interruptControllerName = getInterruptControllerName();
79:
80: // Allocate the interruptController instance.
81: interruptController = new OHareInterruptController;
82: if (interruptController == NULL) return false;
83:
84: // call the interruptController's init method.
85: error = interruptController->initInterruptController(provider, ohareBaseAddress);
86: if (error != kIOReturnSuccess) return false;
87:
88: handler = interruptController->getInterruptHandlerAddress();
89: provider->registerInterrupt(0, interruptController, handler, 0);
90:
91: provider->enableInterrupt(0);
92:
93: // Register the interrupt controller so clients can find it.
94: getPlatform()->registerInterruptController(interruptControllerName,
95: interruptController);
96:
97: if (ohareNum != kPrimaryOHare) return true;
98:
99: // Create the NMI Driver.
100: nmiSource = 20;
101: nmiData = OSData::withBytes(&nmiSource, sizeof(long));
102: appleNMI = new AppleNMI;
103: if ((nmiData != 0) && (appleNMI != 0)) {
104: appleNMI->initNMI(interruptController, nmiData);
105: }
106:
107: return true;
108: }
109:
110: OSSymbol *OHare::getInterruptControllerName(void)
111: {
112: OSSymbol *interruptControllerName;
113:
114: switch (ohareNum) {
115: case kPrimaryOHare :
116: interruptControllerName = gIODTDefaultInterruptController;
117: break;
118:
119: case kSecondaryOHare :
120: interruptControllerName = OSSymbol::withCStringNoCopy("SecondaryInterruptController");
121: break;
122:
123: default:
124: interruptControllerName = OSSymbol::withCStringNoCopy("UnknownInterruptController");
125: break;
126: }
127:
128: return interruptControllerName;
129: }
130:
131:
132: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
133:
134: #undef super
135: #define super IOInterruptController
136:
137: OSDefineMetaClassAndStructors(OHareInterruptController, IOInterruptController);
138:
139: IOReturn OHareInterruptController::initInterruptController(IOService *provider, IOLogicalAddress interruptControllerBase)
140: {
141: int cnt;
142:
143: parentNub = provider;
144:
145: // Allocate the task lock.
146: taskLock = IOLockAlloc();
147: if (taskLock == 0) return kIOReturnNoResources;
148:
149: // Allocate the memory for the vectors
150: vectors = (IOInterruptVector *)IOMalloc(kNumVectors * sizeof(IOInterruptVector));
151: if (vectors == NULL) {
152: IOLockFree(taskLock);
153: return kIOReturnNoMemory;
154: }
155: bzero(vectors, kNumVectors * sizeof(IOInterruptVector));
156:
157: // Allocate locks for the
158: for (cnt = 0; cnt < kNumVectors; cnt++) {
159: vectors[cnt].interruptLock = IOLockAlloc();
160: if (vectors[cnt].interruptLock == NULL) {
161: for (cnt = 0; cnt < kNumVectors; cnt++) {
162: IOLockFree(taskLock);
163: if (vectors[cnt].interruptLock != NULL)
164: IOLockFree(vectors[cnt].interruptLock);
165: }
166: return kIOReturnNoResources;
167: }
168: }
169:
170: // Setup the registers accessors
171: eventsReg = (unsigned long)(interruptControllerBase + kEventsOffset);
172: maskReg = (unsigned long)(interruptControllerBase + kMaskOffset);
173: clearReg = (unsigned long)(interruptControllerBase + kClearOffset);
174: levelsReg = (unsigned long)(interruptControllerBase + kLevelsOffset);
175:
176: // Initialize the registers.
177:
178: // Disable all interrupts.
179: stwbrx(0x00000000, maskReg);
180: eieio();
181:
182: // Clear all pending interrupts.
183: stwbrx(0xFFFFFFFF, clearReg);
184: eieio();
185:
186: // Disable all interrupts. (again?)
187: stwbrx(0x00000000, maskReg);
188: eieio();
189:
190: return kIOReturnSuccess;
191: }
192:
193: IOInterruptAction OHareInterruptController::getInterruptHandlerAddress(void)
194: {
195: return (IOInterruptAction)&OHareInterruptController::handleInterrupt;
196: }
197:
198: IOReturn OHareInterruptController::handleInterrupt(void * /*refCon*/,
199: IOService * /*nub*/,
200: int /*source*/)
201: {
202: int done;
203: long events, vectorNumber;
204: IOInterruptVector *vector;
205: unsigned long maskTmp;
206:
207: do {
208: done = 1;
209:
210: // Do all the sources for events, plus any pending interrupts.
211: // Also add in the "level" sensitive sources
212: maskTmp = lwbrx(maskReg);
213: events = lwbrx(eventsReg) & ~kTypeLevelMask;
214: events |= lwbrx(levelsReg) & maskTmp & kTypeLevelMask;
215: events |= pendingEvents & maskTmp;
216: pendingEvents = 0;
217: eieio();
218:
219: // Since we have to clear the level'd one clear the current edge's too.
220: stwbrx(kTypeLevelMask | events, clearReg);
221: eieio();
222:
223: if (events) done = 0;
224:
225: while (events) {
226: vectorNumber = 31 - cntlzw(events);
227: events ^= (1 << vectorNumber);
228: vector = &vectors[vectorNumber];
229:
230: vector->interruptActive = 1;
231: sync();
232: isync();
233: if (!vector->interruptDisabledSoft) {
234: isync();
235:
236: // Call the handler if it exists.
237: if (vector->interruptRegistered) {
238: vector->handler(vector->target, vector->refCon,
239: vector->nub, vector->source);
240: }
241: } else {
242: // Hard disable the source.
243: vector->interruptDisabledHard = 1;
244: disableVectorHard(vectorNumber, vector);
245: }
246:
247: vector->interruptActive = 0;
248: }
249: } while (!done);
250:
251: return kIOReturnSuccess;
252: }
253:
254: bool OHareInterruptController::vectorCanBeShared(long /*vectorNumber*/, IOInterruptVector */*vector*/)
255: {
256: return true;
257: }
258:
259: int OHareInterruptController::getVectorType(long vectorNumber, IOInterruptVector */*vector*/)
260: {
261: int interruptType;
262:
263: if (kTypeLevelMask & (1 << vectorNumber)) {
264: interruptType = kIOInterruptTypeLevel;
265: } else {
266: interruptType = kIOInterruptTypeEdge;
267: }
268:
269: return interruptType;
270: }
271:
272: void OHareInterruptController::disableVectorHard(long vectorNumber, IOInterruptVector */*vector*/)
273: {
274: unsigned long maskTmp;
275:
276: // Turn the source off at hardware.
277: maskTmp = lwbrx(maskReg);
278: maskTmp &= ~(1 << vectorNumber);
279: stwbrx(maskTmp, maskReg);
280: eieio();
281: }
282:
283: void OHareInterruptController::enableVector(long vectorNumber,
284: IOInterruptVector *vector)
285: {
286: unsigned long maskTmp;
287:
288: maskTmp = lwbrx(maskReg);
289: maskTmp |= (1 << vectorNumber);
290: stwbrx(maskTmp, maskReg);
291: eieio();
292: if (lwbrx(levelsReg) & (1 << vectorNumber)) {
293: // lost the interrupt
294: causeVector(vectorNumber, vector);
295: }
296: }
297:
298: void OHareInterruptController::causeVector(long vectorNumber,
299: IOInterruptVector */*vector*/)
300: {
301: pendingEvents |= 1 << vectorNumber;
302: parentNub->causeInterrupt(0);
303: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.