|
|
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: #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 "AppleVIA.h"
38:
39:
40: extern "C" {
41: extern void PE_Determine_Clock_Speeds(unsigned int via_addr,
42: int num_speeds,
43: unsigned long *speed_list);
44: }
45:
46: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
47:
48: #define super IOService
49:
50: OSDefineMetaClassAndStructors(AppleVIA, IOService);
51:
52: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
53:
54: bool AppleVIA::start(IOService *provider)
55: {
56: AppleVIADevice *nub;
57: IOInterruptAction handler;
58: IOReturn error;
59: IOMemoryMap *viaMemoryMap;
60: OSSymbol *interruptControllerName;
61: int numSpeeds;
62: unsigned long *speedList;
63:
64: // Call super's start.
65: if (!super::start(provider))
66: return false;
67:
68: // Figure out what kind of via device nub to make.
69: if (IODTMatchNubWithKeys(provider, "'via-cuda'"))
70: viaDeviceType = kVIADeviceTypeCuda;
71: else if (IODTMatchNubWithKeys(provider, "'via-pmu'"))
72: viaDeviceType = kVIADeviceTypePMU;
73: else viaDeviceType = -1; // This should not happen.
74:
75: // get the via's base address
76: viaMemoryMap = provider->mapDeviceMemoryWithIndex(0);
77: if (viaMemoryMap == 0) return false;
78: viaBaseAddress = viaMemoryMap->getVirtualAddress();
79: viaMemoryMap->release();
80:
81: // Calculate the bus and cpu speeds.
82: getPlatform()->getDefaultBusSpeeds(&numSpeeds, &speedList);
83: PE_Determine_Clock_Speeds(viaBaseAddress, numSpeeds, speedList);
84:
85: // Allocate the interruptController instance.
86: interruptController = new AppleVIAInterruptController;
87: if (interruptController == NULL) return false;
88:
89: // call the interruptController's init method.
90: error = interruptController->initInterruptController(provider,
91: viaBaseAddress);
92: if (error != kIOReturnSuccess) return false;
93:
94: handler = interruptController->getInterruptHandlerAddress();
95: provider->registerInterrupt(0, interruptController, handler, 0);
96:
97: provider->enableInterrupt(0);
98:
99: // Register the interrupt controller so clients can find it.
100: interruptControllerName = OSSymbol::withCStringNoCopy(kInterruptControllerName);
101: getPlatform()->registerInterruptController(interruptControllerName,
102: interruptController);
103:
104: nub = createNub();
105: if (nub == 0) return false;
106:
107: nub->attach(this);
108: nub->registerService();
109:
110: return true;
111: }
112:
113: AppleVIADevice *AppleVIA::createNub(void)
114: {
115: int cnt;
116: bool err;
117: OSSymbol *cName;
118: OSSymbol *name = 0;
119: OSArray *array = 0, *vecArray = 0, *deviceMemoryArray;
120: OSDictionary *dict = 0;
121: AppleVIADevice *nub = 0;
122:
123: do {
124: // create the name symbol for the interrupt controller.
125: cName = OSSymbol::withCStringNoCopy(kInterruptControllerName);
126: if (cName == 0) continue;
127:
128: // create the vector array.
129: vecArray = OSDynamicCast(OSArray, getProperty("vectors"));
130: if ((vecArray == 0) || (vecArray->getCount() != kNumVectors)) continue;
131:
132: // create the controller array.
133: array = OSArray::withCapacity(kNumVectors);
134: if (array == 0) continue;
135:
136: // populate the names array
137: err = false;
138: for (cnt = 0; cnt < kNumVectors; cnt++) {
139: if (!array->setObject(cName)) {
140: err = true;
141: break;
142: }
143: }
144: if (err) continue;
145:
146: // create the deviceMemory array.
147: deviceMemoryArray = getProvider()->getDeviceMemory();
148: if (deviceMemoryArray == 0) continue;
149:
150: // create the name for the viaDevice nub
151: if (viaDeviceType == kVIADeviceTypeCuda)
152: name = OSSymbol::withCStringNoCopy("cuda");
153: else if (viaDeviceType == kVIADeviceTypePMU)
154: name = OSSymbol::withCStringNoCopy("pmu");
155: else name = 0;
156: if (name == 0) continue;
157:
158: // Create the dictionary for the viaDevice nub.
159: dict = OSDictionary::withCapacity(1);
160: if (dict == 0) continue;
161:
162: // add the interrupt numbers and parents to the dictionary.
163: err = !dict->setObject("name", name);
164: err |= !dict->setObject(gIOInterruptSpecifiersKey, vecArray);
165: err |= !dict->setObject(gIOInterruptControllersKey, array);
166: if (err) continue;
167:
168: // Create the viaDevice nub
169: nub = new AppleVIADevice;
170: if (nub == 0) continue;
171:
172: if (!nub->init(dict)) {
173: nub->release();
174: nub = 0;
175: continue;
176: }
177:
178: // set the nub's name.
179: nub->setName(name);
180:
181: // set the nub's deviceMemory.
182: nub->setDeviceMemory(deviceMemoryArray);
183:
184: } while(false);
185:
186: if(name) name->release();
187: if(cName) cName->release();
188: if(array) array->release();
189: if(dict) dict->release();
190:
191: return nub;
192: }
193:
194: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
195:
196: #undef super
197: #define super IOService
198:
199: OSDefineMetaClassAndStructors(AppleVIADevice, IOService);
200:
201: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
202:
203: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
204:
205: #undef super
206: #define super IOInterruptController
207:
208: OSDefineMetaClassAndStructors(AppleVIAInterruptController, IOInterruptController);
209:
210: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
211:
212: IOReturn AppleVIAInterruptController::initInterruptController(IOService *provider, IOLogicalAddress interruptControllerBase)
213: {
214: int cnt;
215:
216: parentNub = provider;
217:
218: // Allocate the memory for the vectors
219: vectors = (IOInterruptVector *)IOMalloc(kNumVectors *
220: sizeof(IOInterruptVector));
221: if (vectors == NULL) return kIOReturnNoMemory;
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: for (cnt = 0; cnt < kNumVectors; cnt++) {
229: if (vectors[cnt].interruptLock != NULL)
230: IOLockFree(vectors[cnt].interruptLock);
231: }
232: return kIOReturnNoResources;
233: }
234: }
235:
236: // Initialize the registers.
237: IEReg = (volatile unsigned char *)(interruptControllerBase + kIEOffset);
238: IFReg = (volatile unsigned char *)(interruptControllerBase + kIFOffset);
239: PCReg = (volatile unsigned char *)(interruptControllerBase + kPCOffset);
240:
241: // Disable all interrupts.
242: *PCReg = 0x00; eieio();
243: *IEReg = 0x00; eieio();
244: *IFReg = 0x7F; eieio();
245:
246: return kIOReturnSuccess;
247: }
248:
249: IOInterruptAction AppleVIAInterruptController::getInterruptHandlerAddress(void)
250: {
251: return (IOInterruptAction)&AppleVIAInterruptController::handleInterrupt;
252: }
253:
254: IOReturn AppleVIAInterruptController::handleInterrupt(void */*refCon*/,
255: IOService */*nub*/,
256: int /*source*/)
257: {
258: int done;
259: long events, vectorNumber;
260: IOInterruptVector *vector;
261:
262: do {
263: done = 1;
264:
265: // Do all the sources for events.
266: events = *IFReg; eieio();
267: events |= pendingEvents;
268: pendingEvents = 0;
269: events &= *IEReg & 0x7F; eieio();
270:
271: if (events) {
272: done = 0;
273: *IFReg = events; eieio();
274: }
275:
276: while (events) {
277: vectorNumber = 31 - cntlzw(events);
278: events ^= (1 << vectorNumber);
279: vector = &vectors[vectorNumber];
280:
281: vector->interruptActive = 1;
282: sync();
283: isync();
284: if (!vector->interruptDisabledSoft) {
285: isync();
286:
287: // Call the handler if it exists.
288: if (vector->interruptRegistered) {
289: vector->handler(vector->target, vector->refCon,
290: vector->nub, vector->source);
291: }
292: } else {
293: // Hard disable the source.
294: vector->interruptDisabledHard = 1;
295: disableVectorHard(vectorNumber, vector);
296: }
297:
298: vector->interruptActive = 0;
299: }
300:
301: } while (!done);
302:
303: return kIOReturnSuccess;
304: }
305:
306: void AppleVIAInterruptController::disableVectorHard(long vectorNumber, IOInterruptVector */*vector*/)
307: {
308: *IEReg &= ~(1 << vectorNumber);
309: eieio();
310: }
311:
312: void AppleVIAInterruptController::enableVector(long vectorNumber,
313: IOInterruptVector *vector)
314: {
315: *IEReg |= (1 << vectorNumber);
316: eieio();
317: }
318:
319: void AppleVIAInterruptController::causeVector(long vectorNumber,
320: IOInterruptVector */*vector*/)
321: {
322: pendingEvents |= 1 << vectorNumber;
323: parentNub->causeInterrupt(0);
324: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.