|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24: /*
25: * Copyright (c) 1997 Apple Computer, Inc.
26: *
27: *
28: * HISTORY
29: *
30: * Simon Douglas 22 Oct 97
31: * - first checked in.
32: * Simon Douglas 26 Jan 98
33: * - support PCI-PCI bridges
34: */
35:
36: #import <machdep/ppc/proc_reg.h>
37: #import "IOMacRiscPCI.h"
38:
39: #define INFO if(0) kprintf
40:
41: enum {
42: kPCIConfigSpace = 0,
43: kPCIIOSpace = 1,
44: kPCI32BitMemorySpace = 2,
45: kPCI64BitMemorySpace = 3
46: };
47:
48: struct AddressCell {
49: unsigned int reloc:1;
50: unsigned int prefetch:1;
51: unsigned int t:1;
52: unsigned int resv:3;
53: unsigned int space:2;
54: unsigned int busNum:8;
55: unsigned int deviceNum:5;
56: unsigned int functionNum:3;
57: unsigned int registerNum:8;
58: unsigned int physMid;
59: unsigned int physLo;
60: unsigned int lengthHi;
61: unsigned int lengthLo;
62: };
63: typedef struct AddressCell AddressCell;
64:
65: #define SWAPLONG(value) ( ((value >> 24) & 0xff) | \
66: ((value >> 8) & 0xff00) | \
67: ((value << 8) & 0xff0000) | \
68: ((value << 24) & 0xff000000) )
69:
70:
71: @implementation IOPCIBridge
72:
73: - initFromDeviceDescription:deviceDescription
74: {
75: IOReturn err;
76: UInt32 * prop;
77: ByteCount propSize;
78:
79: do {
80: if ([super initFromDeviceDescription:deviceDescription] == nil)
81: continue;
82:
83: // Redo the default ranges so less may be pmap'ed
84: err = [self mapRegisters:deviceDescription];
85: if( err)
86: continue;
87:
88: err = [[deviceDescription propertyTable] getProperty:"bus-range"
89: flags:kReferenceProperty value:(void **) &prop length:&propSize];
90:
91: if( (err == noErr) && (propSize >= sizeof( int)))
92: primaryBus = *prop;
93:
94: if( [deviceDescription isKindOf:[IOPCIDevice class]] )
95: parentBridge = [deviceDescription parent];
96:
97: return( self);
98:
99: } while( false);
100:
101: return( [super free]);
102: }
103:
104:
105: - createDevice:(IOPropertyTable *)newTable ref:ref
106: {
107: IOReturn err;
108: IOPCIDevice * newDev;
109: AddressCell * cell;
110: ByteCount propSize;
111:
112: newDev = [IOPCIDevice alloc];
113:
114: // If we were really probing PCI we would know the device & function
115: // numbers but for now just rely on the tree probe to create our children
116: // and get the info necessary from the OpenFirmware probe.
117:
118: err = [newTable getProperty:"reg" flags:kReferenceProperty
119: value:(void **) &cell length:&propSize];
120: if( err || (propSize < sizeof(AddressCell)))
121: return( nil);
122:
123: newDev->busNum = cell->busNum;
124: newDev->deviceNum = cell->deviceNum;
125: newDev->functionNum = cell->functionNum;
126:
127: [newDev initAt:newTable parent:self ref:ref];
128:
129: return( [newDev publish] );
130: }
131:
132: #if 0
133: - (BOOL) match:(IOPCIDevice *)device key:(const char *)key location:(const char *)location
134: {
135:
136: // check for vendor, product ID keys and so on...
137:
138: // otherwise the default device name matching from IODeviceTreeBus
139: return( [super match:device key:key location:location]);
140: }
141: #endif
142:
143: - (IOReturn) configReadLong:(IOPCIDevice *)device
144: offset:(UInt32)offset value:(UInt32 *)value
145: {
146: volatile UInt32 * access;
147:
148: access = [self setConfigAddress:device offset:offset];
149: *value = SWAPLONG( *access);
150: eieio();
151: return( noErr);
152: }
153:
154: - (IOReturn) configWriteLong:(IOPCIDevice *)device
155: offset:(UInt32)offset value:(UInt32)value
156: {
157: volatile UInt32 * access;
158:
159: access = [self setConfigAddress:device offset:offset];
160: *access = SWAPLONG( value);
161: eieio();
162: return( noErr);
163: }
164:
165: - getDeviceUnitStr:(IOPCIDevice *)device name:(char *)name maxLength:(int)len
166: {
167: UInt32 * regProp;
168: char unitStr[ 20 ];
169:
170: if( device->functionNum)
171: sprintf( unitStr, "%x,%x", device->deviceNum, device->functionNum );
172: else
173: sprintf( unitStr, "%x", device->deviceNum );
174: if( strlen( unitStr) < len) {
175: strcpy( name, unitStr);
176: return( self);
177: }
178: // failed
179: return( nil);
180: }
181:
182: - (IOReturn) mapRegisters:device
183: {
184: return( IO_R_SUCCESS);
185: }
186:
187: - (volatile UInt32 *) setConfigAddress:(IOPCIDevice *)device offset:(UInt32)offset;
188: {
189: if( parentBridge)
190: return( [parentBridge setConfigAddress:device offset:offset]);
191:
192: return( NULL);
193: }
194:
195: - (LogicalAddress) getIOAperture;
196: {
197: if( parentBridge)
198: return( [parentBridge getIOAperture]);
199:
200: return( NULL);
201: }
202:
203: @end
204:
205: @implementation IOMacRiscPCIBridge
206:
207: - registerLoudly
208: {
209: return( self);
210: }
211:
212: - (BOOL) isVCI
213: {
214: return( NO);
215: }
216:
217: - (IOReturn) mapRegisters:device
218: {
219: IOReturn err;
220: IORange realRanges[ 3 ];
221: IORange * range;
222: UInt32 i;
223: vm_address_t * logical;
224: static AddressCell ioAddrCell = { 0, 0, 0, 0, kPCIIOSpace,
225: 0, 0, 0, 0, 0, 0, 0, 0 };
226: UInt32 ioPhys;
227:
228: // Look for our IO memory aperture
229: err = [self resolveAddressCell:(UInt32 *)&ioAddrCell
230: physicalAddress:(PhysicalAddress *)&ioPhys];
231: if( err)
232: return( err);
233:
234: range = realRanges;
235: range->start = ioPhys + 0x00800000; // config addr
236: range->size = 0x1000;
237: range++;
238: range->start = ioPhys + 0x00c00000; // config data
239: range->size = 0x1000;
240: range++;
241:
242: if( NO == [self isVCI]) {
243: range->start = ioPhys;
244: range->size = 0x10000; // 64K of non-reloc I/O access !!
245: range++;
246: }
247:
248: [device setMemoryRangeList:0 num:0];
249: err = [device setMemoryRangeList:realRanges num:(range - realRanges)];
250: if( err)
251: return( err);
252:
253: range = realRanges;
254: logical = (vm_address_t *) &configAddr;
255: for( i = 0; i < [device numMemoryRanges]; i++, logical++, range++ ) {
256:
257: err = [self mapMemoryRange:i to:logical findSpace:YES cache:IO_CacheOff];
258: INFO( "Phys %x = Virt %x\n", range->start, *logical);
259:
260: if( err) {
261: IOLog( "%s: mapMemoryRange failed", [self name]);
262: break;
263: }
264: }
265: return( err);
266: }
267:
268: - (volatile UInt32 *) setConfigAddress:(IOPCIDevice *)device offset:(UInt32)offset
269: {
270: UInt32 addrCycle;
271:
272: if( device->busNum == primaryBus) {
273: // primary config cycle
274: addrCycle = SWAPLONG(( (1 << device->deviceNum)
275: | (device->functionNum << 8)
276: | (offset & 0xfc) ));
277:
278: } else {
279: // pass thru config cycle
280: addrCycle = SWAPLONG(( (device->busNum << 16)
281: | (device->deviceNum << 11)
282: | (device->functionNum << 8)
283: | (offset & 0xfc)
284: | 1 ));
285: }
286:
287: while( *configAddr != addrCycle) {
288: (*configAddr) = addrCycle;
289: eieio();
290: }
291:
292: return( configData);
293: }
294:
295: - (LogicalAddress) getIOAperture
296: {
297: return( (LogicalAddress) ioAperture); // zero on VCI
298: }
299:
300: @end
301:
302: @implementation IOMacRiscVCIBridge
303:
304: - (BOOL) isVCI
305: {
306: return( YES);
307: }
308:
309: @end
310:
311: @implementation IOGracklePCIBridge
312:
313: - (IOReturn) mapRegisters:device
314: {
315: IOReturn err;
316: IORange realRanges[ 3 ];
317: IORange * range;
318: UInt32 i;
319: vm_address_t * logical;
320: static AddressCell ioAddrCell = { 0, 0, 0, 0, kPCIIOSpace,
321: 0, 0, 0, 0, 0, 0, 0, 0 };
322: UInt32 ioPhys;
323:
324: // Look for our IO memory aperture
325: err = [self resolveAddressCell:(UInt32 *)&ioAddrCell
326: physicalAddress:(PhysicalAddress *)&ioPhys];
327: if( err)
328: return( err);
329:
330: range = realRanges;
331: range->start = ioPhys + 0x00c00000; // config addr
332: range->size = 0x1000;
333: range++;
334: range->start = ioPhys + 0x00e00000; // config data
335: range->size = 0x1000;
336: range++;
337: range->start = ioPhys;
338: range->size = 0x10000; // 64K of non-reloc I/O access !!
339: range++;
340:
341: [device setMemoryRangeList:0 num:0];
342: err = [device setMemoryRangeList:realRanges num:3];
343: if( err)
344: return( err);
345:
346: range = realRanges;
347: logical = (vm_address_t *) &configAddr;
348: for( i = 0; i < 3; i++, logical++, range++ ) {
349:
350: err = [self mapMemoryRange:i to:logical findSpace:YES cache:IO_CacheOff];
351: INFO( "Phys %x = Virt %x\n", range->start, *logical);
352:
353: if( err) {
354: IOLog( "%s: mapMemoryRange failed", [self name]);
355: break;
356: }
357: }
358: return( err);
359: }
360:
361: - (volatile UInt32 *) setConfigAddress:(IOPCIDevice *)device offset:(UInt32)offset
362: {
363: *configAddr = (SWAPLONG(( (0x80000000)
364: | (device->busNum << 16)
365: | (device->deviceNum << 11)
366: | (device->functionNum << 8)
367: | (offset & 0xfc))));
368: eieio();
369: return( configData);
370: }
371:
372: - (LogicalAddress) getIOAperture
373: {
374: return( (LogicalAddress) ioAperture);
375: }
376:
377: @end
378:
379:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.