|
|
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 "Heathrow.h"
40:
41: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
42:
43: #define super AppleMacIO
44:
45: OSDefineMetaClassAndStructors(Heathrow, AppleMacIO);
46:
47: bool Heathrow::start(IOService *provider)
48: {
49: bool ret;
50:
51: // Call MacIO's start.
52: if (!super::start(provider))
53: return false;
54:
55: // Figure out which heathrow this is.
56: if (IODTMatchNubWithKeys(provider, "heathrow"))
57: heathrowNum = kPrimaryHeathrow;
58: else if (IODTMatchNubWithKeys(provider, "gatwick"))
59: heathrowNum = kSecondaryHeathrow;
60: else return false; // This should not happen.
61:
62: if (heathrowNum == kPrimaryHeathrow) {
63: if (getPlatform()->getFamily() != 3)
64: getPlatform()->setCPUInterruptProperties(provider);
65: }
66:
67: // get the base address of the this heathrow.
68: heathrowBaseAddress = fMemory->getVirtualAddress();
69:
70: // Make nubs for the children.
71: publishBelow( provider );
72:
73: ret = installInterrupts(provider);
74:
75: return ret;
76: }
77:
78: bool Heathrow::installInterrupts(IOService *provider)
79: {
80: IORegistryEntry *regEntry;
81: OSSymbol *interruptControllerName;
82: IOInterruptAction handler;
83: AppleNMI *appleNMI;
84: long nmiSource;
85: OSData *nmiData;
86: IOReturn error;
87:
88: // Everything below here is for interrupts, return true if
89: // interrupts are not needed.
90: if (getPlatform()->getFamily() == 3) return true;
91:
92: // get the name of the interrupt controller
93: if( (regEntry = provider->childFromPath("interrupt-controller",
94: gIODTPlane))) {
95: interruptControllerName = (OSSymbol *)IODTInterruptControllerName(regEntry);
96: regEntry->release();
97: } else
98: interruptControllerName = getInterruptControllerName();
99:
100: // Allocate the interruptController instance.
101: interruptController = new HeathrowInterruptController;
102: if (interruptController == NULL) return false;
103:
104: // call the interruptController's init method.
105: error = interruptController->initInterruptController(provider, heathrowBaseAddress);
106: if (error != kIOReturnSuccess) return false;
107:
108: handler = interruptController->getInterruptHandlerAddress();
109: provider->registerInterrupt(0, interruptController, handler, 0);
110:
111: provider->enableInterrupt(0);
112:
113: // Register the interrupt controller so clients can find it.
114: getPlatform()->registerInterruptController(interruptControllerName,
115: interruptController);
116:
117: if (heathrowNum != kPrimaryHeathrow) return true;
118:
119: // Create the NMI Driver.
120: nmiSource = 20;
121: nmiData = OSData::withBytes(&nmiSource, sizeof(long));
122: appleNMI = new AppleNMI;
123: if ((nmiData != 0) && (appleNMI != 0)) {
124: appleNMI->initNMI(interruptController, nmiData);
125: }
126:
127: return true;
128: }
129:
130: OSSymbol *Heathrow::getInterruptControllerName(void)
131: {
132: OSSymbol *interruptControllerName;
133:
134: switch (heathrowNum) {
135: case kPrimaryHeathrow :
136: interruptControllerName = (OSSymbol *)gIODTDefaultInterruptController;
137: break;
138:
139: case kSecondaryHeathrow :
140: interruptControllerName = (OSSymbol *)OSSymbol::withCStringNoCopy("SecondaryInterruptController");
141: break;
142:
143: default:
144: interruptControllerName = (OSSymbol *)OSSymbol::withCStringNoCopy("UnknownInterruptController");
145: break;
146: }
147:
148: return interruptControllerName;
149: }
150:
151: void Heathrow::processNub(IOService *nub)
152: {
153: int cnt, numSources;
154: OSArray *controllerNames, *controllerSources;
155: OSSymbol *interruptControllerName;
156: char *nubName;
157: unsigned long heathrowIDs, heathrowFCR;
158:
159: nubName = (char *)nub->getName();
160:
161: // Turn on the media bay if this a PowerBook 101.
162: if (IODTMatchNubWithKeys(getPlatform()->getProvider(), "'PowerBook1,1'")) {
163: if (!strcmp(nubName, "media-bay")) {
164: heathrowIDs = lwbrx(heathrowBaseAddress + 0x34);
165: if ((heathrowIDs & 0x0000FF00) == 0x00003000) {
166: heathrowFCR = lwbrx(heathrowBaseAddress + 0x38);
167: heathrowFCR |= 0x00800000;
168: stwbrx(heathrowFCR, heathrowBaseAddress + 0x38);
169: IOSleep(500);
170: }
171: }
172: }
173:
174: // change the interrupt controller name for this nub
175: // if it is on the secondary heathrow.
176: if (heathrowNum == kPrimaryHeathrow) return;
177:
178: interruptControllerName = getInterruptControllerName();
179:
180: if (!strcmp(nubName, "ch-a")) {
181: controllerSources = OSDynamicCast(OSArray, getProperty("vectors-escc-ch-a"));
182: } else if (!strcmp(nubName, "floppy")) {
183: controllerSources = OSDynamicCast(OSArray, getProperty("vectors-floppy"));
184: } else if (!strcmp(nubName, "ata4")) {
185: controllerSources = OSDynamicCast(OSArray, getProperty("vectors-ata4"));
186: } else return;
187:
188: numSources = controllerSources->getCount();
189:
190: controllerNames = OSArray::withCapacity(numSources);
191: for (cnt = 0; cnt < numSources; cnt++) {
192: controllerNames->setObject(interruptControllerName);
193: }
194:
195: nub->setProperty(gIOInterruptControllersKey, controllerNames);
196: nub->setProperty(gIOInterruptSpecifiersKey, controllerSources);
197: }
198:
199: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
200:
201: #undef super
202: #define super IOInterruptController
203:
204: OSDefineMetaClassAndStructors(HeathrowInterruptController, IOInterruptController);
205:
206: IOReturn HeathrowInterruptController::initInterruptController(IOService *provider, IOLogicalAddress interruptControllerBase)
207: {
208: int cnt;
209:
210: parentNub = provider;
211:
212: // Allocate the task lock.
213: taskLock = IOLockAlloc();
214: if (taskLock == 0) return kIOReturnNoResources;
215:
216: // Allocate the memory for the vectors
217: vectors = (IOInterruptVector *)IOMalloc(kNumVectors * sizeof(IOInterruptVector));
218: if (vectors == NULL) {
219: IOLockFree(taskLock);
220: return kIOReturnNoMemory;
221: }
222: bzero(vectors, kNumVectors * sizeof(IOInterruptVector));
223:
224: // Allocate locks for the
225: for (cnt = 0; cnt < kNumVectors; cnt++) {
226: vectors[cnt].interruptLock = IOLockAlloc();
227: if (vectors[cnt].interruptLock == NULL) {
228: IOLockFree(taskLock);
229: for (cnt = 0; cnt < kNumVectors; cnt++) {
230: if (vectors[cnt].interruptLock != NULL)
231: IOLockFree(vectors[cnt].interruptLock);
232: }
233: return kIOReturnNoResources;
234: }
235: }
236:
237: // Setup the registers accessors
238: events1Reg = (unsigned long)(interruptControllerBase + kEvents1Offset);
239: events2Reg = (unsigned long)(interruptControllerBase + kEvents2Offset);
240: mask1Reg = (unsigned long)(interruptControllerBase + kMask1Offset);
241: mask2Reg = (unsigned long)(interruptControllerBase + kMask2Offset);
242: clear1Reg = (unsigned long)(interruptControllerBase + kClear1Offset);
243: clear2Reg = (unsigned long)(interruptControllerBase + kClear2Offset);
244: levels1Reg = (unsigned long)(interruptControllerBase + kLevels1Offset);
245: levels2Reg = (unsigned long)(interruptControllerBase + kLevels2Offset);
246:
247: // Initialize the registers.
248:
249: // Disable all interrupts.
250: stwbrx(0x00000000, mask1Reg);
251: stwbrx(0x00000000, mask2Reg);
252: eieio();
253:
254: // Clear all pending interrupts.
255: stwbrx(0xFFFFFFFF, clear1Reg);
256: stwbrx(0xFFFFFFFF, clear2Reg);
257: eieio();
258:
259: // Disable all interrupts. (again?)
260: stwbrx(0x00000000, mask1Reg);
261: stwbrx(0x00000000, mask2Reg);
262: eieio();
263:
264: return kIOReturnSuccess;
265: }
266:
267: IOInterruptAction HeathrowInterruptController::getInterruptHandlerAddress(void)
268: {
269: return (IOInterruptAction)&HeathrowInterruptController::handleInterrupt;
270: }
271:
272: IOReturn HeathrowInterruptController::handleInterrupt(void * /*refCon*/,
273: IOService * /*nub*/,
274: int /*source*/)
275: {
276: int done;
277: long events, vectorNumber;
278: IOInterruptVector *vector;
279: unsigned long maskTmp;
280:
281: do {
282: done = 1;
283:
284: // Do all the sources for events1, plus any pending interrupts.
285: // Also add in the "level" sensitive sources
286: maskTmp = lwbrx(mask1Reg);
287: events = lwbrx(events1Reg) & ~kTypeLevelMask;
288: events |= lwbrx(levels1Reg) & maskTmp & kTypeLevelMask;
289: events |= pendingEvents1 & maskTmp;
290: pendingEvents1 = 0;
291: eieio();
292:
293: // Since we have to clear the level'd one clear the current edge's too.
294: stwbrx(kTypeLevelMask | events, clear1Reg);
295: eieio();
296:
297: if (events) done = 0;
298:
299: while (events) {
300: vectorNumber = 31 - cntlzw(events);
301: events ^= (1 << vectorNumber);
302: vector = &vectors[vectorNumber];
303:
304: vector->interruptActive = 1;
305: sync();
306: isync();
307: if (!vector->interruptDisabledSoft) {
308: isync();
309:
310: // Call the handler if it exists.
311: if (vector->interruptRegistered) {
312: vector->handler(vector->target, vector->refCon,
313: vector->nub, vector->source);
314: }
315: } else {
316: // Hard disable the source.
317: vector->interruptDisabledHard = 1;
318: disableVectorHard(vectorNumber, vector);
319: }
320:
321: vector->interruptActive = 0;
322: }
323:
324: // Do all the sources for events2, plus any pending interrupts.
325: maskTmp = lwbrx(mask2Reg);
326: events = lwbrx(events2Reg);
327: events |= pendingEvents1 & maskTmp;
328: pendingEvents2 = 0;
329: eieio();
330:
331: if (events) {
332: done = 0;
333: stwbrx(events, clear2Reg);
334: eieio();
335: }
336:
337: while (events) {
338: vectorNumber = 31 - cntlzw(events);
339: events ^= (1 << vectorNumber);
340: vector = &vectors[vectorNumber + kVectorsPerReg];
341:
342: vector->interruptActive = 1;
343: sync();
344: isync();
345: if (!vector->interruptDisabledSoft) {
346: isync();
347:
348: // Call the handler if it exists.
349: if (vector->interruptRegistered) {
350: vector->handler(vector->target, vector->refCon,
351: vector->nub, vector->source);
352: }
353: } else {
354: // Hard disable the source.
355: vector->interruptDisabledHard = 1;
356: disableVectorHard(vectorNumber + kVectorsPerReg, vector);
357: }
358:
359: vector->interruptActive = 0;
360: }
361: } while (!done);
362:
363: return kIOReturnSuccess;
364: }
365:
366: bool HeathrowInterruptController::vectorCanBeShared(long /*vectorNumber*/, IOInterruptVector */*vector*/)
367: {
368: return true;
369: }
370:
371: int HeathrowInterruptController::getVectorType(long vectorNumber, IOInterruptVector */*vector*/)
372: {
373: int interruptType;
374:
375: if (kTypeLevelMask & (1 << vectorNumber)) {
376: interruptType = kIOInterruptTypeLevel;
377: } else {
378: interruptType = kIOInterruptTypeEdge;
379: }
380:
381: return interruptType;
382: }
383:
384: void HeathrowInterruptController::disableVectorHard(long vectorNumber, IOInterruptVector */*vector*/)
385: {
386: unsigned long maskTmp;
387:
388: // Turn the source off at hardware.
389: if (vectorNumber < kVectorsPerReg) {
390: maskTmp = lwbrx(mask1Reg);
391: maskTmp &= ~(1 << vectorNumber);
392: stwbrx(maskTmp, mask1Reg);
393: eieio();
394: } else {
395: vectorNumber -= kVectorsPerReg;
396: maskTmp = lwbrx(mask2Reg);
397: maskTmp &= ~(1 << vectorNumber);
398: stwbrx(maskTmp, mask2Reg);
399: eieio();
400: }
401: }
402:
403: void HeathrowInterruptController::enableVector(long vectorNumber,
404: IOInterruptVector *vector)
405: {
406: unsigned long maskTmp;
407:
408: if (vectorNumber < kVectorsPerReg) {
409: maskTmp = lwbrx(mask1Reg);
410: maskTmp |= (1 << vectorNumber);
411: stwbrx(maskTmp, mask1Reg);
412: eieio();
413: if (lwbrx(levels1Reg) & (1 << vectorNumber)) {
414: // lost the interrupt
415: causeVector(vectorNumber, vector);
416: }
417: } else {
418: vectorNumber -= kVectorsPerReg;
419: maskTmp = lwbrx(mask2Reg);
420: maskTmp |= (1 << vectorNumber);
421: stwbrx(maskTmp, mask2Reg);
422: eieio();
423: if (lwbrx(levels1Reg) & (1 << vectorNumber)) {
424: // lost the interrupt
425: causeVector(vectorNumber + kVectorsPerReg, vector);
426: }
427: }
428: }
429:
430: void HeathrowInterruptController::causeVector(long vectorNumber,
431: IOInterruptVector */*vector*/)
432: {
433: if (vectorNumber < kVectorsPerReg) {
434: pendingEvents1 |= 1 << vectorNumber;
435: } else {
436: vectorNumber -= kVectorsPerReg;
437: pendingEvents2 |= 1 << vectorNumber;
438: }
439:
440: parentNub->causeInterrupt(0);
441: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.