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